diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..18d2ab79 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,10 @@ +.git +.VSCodeCounter +.nyc_output +.archive +.vscode +.angular +node_modules +reports +build +dist \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..65b51509 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,55 @@ +{ + "root": true, + "ignorePatterns": [ + "projects/**/*" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "lib", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "lib", + "style": "kebab-case" + } + ] + } + }, + { + "files": [ + "*.html" + ], + "extends": [ + "plugin:@angular-eslint/template/recommended", + "plugin:@angular-eslint/template/accessibility" + ], + "rules": {} + }, + { + "files": [ + "*.ts" + ], + "extends": [ + "plugin:@ngrx/recommended" + ] + } + ] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..583237fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,53 @@ +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +**/bin +**/obj +./aas-server/users +./aas-server/test/users +nginx +*.user +*.log +*.~dx +node_modules +build +dist +coverage +**/users +mongo-volume + +# Miscellaneous +.angular +.sass-cache/9 +connect.lock +coverage +libpeerconnection.log +testem.log +typings +./aas-server-config.json +reports +.nyc_output +temp +*-audit.json +swagger.json +swagger.yaml +projects/aas-server/src/app/routes + +# System files +.DS_Store +Thumbs.db +.VSCodeCounter diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..cf24188f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,87 @@ +stages: + - tag + - build + - test + - deploy + +tag: + image: node:18.10 + stage: tag + rules: + - if: '$CI_COMMIT_MESSAGE !~ /(Release)/' + script: + - npm install @semantic-release/gitlab -D + - npm install @semantic-release/git -D + - npx semantic-release + +build: + image: node:lts-alpine3.16 + stage: build + rules: + - if: '$CI_COMMIT_MESSAGE =~ /(Release)/' + script: + - npm ci + - npm run build -ws + +test: + image: node:lts-alpine3.16 + stage: test + rules: + - if: '$CI_COMMIT_MESSAGE =~ /(Release)/' + script: + - apk add --no-cache chromium && export CHROME_BIN='/usr/bin/chromium-browser' + - npm ci + - npm run build -ws + - npm run test -ws + - npm run coverage + coverage: '/Lines \W+: (\d+\.\d+)%.*/' + artifacts: + paths: + - reports/aas-portal.xml + - reports/aas-server.xml + - reports/common.xml + reports: + junit: [reports/aas-portal.xml, reports/aas-server.xml, reports/common.xml] + coverage_report: + coverage_format: cobertura + path: reports/**/cobertura-coverage.xml + +deploy_aas-server-app: + stage: deploy + only: + refs: + - development + - main + variables: + - $CI_COMMIT_MESSAGE =~ /(Release)/ + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - mkdir -p /kaniko/.docker + - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json + - >- + /kaniko/executor + --context "${CI_PROJECT_DIR}" + --dockerfile "${CI_PROJECT_DIR}/Dockerfile.aas-server" + --destination "${CI_REGISTRY_IMAGE}:node.${CI_COMMIT_BRANCH}" + +deploy_aas-web-app: + stage: deploy + only: + refs: + - development + - main + variables: + - $CI_COMMIT_MESSAGE =~ /(Release)/ + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - mkdir -p /kaniko/.docker + - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json + - >- + /kaniko/executor + --context "${CI_PROJECT_DIR}" + --dockerfile "${CI_PROJECT_DIR}/Dockerfile.aas-portal" + --destination "${CI_REGISTRY_IMAGE}:nginx.${CI_COMMIT_BRANCH}" diff --git a/.releaserc.yml b/.releaserc.yml new file mode 100644 index 00000000..685a7705 --- /dev/null +++ b/.releaserc.yml @@ -0,0 +1,17 @@ +{ + "branches": ["main", "development"], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + ["@semantic-release/npm", { + "npmPublish": false + }], + ["@semantic-release/gitlab", { + "gitlabUrl": "https://gitlab.cc-asp.fraunhofer.de/" + }], + ["@semantic-release/git", { + "assets": ["package.json"], + "message": "chore(Release): ${nextRelease.version}\n\n${nextRelease.notes}" + }] + ] +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..77b37457 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 + "recommendations": ["angular.ng-template"] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..ac098620 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,93 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Start aas-portal", + "type": "chrome", + "request": "launch", + "preLaunchTask": "start", + "url": "http://localhost:4200/", + "webRoot": "${workspaceFolder}" + }, + { + "name": "Start aas-server", + "type": "node", + "request": "launch", + "preLaunchTask": "build-aas-server", + "program": "${workspaceFolder}/projects/aas-server/build/aas-server.js", + "cwd": "${workspaceFolder}", + "outFiles": [ + "${workspaceFolder}/projects/aas-server/build/**/*.js" + ], + "skipFiles": [ + "/**" + ], + "env": { + "NODE_ENV": "development", + "NODE_SERVER_PORT": "1337", + "CONTENT_ROOT": "projects/aas-server/build", + "WEB_ROOT": "projects/aas-portal/dist", + "ASSETS": "projects/aas-server/src/assets", + "ENDPOINTS": "[\"file:///samples?name=Samples\"]" + } + }, + { + "name": "Run aas-server", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/projects/aas-server/dist/aas-server.js", + "cwd": "${workspaceFolder}", + "skipFiles": [ + "/**" + ], + "env": { + "NODE_ENV": "development", + "NODE_SERVER_PORT": "1337", + "CONTENT_ROOT": "projects/aas-server/dist", + "WEB_ROOT": "projects/aas-portal/dist", + "ASSETS": "projects/aas-server/src/assets", + "ENDPOINTS": "[\"file:///samples?name=Samples\"]" + } + }, + { + "name": "Test aas-portal", + "type": "chrome", + "request": "launch", + "preLaunchTask": "test", + "url": "http://localhost:9876/debug.html", + }, + { + "name": "Test aas-lib", + "type": "chrome", + "request": "launch", + "preLaunchTask": "test-aas-lib", + "url": "http://localhost:9876/debug.html", + }, + { + "name": "Test aas-server", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run-script", + "test:debug", + "-w", + "aas-server" + ], + }, + { + "name": "Test common", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}", + "runtimeExecutable": "npm", + "runtimeArgs": [ + "run-script", + "test", + "-w", + "common" + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..79b78ec9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,37 @@ +{ + "cSpell.words": [ + "aaslist", + "aasv3", + "angewandten", + "autohide", + "classname", + "eine", + "Einrichtung", + "Foerderung", + "Forschung", + "IDREF", + "IDREFS", + "IOSB", + "irdi", + "jszip", + "lcid", + "Lemgo", + "maxsize", + "metainformation", + "metamodel", + "nicht", + "NMTOKEN", + "NMTOKENS", + "preprocessors", + "Qualifiable", + "rechtlich", + "selbstaendige", + "submodel", + "tsoa", + "tsyringe", + "Ungroup", + "uuid", + "xmldoc", + "ZVEI" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..0234a9da --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,77 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "start", + "command": "npm", + "args": ["run", "serve", "-w", "aas-portal"], + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + }, + { + "type": "shell", + "label": "test", + "command": "npm", + "args": ["run", "test", "-w", "aas-portal"], + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + }, + { + "label": "build-aas-server", + "type": "typescript", + "tsconfig": "projects/aas-server/tsconfig.app.json", + "problemMatcher": [ + "$tsc" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "shell", + "label": "test-aas-lib", + "command": "npm", + "args": ["run", "test", "-w", "aas-lib"], + "isBackground": true, + "problemMatcher": { + "owner": "typescript", + "pattern": "$tsc", + "background": { + "activeOnStart": true, + "beginsPattern": { + "regexp": "(.*?)" + }, + "endsPattern": { + "regexp": "bundle generation complete" + } + } + } + } + ] +} \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..c8df2cc9 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,135 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people + +* Being respectful of differing opinions, viewpoints, and experiences + +* Giving and gracefully accepting constructive feedback + +* Accepting responsibility and apologizing to those affected by our mistakes, +and learning from the experience + +* Focusing on what is best not just for us as individuals, but for the +overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or +advances of any kind + +* Trolling, insulting or derogatory comments, and personal or political attacks + +* Public or private harassment + +* Publishing others' private information, such as a physical or email +address, without their explicit permission + +* Other conduct which could reasonably be considered inappropriate in a +professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at aasportal@iosb-ina.fraunhofer.de. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. + +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..b3f5a350 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,24 @@ +Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions are **greatly appreciated**. + +If you have a suggestion for improvements, please fork the repo and create a pull request. You can also simply open an issue. +Don't forget to rate the project! Thanks again! + +1. Fork the Project +2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) +3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) +4. Push to the Branch (`git push origin feature/AmazingFeature`) +5. Open a Pull Request + +### Code Formatting +The project uses *spotless:check* in the build cycle, which means the project only compiles if all code, *.pom and *.xml files are formatted according to the project's codestyle definitions (see details on [spotless](https://github.com/diffplug/spotless)). +You can automatically format your code by running + +> mvn spotless:apply + +Additionally, you can import the eclipse formatting rules defined in */codestyle* into our IDE. + +### Third Party License +If you use additional dependencies please be sure that the licenses of these dependencies are compliant with our [License](#license). If you are not sure which license your dependencies have, you can run +> mvn license:aggregate-third-party-report + +and check the generated report in the directory `documentation/third_party_licenses_report.html`. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..a538946e --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +# Dockerfile to build server and client parts +FROM node:lts-alpine3.16 as build +WORKDIR /usr/src/app +COPY . . +RUN npm install -w=aas-server -w=aas-portal +RUN node create-app-info.js +RUN npm run build + +FROM node:lts-alpine3.16 as aas-server-app +RUN apk upgrade --update-cache --available && apk add openssl && rm -rf /var/cache/apk/* +WORKDIR /usr/src/app +COPY package.json package.json +COPY projects/aas-server/package.json projects/aas-server/package.json +COPY --from=build /usr/src/app/projects/aas-server/dist/ /usr/src/app/ +COPY --from=build /usr/src/app/projects/aas-server/app-info.json /usr/src/app/app-info.json +COPY --from=build /usr/src/app/projects/common/dist/ /usr/src/app/node_modules/common/dist/ +COPY --from=build /usr/src/app/projects/common/package.json /usr/src/app/node_modules/common/package.json +COPY --from=build /usr/src/app/projects/aas-portal/dist/ /usr/src/app/wwwroot +RUN npm install -w=aas-server --omit=dev +COPY projects/aas-server/src/assets assets/ +ENV NODE_LOG=./log/debug.log +ENV NODE_SERVER_PORT=80 +ENV ENDPOINTS=["\"file:///samples?name=Samples\""] +ENV NODE_ENV=production + +EXPOSE 80 +CMD ["node", "aas-server.js" ] diff --git a/Dockerfile.aas-portal b/Dockerfile.aas-portal new file mode 100644 index 00000000..e1178103 --- /dev/null +++ b/Dockerfile.aas-portal @@ -0,0 +1,11 @@ +# Dockerfile to build server and client parts +FROM node:lts-alpine3.16 as build +WORKDIR /usr/src/app +COPY . . +RUN npm ci -w=aas-portal +RUN npm run aas-portal:build + +FROM nginx:latest as aas-portal +COPY --from=build /usr/src/app/projects/aas-portal/dist/ /usr/share/nginx/html/ +COPY --from=build /usr/src/app/projects/aas-portal/nginx.conf /etc/nginx/nginx.conf +EXPOSE 80 diff --git a/Dockerfile.aas-server b/Dockerfile.aas-server new file mode 100644 index 00000000..c9a385c0 --- /dev/null +++ b/Dockerfile.aas-server @@ -0,0 +1,28 @@ +# Dockerfile to build server and client parts +FROM node:lts-alpine3.16 as build +WORKDIR /usr/src/app +COPY . . +RUN npm install -w=aas-server +RUN node create-app-info.js +RUN npm run aas-server:build + +FROM node:lts-alpine3.16 as aas-server-app +RUN apk upgrade --update-cache --available && apk add openssl && rm -rf /var/cache/apk/* +WORKDIR /usr/src/app +COPY package.json package.json +COPY projects/aas-server/package.json projects/aas-server/package.json +COPY --from=build /usr/src/app/projects/aas-server/dist/ /usr/src/app/ +COPY --from=build /usr/src/app/projects/aas-server/app-info.json /usr/src/app/app-info.json +COPY --from=build /usr/src/app/projects/common/dist/ /usr/src/app/node_modules/common/dist/ +COPY --from=build /usr/src/app/projects/common/package.json /usr/src/app/node_modules/common/package.json +RUN npm install -w=aas-server --omit=dev +COPY projects/aas-server/src/assets assets/ +ENV NODE_LOG=./log/debug.log +ENV NODE_SERVER_PORT=1337 +ENV USER_STORAGE=mongodb://172.16.160.178:27017/aasportal-users +ENV ENDPOINTS=["\"file:///samples?name=Samples\""] +ENV NODE_ENV=production + +EXPOSE 1337 +EXPOSE 1338 +CMD ["node", "aas-server.js" ] diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d215ab64 --- /dev/null +++ b/LICENSE @@ -0,0 +1,203 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + zur Foerderung der angewandten Forschung e.V. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index e69de29b..646a4dfa 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,69 @@ +# AASPortal [![Documentation Status](https://readthedocs.org/projects/fpethig-rtd-tutorial/badge/?version=latest "Documentation Status")](https://fpethig-rtd-tutorial.readthedocs.io/en/latest/?badge=latest) + +![AASPortal Logo <](./docs/source/images/AASPortal_mid.png "AASPortal Logo") + +**AASPortal** is a Node.js based web portal for the visualization and management of Asset Administration Shells (AAS). The implementation uses the concepts of the document "Details of the Asset Administration Shell" published on https://www.plattform-i40.de and licensed under Creative Commons CC BY 4.0. + +Check out the [Getting Started](./docs/source/gettingstarted.md) section to learn how to setup Visual Studio Code and start using and developing the *AASPortal*. Learn more about the [Architecture](./docs/source/architecture.md) of *AASPortal*, and check out the [Usage](./docs/source/usage.md) section to learn about available search filters for AAS and which Endpoints can be connected to the *AASPortal*. + +For more details about the AASPortal see the full documentation :blue_book: [here](https://fpethig-rtd-tutorial.readthedocs.io/en/latest/?badge=latest). + +**AASPortal is under active development and we are looking forward to your active contributions!** + +## Prerequisites +- Visual Studio Code +- Node.js v18.10.0 +- GIT 2.36.0.windows.1 +- Docker Desktop 4.x + +## Getting Started +You can find a detailed documentation :blue_book: [here](https://fpethig-rtd-tutorial.readthedocs.io/) + +## Usage + +### Setup Visual Studio Code +The preferred development environment is Visual Studio Code. Clone *AASPortal*'s GIT repository. Open aasportal in Visual Studio Code. In a terminal window execute the the following commands: + +`npm install` + +and + +`npm run build -ws` + +restart Visual Studio Code. + +### Start AASPortal +The following command creates and executes a Docker image: + +`npm run start` + +Go to: + + http://localhost/ + +## Changelog + +You can find the detailed changelog [here](docs/source/changelog/changelog.md). + +## Roadmap + +## Contributors + +| Name | Github Account | +| :------------------ | ----------------------------------------------------------- | +| Ralf Aron | [ralfaron](https://github.com/ralfaron) | +| Alexander Wollbrink | [AlexanderWollbrink](https://github.com/AlexanderWollbrink) | +| Juilee Tikekar | [juileetikekar](https://github.com/juileetikekar) | +| Florian Pethig | [fpethig](https://github.com/fpethig) | + +## Contact + +aasportal@iosb-ina.fraunhofer.de + +## License + +Distributed under the Apache 2.0 License. See `LICENSE` for more information. + +Copyright (C) 2023, Fraunhofer IOSB-INA Lemgo, eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Germany + +You should have received a copy of the Apache 2.0 License along with this program. If not, see https://www.apache.org/licenses/LICENSE-2.0.html. diff --git a/aasportal.mdx b/aasportal.mdx new file mode 100644 index 00000000..2a7c44b3 --- /dev/null +++ b/aasportal.mdx @@ -0,0 +1,5529 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Requirement Model + requirementModel + 1 + + + Use Case Model + usecaseModel + 2 + + + Analysis Model + analysisModel + 3 + + + Design Model + designModel + 4 + + + Implementation Model + implementationModel + 5 + + + Deployment Model + deploymentModel + 6 + + + Main + 1 + + + Main + 1 + + + Main + 1 + + + aasportal + 1 + + + aas-server + workspace + + + main + 1 + + + {"bounds": "487,157,107,70","model": "lUNC+bF3k0CvtsFIiXav0g","name": "aas-server","render": [{"bounds": "487,157,107,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "492,186,97,16","text": "<<workspace>>","type": "Text"},{"bounds": "510,202,61,16","text": "aas-server","type": "Text"}],"type": "UMLPackageView"} + 449,101,107,70 + + + common + workspace + 3 + + + {"bounds": "297,337,107,70","model": "09ZDFMDrFUyf7OuCrLmopQ","name": "common","render": [{"bounds": "297,337,107,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "302,366,97,16","text": "<<workspace>>","type": "Text"},{"bounds": "326,382,49,16","text": "common","type": "Text"}],"type": "UMLPackageView"} + 259,281,107,70 + + + session-use-cases + + + register new user + 1 + + + {"bounds": "761,212,143,63","model": "DdObMY0LiEGg9I7B7sPwdQ","name": "register new user","render": [{"bounds": "783,262,99,13","fontStyle": "2","text": "register new user","type": "Text"},{"bounds": "783,212,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 761,212,143,63 + + + login + 2 + + + {"bounds": "271,112,80,63","model": "M7dYKbSchUCEGE8AuF0fFw","name": "login","render": [{"bounds": "298,162,27,13","fontStyle": "2","text": "login","type": "Text"},{"bounds": "271,116,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 271,112,80,63 + + + logout + 3 + + + {"bounds": "371,201,80,63","model": "QMF5KkzEg0mS7miR8nBWNw","name": "logout","render": [{"bounds": "393,251,36,13","fontStyle": "2","text": "logout","type": "Text"},{"bounds": "371,205,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 371,201,80,63 + + + update user profile + 4 + + + {"bounds": "291,302,155,63","model": "JgBbS2UjyUaKQk38U0BNEw","name": "update user profile","render": [{"bounds": "315,352,107,13","fontStyle": "2","text": "update user profile","type": "Text"},{"bounds": "319,302,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 291,302,155,63 + + + reset password + 5 + + + {"bounds": "405,422,124,63","model": "pGD8+2SnkEuhaK0mkqxwQA","name": "reset password","render": [{"bounds": "424,472,87,13","fontStyle": "2","text": "reset password","type": "Text"},{"bounds": "417,422,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 405,422,124,63 + + + {"model": "xj+ji/nryE2ZkJDv/6JEXg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "441,422,393,364,","type": "Line"},{"bounds": "393,355,16,18","path": ":/images/dummy/arrow.svg","rotate": "-396","type": "EdgeEnd"},{"bounds": "440,390,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 441,422,393,364, + + + true + false + 387,397,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 440,390,66,13 + 17 + -38,41 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + start-use-cases + + + guest + + + {"bounds": "78,213,46,108","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "85,308,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "80,213,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 78,213,46,108 + + + select AAS workspace + 1 + + + {"bounds": "311,102,179,63","model": "EaqDS7t/ZkKZJrIytAecKg","name": "select AAS workspace","render": [{"bounds": "339,152,124,13","fontStyle": "2","text": "select AAS workspace","type": "Text"},{"bounds": "351,102,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 311,102,179,63 + + + {"model": "vhkL4v28QU6/jfm+UEWrMw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,256,330,164,","type": "Line"},{"bounds": "330,155,16,18","path": ":/images/dummy/arrow.svg","rotate": "660","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,256,330,164, + + + true + false + 203,190,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 168,177,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + system + 1 + + + {"bounds": "926,292,57,108","model": "uuP9Ld4epE2kxnEypWRjqw","name": "system","render": [{"bounds": "934,387,42,13","fontStyle": "2","text": "system","type": "Text"},{"bounds": "933,292,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 926,292,57,108 + + + display available AAS workspaces + 2 + + + {"bounds": "494,369,275,63","model": "pXHJ0E8Mm0ihm9ChxE2uhw","name": "display available AAS workspaces","render": [{"bounds": "537,419,190,13","fontStyle": "2","text": "display available AAS workspaces","type": "Text"},{"bounds": "582,369,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 494,369,275,63 + + + {"model": "yZ36x/0iGkqQwmOkCVOjew","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "926,350,768,377,","type": "Line"},{"bounds": "768,368,16,18","path": ":/images/dummy/arrow.svg","rotate": "-996","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 926,350,768,377, + + + true + false + 832,373,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 805,388,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + filter AAS collection + 3 + + + {"bounds": "291,212,162,63","model": "DdxpordBCUadHgIiC8bfiw","name": "filter AAS collection","render": [{"bounds": "317,262,110,13","fontStyle": "2","text": "filter AAS collection","type": "Text"},{"bounds": "322,212,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 291,212,162,63 + + + {"model": "swNLVSNKDUi+arKWAyUZ1w","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,264,291,250,","type": "Line"},{"bounds": "291,241,16,18","path": ":/images/dummy/arrow.svg","rotate": "852","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,264,291,250, + + + true + false + 188,236,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 158,221,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + sort AAS collection + 4 + + + {"bounds": "279,314,154,63","model": "gF8hNfqTE0+tnIiYevmzjw","name": "sort AAS collection","render": [{"bounds": "303,364,106,13","fontStyle": "2","text": "sort AAS collection","type": "Text"},{"bounds": "306,314,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 279,314,154,63 + + + {"model": "0Srgpff+YkOmLs0tKM+AMQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,273,279,321,","type": "Line"},{"bounds": "279,312,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2528","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,273,279,321, + + + true + false + 187,277,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 163,262,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + open AAS + 5 + + + {"bounds": "291,412,96,99","model": "tOGbG7+tyEytf9xSF7q+qQ","name": "open AAS","render": [{"bounds": "312,498,54,13","fontStyle": "2","text": "open AAS","type": "Text"},{"bounds": "291,430,96,44","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 291,412,96,99 + + + {"model": "kmR3l0u9vE+2Vecw5AvgCw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,285,291,423,","type": "Line"},{"bounds": "291,414,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2305","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,285,291,423, + + + true + false + 199,336,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 179,325,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + display AAS collection of selected workspace + 6 + + + {"bounds": "471,235,365,63","model": "aolN93DVKUukGbJvNGeAIg","name": "display AAS collection of selected workspace","render": [{"bounds": "528,285,252,13","fontStyle": "2","text": "display AAS collection of selected workspace","type": "Text"},{"bounds": "604,235,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 471,235,365,63 + + + {"model": "NlmI/WGUbkidNxKN+w7cJw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "926,338,771,297,","type": "Line"},{"bounds": "771,288,16,18","path": ":/images/dummy/arrow.svg","rotate": "-751","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 926,338,771,297, + + + true + false + 827,327,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 794,341,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "IQdHY/lZKkmktdThU0r7GQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "594,235,459,164,","type": "Line"},{"bounds": "459,155,16,18","path": ":/images/dummy/arrow.svg","rotate": "-622","type": "EdgeEnd"},{"bounds": "480,221,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 594,235,459,164, + + + true + false + 502,207,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 480,221,66,13 + 17 + 0,-30 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + aas-use-cases + 14 + + + {"bounds": "78,129,46,108","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "85,224,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "80,129,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 78,129,46,108 + + + users + 4 + + + {"bounds": "308,166,105,70","model": "3rlR8jf5MEm3e8UUHSd2vQ","name": "users","render": [{"bounds": "308,166,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "348,204,26,13","text": "users","type": "Text"}],"type": "UMLPackageView"} + 308,166,105,70 + + + editor + 2 + + + {"bounds": "58,201,124,108","model": "+DszC4J/o0KpLHMfXSIcYA","name": "editor","render": [{"bounds": "103,296,34,13","fontStyle": "2","text": "editor","type": "Text"},{"bounds": "99,201,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 58,201,124,108 + + + {"bounds": "528,190,46,108","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "535,285,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "530,190,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 528,190,46,108 + + + users + 5 + + + {"bounds": "88,79,46,108","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "95,174,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "90,79,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 88,79,46,108 + + + {"bounds": "478,69,57,108","model": "uuP9Ld4epE2kxnEypWRjqw","name": "system","render": [{"bounds": "486,164,42,13","fontStyle": "2","text": "system","type": "Text"},{"bounds": "485,69,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 478,69,57,108 + + + {"bounds": "209,186,124,108","model": "+DszC4J/o0KpLHMfXSIcYA","name": "editor","render": [{"bounds": "254,281,34,13","fontStyle": "2","text": "editor","type": "Text"},{"bounds": "250,186,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 209,186,124,108 + + + {"model": "sXSaypz3t0qtFwsAkLOhsQ","name": "","render": [{"lineWidth": "0","points": "209,198,133,147,","type": "Line"},{"bounds": "133,135,17,24","path": ":/images/dummy/arrow_triangle.svg","rotate": "-561","type": "EdgeEnd"}],"type": "UMLGeneralizationView"} + 209,198,133,147, + + + true + false + 145,179,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 107,192,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "XfqaGlS1vkC7cLHXlv7l7Q","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "573,243,761,243,","type": "Line"},{"bounds": "761,234,16,18","path": ":/images/dummy/arrow.svg","rotate": "900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 573,243,761,243, + + + true + false + 649,222,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 620,207,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "RsAgw3llyki9/MEvSZ1wWQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "181,218,271,166,","type": "Line"},{"bounds": "271,157,16,18","path": ":/images/dummy/arrow.svg","rotate": "599","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 181,218,271,166, + + + true + false + 200,173,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 164,160,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "EYyk3cC17kSZ+wVn1GI5dg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "181,249,371,235,","type": "Line"},{"bounds": "371,226,16,18","path": ":/images/dummy/arrow.svg","rotate": "857","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 181,249,371,235, + + + true + false + 257,221,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 227,206,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "M2SEBHf540y7cz8kTrXlNg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "181,274,291,309,","type": "Line"},{"bounds": "291,300,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2523","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 181,274,291,309, + + + true + false + 223,272,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 198,257,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + display AAS document + 13 + + + {"bounds": "721,213,181,63","model": "YpsseLqn1k+Wm2au4XUHtQ","name": "display AAS document","render": [{"bounds": "749,263,126,13","fontStyle": "2","text": "display AAS document","type": "Text"},{"bounds": "762,213,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 721,213,181,63 + + + {"bounds": "978,191,57,108","model": "uuP9Ld4epE2kxnEypWRjqw","name": "system","render": [{"bounds": "986,286,42,13","fontStyle": "2","text": "system","type": "Text"},{"bounds": "985,191,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 978,191,57,108 + + + {"model": "tsKS5euIUEuAW83hLtFAnA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "978,244,901,244,","type": "Line"},{"bounds": "901,235,16,18","path": ":/images/dummy/arrow.svg","rotate": "-900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 978,244,901,244, + + + true + false + 922,253,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 893,268,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + browse AAS document + 12 + + + {"bounds": "291,53,183,63","model": "t9RwiPtbu0iHErjDUGZ6QQ","name": "browse AAS document","render": [{"bounds": "319,103,127,13","fontStyle": "2","text": "browse AAS document","type": "Text"},{"bounds": "333,53,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 291,53,183,63 + + + {"model": "DgjGDeSz+EuGTetwPCNChA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,174,293,115,","type": "Line"},{"bounds": "293,106,16,18","path": ":/images/dummy/arrow.svg","rotate": "708","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,174,293,115, + + + true + false + 185,125,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 151,111,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + add properties to dashbord + 11 + + + {"bounds": "337,141,253,63","model": "p+A/XqKhQE+sOWMonEqwOw","name": "add properties to dashbord","render": [{"bounds": "387,191,154,13","fontStyle": "2","text": "add properties to dashbord","type": "Text"},{"bounds": "414,141,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 337,141,253,63 + + + monitor properties here + 10 + + + {"bounds": "230,226,195,63","model": "jctBX3v/h0mwPBSmIu1a9A","name": "monitor properties here","render": [{"bounds": "260,276,136,13","fontStyle": "2","text": "monitor properties here","type": "Text"},{"bounds": "278,226,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 230,226,195,63 + + + {"model": "dEb7jQxw+0WQ6sxxf0jVPQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,181,337,175,","type": "Line"},{"bounds": "337,166,16,18","path": ":/images/dummy/arrow.svg","rotate": "883","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,181,337,175, + + + true + false + 212,157,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 182,142,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "jIvXhNvND02wDoORWSbp8g","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,190,233,226,","type": "Line"},{"bounds": "233,217,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2518","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,190,233,226, + + + true + false + 165,188,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 140,173,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + switch to online + 9 + + + switch to offline + 8 + + + navigate to dashboard + 7 + + + About + 2 + + + dashboard-use-cases + + + about-use-cases + 3 + + + common + 10 + + + {"bounds": "108,286,105,70","model": "h88sdLXLCEqfOx76khYx5g","name": "common","render": [{"bounds": "108,286,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "141,324,39,13","text": "common","type": "Text"}],"type": "UMLPackageView"} + 108,286,105,70 + + + aas-portal + 11 + + + {"bounds": "108,166,105,70","model": "EbGjZANjqkG09IY0dom9fg","name": "aas-portal","render": [{"bounds": "108,166,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "136,204,49,13","text": "aas-portal","type": "Text"}],"type": "UMLPackageView"} + 108,166,105,70 + + + common-use-cases + 5 + + + {"model": "/ZYAdPxlm023Y8SVls1Btg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "160,235,160,286,","type": "Line"},{"bounds": "160,277,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1800","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 160,235,160,286, + + + true + false + 157,255,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 143,255,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + get 3rd-party libraries + 2 + + + {"bounds": "252,259,242,63","model": "IvSl7JRuUUqLFHz+HvjjDQ","name": "get 3rd-party libraries","render": [{"bounds": "310,309,126,13","fontStyle": "2","text": "get 3rd-party libraries","type": "Text"},{"bounds": "323,259,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 252,259,242,63 + + + get AASServer messages + 1 + + + {"bounds": "371,156,172,63","model": "lqY8aVKmw0y8fbPhvmf2FA","name": "get AASServer messages","render": [{"bounds": "386,206,143,13","fontStyle": "2","text": "get AASServer messages","type": "Text"},{"bounds": "407,156,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 371,156,172,63 + + + {"bounds": "228,260,46,108","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "235,355,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "230,260,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 228,260,46,108 + + + admin + 6 + + + {"bounds": "88,313,54,108","model": "WPMuxGNrUkS0AauS7eN3NA","name": "admin","render": [{"bounds": "98,408,35,13","fontStyle": "2","text": "admin","type": "Text"},{"bounds": "94,313,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 88,313,54,108 + + + {"model": "Hc2Q1KH6uEWs43I6EuL1Mg","name": "","render": [{"lineWidth": "0","points": "141,344,209,289,","type": "Line"},{"bounds": "209,277,17,24","path": ":/images/dummy/arrow_triangle.svg","rotate": "510","type": "EdgeEnd"}],"type": "UMLGeneralizationView"} + 141,344,209,289, + + + true + false + 148,299,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 109,288,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + open data element + 6 + + + {"bounds": "190,322,174,63","model": "UHvIgpVgUkyB7ypdWLTrrg","name": "open data element","render": [{"bounds": "224,372,107,13","fontStyle": "2","text": "open data element","type": "Text"},{"bounds": "227,322,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 190,322,174,63 + + + view image + 5 + + + {"bounds": "553,322,93,63","model": "pGPG77AQmEW1E7uPDxtNEg","name": "view image","render": [{"bounds": "568,372,64,13","fontStyle": "2","text": "view image","type": "Text"},{"bounds": "553,323,93,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 553,322,93,63 + + + open URL + 4 + + + {"bounds": "140,452,80,63","model": "qXen9hrFQEOK5799DD3YWw","name": "open URL","render": [{"bounds": "154,502,53,13","fontStyle": "2","text": "open URL","type": "Text"},{"bounds": "140,456,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 140,452,80,63 + + + open known + 3 + + + {"model": "MJMBT5+zzUeia5Dls2NWXA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,204,244,322,","type": "Line"},{"bounds": "244,313,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2257","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,204,244,322, + + + true + false + 176,246,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 158,236,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "BsJKNykUdkWHgDdLnVNc9g","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "553,353,363,353,","type": "Line"},{"bounds": "363,344,16,18","path": ":/images/dummy/arrow.svg","rotate": "-900","type": "EdgeEnd"},{"bounds": "441,329,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 553,353,363,353, + + + true + false + 440,362,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 441,329,66,13 + 17 + -16,18 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "rpGf+n7+S0mBR0a1Dbx50Q","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "202,452,253,384,","type": "Line"},{"bounds": "253,375,16,18","path": ":/images/dummy/arrow.svg","rotate": "368","type": "EdgeEnd"},{"bounds": "186,428,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 202,452,253,384, + + + true + false + 198,403,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 186,428,66,13 + 17 + -18,2 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + play video + 2 + + + {"bounds": "314,492,83,63","model": "/1cxOYtCSUGDxKgr0nVt2g","name": "play video","render": [{"bounds": "327,542,58,13","fontStyle": "2","text": "play video","type": "Text"},{"bounds": "314,495,83,38","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 314,492,83,63 + + + open AAS document + 1 + + + {"bounds": "393,396,164,63","model": "MvB9Ida8kE21GDxeZNdFZQ","name": "open AAS document","render": [{"bounds": "418,446,114,13","fontStyle": "2","text": "open AAS document","type": "Text"},{"bounds": "425,396,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 393,396,164,63 + + + {"model": "O7JyRlGrh02mpWycvJeXfQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "393,397,358,384,","type": "Line"},{"bounds": "358,375,16,18","path": ":/images/dummy/arrow.svg","rotate": "-696","type": "EdgeEnd"},{"bounds": "333,413,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 393,397,358,384, + + + true + false + 353,399,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 333,413,66,13 + 17 + 0,-30 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "qjQnPHuW4UWCoV5f4abh9g","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "341,492,290,384,","type": "Line"},{"bounds": "290,375,16,18","path": ":/images/dummy/arrow.svg","rotate": "-252","type": "EdgeEnd"},{"bounds": "256,445,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 341,492,290,384, + + + true + false + 284,438,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 256,445,66,13 + 17 + 0,-30 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + call operation + + + {"bounds": "44,372,112,63","model": "6UMlGnudj0C0JC9cz2hZ0Q","name": "call operation","render": [{"bounds": "62,422,77,13","fontStyle": "2","text": "call operation","type": "Text"},{"bounds": "50,372,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 44,372,112,63 + + + {"model": "xhRlO81BV0mlJlqvcgC58g","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "155,387,190,377,","type": "Line"},{"bounds": "190,368,16,18","path": ":/images/dummy/arrow.svg","rotate": "740","type": "EdgeEnd"},{"bounds": "132,347,66,13","text": "<<extend>>","type": "Text"}],"type": "UMLExtendView"} + 155,387,190,377, + + + true + false + 151,362,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 132,347,66,13 + 17 + 0,-30 + <<extend>> + 132 + <<extend>> + true + true + uml.onEditStereotype(view, model, text) + + + add endpoint + 7 + + + {"bounds": "347,560,107,63","model": "a9Xx8lx1VEyxAuc3AB5k4g","name": "add endpoint","render": [{"bounds": "364,610,74,13","fontStyle": "2","text": "add endpoint","type": "Text"},{"bounds": "351,560,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 347,560,107,63 + + + {"bounds": "39,590,124,108","model": "+DszC4J/o0KpLHMfXSIcYA","name": "editor","render": [{"bounds": "84,685,34,13","fontStyle": "2","text": "editor","type": "Text"},{"bounds": "80,590,41,91","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 39,590,124,108 + + + {"model": "sXSaypz3t0qtFwsAkLOhsQ","name": "","render": [{"lineWidth": "0","points": "100,590,100,320,","type": "Line"},{"bounds": "100,308,17,24","path": ":/images/dummy/arrow_triangle.svg","type": "EdgeEnd"}],"type": "UMLGeneralizationView"} + 100,590,100,320, + + + true + false + 67,449,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 23,449,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "o4MEbd/5VU68f32aU/UtBw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "162,632,347,600,","type": "Line"},{"bounds": "347,591,16,18","path": ":/images/dummy/arrow.svg","rotate": "801","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 162,632,347,600, + + + true + false + 234,595,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 203,580,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + remove endpoint + 8 + + + {"bounds": "368,662,138,63","model": "6IPU7oC1F0ul56NigwREgA","name": "remove endpoint","render": [{"bounds": "389,712,97,13","fontStyle": "2","text": "remove endpoint","type": "Text"},{"bounds": "387,662,99,46","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 368,662,138,63 + + + {"model": "Ht/HtcpSBkyppA8SmDoEIw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "162,652,368,683,","type": "Line"},{"bounds": "368,674,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2614","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 162,652,368,683, + + + true + false + 249,647,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 222,632,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + reset + 9 + + + {"bounds": "291,732,80,60","model": "cldJaiRWoEahN5GwO6J4zA","name": "reset","render": [{"bounds": "316,779,30,13","fontStyle": "2","text": "reset","type": "Text"},{"bounds": "291,734,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 291,732,80,60 + + + {"model": "MEnWOSJJNUOZGpngw4H3tA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "162,675,291,741,","type": "Line"},{"bounds": "291,732,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2429","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 162,675,291,741, + + + true + false + 216,689,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 194,675,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + PC, Tablet, Phone + web browser + 2 + + + {"border-color": "91,155,213,255","fill-color": "151,188,228,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "291,66,166,80","model": "YU49xadxiUm+XA2jmjG0IA","name": "PC, Tablet, Phone","render": [{"bounds": "291,66,166,80","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "325,95,94,13","text": "<<web browser>>","type": "Text"},{"bounds": "323,108,97,13","fontStyle": "2","text": "PC, Tablet, Phone","type": "Text"}],"type": "UMLNodeView"} + 291,66,166,80 + + + aas-web-app + docker container + 5 + + + {"fill-color": "255,255,255,255"} + {"bounds": "291,227,166,80","model": "99kwFUgB7EqpO13lxMSpzg","name": "aas-web-app","render": [{"bounds": "291,227,166,80","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "316,256,112,13","text": "<<docker container>>","type": "Text"},{"bounds": "335,269,74,13","fontStyle": "2","text": "aas-web-app","type": "Text"}],"type": "UMLNodeView"} + 291,227,166,80 + + + aas-server + node.js + 6 + + + {"bounds": "78,135,46,105","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "85,227,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "80,135,40,88","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 78,135,46,105 + + + {"model": "ZUfSsTFDOU+ruYt46/xhpg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,187,371,187,","type": "Line"},{"bounds": "371,178,16,18","path": ":/images/dummy/arrow.svg","rotate": "900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,187,371,187, + + + true + false + 229,166,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 200,151,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "jY1Mcx3+3k+Vi1pU8Qucfw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,196,290,259,","type": "Line"},{"bounds": "290,250,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2493","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,196,290,259, + + + true + false + 194,208,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 171,194,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + get application info + + + {"bounds": "311,62,124,60","model": "Ka/ii5ztp02RE0EffeU7dg","name": "get application info","render": [{"bounds": "319,109,108,13","fontStyle": "2","text": "get application info","type": "Text"},{"bounds": "326,62,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 311,62,124,60 + + + {"model": "UsCUMK7GKkynX6ovjVJUow","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "123,179,311,113,","type": "Line"},{"bounds": "311,104,16,18","path": ":/images/dummy/arrow.svg","rotate": "706","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 123,179,311,113, + + + true + false + 194,126,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 160,112,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "93MvxkRzIU6GeEx9uBKmyA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "503,226,386,337,","type": "Line"},{"bounds": "386,328,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1334","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 503,226,386,337, + + + true + false + 437,287,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 419,298,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + common + 5 + + + {"model": "M8ySx8TZlk6RyQIVYtyXCg","name": "","render": [{"lineWidth": "0","points": "373,145,373,227,","type": "Line"},{"bounds": "355,159,6,13","text": "*","type": "Text"},{"bounds": "358,198,6,13","text": "1","type": "Text"}],"type": "UMLAssociationView"} + 373,145,373,227, + + + true + false + 370,180,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 356,180,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 359,179,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + 355,159,6,13 + 16 + 20,15 + * + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 365,181,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 358,198,6,13 + 18 + 23,-12 + 1 + 132 + {toMultiplicity} + true + true + + + true + false + 366,146,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 366,216,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + AAS Registry + 6 + + + {"border-color": "255,192,0,255","fill-color": "255,213,129,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "247,576,122,75","model": "Ce0IHwmEc0GJgRaS0f712w","name": "AAS Registry","render": [{"bounds": "247,576,122,75","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "269,609,74,13","fontStyle": "2","text": "AAS Registry","type": "Text"}],"type": "UMLNodeView"} + 247,576,122,75 + + + OPC UA server + 7 + + + {"border-color": "255,192,0,255","fill-color": "255,213,129,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "404,576,129,75","model": "ZKBFgxgQOkiFwoGB3etLag","name": "OPC UA server","render": [{"bounds": "404,576,129,75","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "426,609,81,13","fontStyle": "2","text": "OPC UA server","type": "Text"}],"type": "UMLNodeView"} + 404,576,129,75 + + + local-file-system + 8 + + + file-system + 10 + + + {"border-color": "255,192,0,255","fill-color": "255,213,129,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "570,576,107,75","model": "RrvO/JZnaECmkQCP8q8nOw","name": "file-system","render": [{"bounds": "570,576,107,75","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "589,609,64,13","fontStyle": "2","text": "file-system","type": "Text"}],"type": "UMLNodeView"} + 570,576,107,75 + + + start-use-cases + + + {"bounds": "118,130,46,105","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "125,222,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "120,130,40,88","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 118,130,46,105 + + + {"bounds": "90,360,101,105","model": "+DszC4J/o0KpLHMfXSIcYA","name": "editor","render": [{"bounds": "124,452,34,13","fontStyle": "2","text": "editor","type": "Text"},{"bounds": "120,360,40,88","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 90,360,101,105 + + + {"model": "sXSaypz3t0qtFwsAkLOhsQ","name": "","render": [{"lineWidth": "0","points": "140,360,140,234,","type": "Line"},{"bounds": "140,222,17,24","path": ":/images/dummy/arrow_triangle.svg","type": "EdgeEnd"}],"type": "UMLGeneralizationView"} + 140,360,140,234, + + + true + false + 107,291,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 63,291,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + monitor AAS + 6 + + + add AAS Registry + 7 + + + {"bounds": "417,301,191,60","model": "tsfmEHDL10GunHtcbZi4Tw","name": "add AAS Registry","render": [{"bounds": "464,348,98,13","fontStyle": "2","text": "add AAS Registry","type": "Text"},{"bounds": "466,301,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 417,301,191,60 + + + open AAS + 8 + + + {"bounds": "321,93,80,60","model": "sQg+1zjZLEC0V2IYtIqZmg","name": "open AAS","render": [{"bounds": "334,140,54,13","fontStyle": "2","text": "open AAS","type": "Text"},{"bounds": "321,95,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 321,93,80,60 + + + {"model": "3sS5kKrQs0aDupfYFFy1OA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "163,176,321,133,","type": "Line"},{"bounds": "321,124,16,18","path": ":/images/dummy/arrow.svg","rotate": "747","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 163,176,321,133, + + + true + false + 220,135,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 187,120,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "HhI1oKCh40On9woxJbR4cA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "190,401,417,351,","type": "Line"},{"bounds": "417,342,16,18","path": ":/images/dummy/arrow.svg","rotate": "775","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 190,401,417,351, + + + true + false + 283,355,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 251,341,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + remove AAS Registry + 9 + + + {"bounds": "443,422,140,60","model": "FM5IZzPKeEq4UlTCnQ8lsA","name": "remove AAS Registry","render": [{"bounds": "453,469,121,13","fontStyle": "2","text": "remove AAS Registry","type": "Text"},{"bounds": "466,422,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 443,422,140,60 + + + {"model": "MINdPRMycUOQGkX4zYLvHA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "190,417,443,444,","type": "Line"},{"bounds": "443,435,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2639","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 190,417,443,444, + + + true + false + 301,410,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 273,395,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"bounds": "98,189,46,105","model": "zgwrPpEJokWqIfVxkTPTJA","name": "guest","render": [{"bounds": "105,281,32,13","fontStyle": "2","text": "guest","type": "Text"},{"bounds": "100,189,40,88","path": "shapes/actor.png","preserveRatio": "true","type": "Image"}],"type": "UMLActorView"} + 98,189,46,105 + + + handle session + 6 + + + {"bounds": "391,112,95,60","model": "Jl9FNKsW+U6DPd6kldYNRQ","name": "handle session","render": [{"bounds": "397,159,83,13","fontStyle": "2","text": "handle session","type": "Text"},{"bounds": "392,112,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 391,112,95,60 + + + {"model": "reamejV8W0+vMhrJZTc40A","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "143,234,391,156,","type": "Line"},{"bounds": "391,147,16,18","path": ":/images/dummy/arrow.svg","rotate": "725","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 143,234,391,156, + + + true + false + 244,175,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 211,160,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + handle AAS + 6 + + + {"bounds": "401,212,80,60","model": "sU8XUcSOTUGLaBxP6TCkSA","name": "handle AAS","render": [{"bounds": "409,259,64,13","fontStyle": "2","text": "handle AAS","type": "Text"},{"bounds": "401,214,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 401,212,80,60 + + + get system info + 6 + + + {"bounds": "380,332,101,60","model": "yl8emgmj7kunUKUsA6IcCA","name": "get system info","render": [{"bounds": "387,379,88,13","fontStyle": "2","text": "get system info","type": "Text"},{"bounds": "384,332,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 380,332,101,60 + + + {"model": "QdG3Kjl4yUyeNP/gi21SYg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "143,241,401,241,","type": "Line"},{"bounds": "401,232,16,18","path": ":/images/dummy/arrow.svg","rotate": "900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 143,241,401,241, + + + true + false + 254,220,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 225,205,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "WMazdjuyE0mgz5whmZ93FA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "143,250,380,342,","type": "Line"},{"bounds": "380,333,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2487","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 143,250,380,342, + + + true + false + 249,276,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 226,262,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + aas-portal + workspace + 3 + + + aas-portal + + + {"bounds": "97,157,107,70","model": "r2NZ58QNZEKWlYvOGlT11g","name": "aas-portal","render": [{"bounds": "97,157,107,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "102,186,97,16","text": "<<workspace>>","type": "Text"},{"bounds": "122,202,58,16","text": "aas-portal","type": "Text"}],"type": "UMLPackageView"} + 59,101,107,70 + + + {"model": "I+eWkMfw9EKIs2ZitA//lQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "189,226,312,337,","type": "Line"},{"bounds": "312,328,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2279","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 189,226,312,337, + + + true + false + 243,265,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 224,254,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + aasportal-users + MongoDB + 10 + + + aas-server-app + docker container + 13 + + + {"fill-color": "255,255,255,255"} + {"bounds": "291,375,166,80","model": "qdayvcplfEapRY3chDyZvA","name": "aas-server-app","render": [{"bounds": "291,375,166,80","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "316,404,112,13","text": "<<docker container>>","type": "Text"},{"bounds": "328,417,88,13","fontStyle": "2","text": "aas-server-app","type": "Text"}],"type": "UMLNodeView"} + 291,375,166,80 + + + AASX Server + 15 + + + {"border-color": "255,192,0,255","fill-color": "255,213,129,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "97,576,120,75","model": "XTDYM1rA0UG653BTEwfqog","name": "AASX Server","render": [{"bounds": "97,576,120,75","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "119,609,71,13","fontStyle": "2","text": "AASX Server","type": "Text"}],"type": "UMLNodeView"} + 97,576,120,75 + + + aas-server + node.js + 17 + + + {"bounds": "70,266,147,80","model": "cmOEgyeti02akOoZ1BETVg","name": "aas-server","render": [{"bounds": "70,266,147,80","path": "shapes/artifact.png","preserveRatio": "true","sliceMargin": "5,22,19,22","type": "Image"},{"bounds": "110,292,68,13","text": "<<node.js>>","type": "Text"},{"bounds": "113,305,62,13","fontStyle": "2","text": "aas-server","type": "Text"}],"type": "UMLArtifactView"} + 70,266,147,80 + + + aasportal-users + docker container + 17 + + + {"border-color": "91,155,213,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "591,296,166,80","model": "DEyatjst4Euy6JghnVkkzw","name": "aasportal-users","render": [{"bounds": "591,296,166,80","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "616,325,112,13","text": "<<docker container>>","type": "Text"},{"bounds": "624,338,95,13","fontStyle": "2","text": "aasportal-users","type": "Text"}],"type": "UMLNodeView"} + 591,296,166,80 + + + aas-scan-worker + node.js + 22 + + + {"bounds": "70,416,147,80","model": "nRhw4pRJ1kKmCyELXdav5w","name": "aas-scan-worker","render": [{"bounds": "70,416,147,80","path": "shapes/artifact.png","preserveRatio": "true","sliceMargin": "5,22,19,22","type": "Image"},{"bounds": "110,442,68,13","text": "<<node.js>>","type": "Text"},{"bounds": "96,455,96,13","fontStyle": "2","text": "aas-scan-worker","type": "Text"}],"type": "UMLArtifactView"} + 70,416,147,80 + + + {"model": "VOaFYxEa+kq15XnfVi0Q4w","name": "","render": [{"lineWidth": "0","points": "143,416,143,345,","type": "Line"},{"bounds": "155,390,6,13","text": "*","type": "Text"},{"bounds": "155,359,6,13","text": "1","type": "Text"}],"type": "UMLAssociationView"} + 143,416,143,345, + + + true + false + 110,375,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 66,375,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 99,370,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + 155,390,6,13 + 16 + 20,15 + * + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 105,379,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 155,359,6,13 + 18 + 20,-15 + 1 + 132 + {toMultiplicity} + true + true + + + true + false + 136,405,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 136,346,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + NGINX + web server + 22 + + + {"bounds": "859,107,130,80","model": "SvIxLoASkki055TXQB2qlA","name": "NGINX","render": [{"bounds": "859,107,130,80","path": "shapes/artifact.png","preserveRatio": "true","sliceMargin": "5,22,19,22","type": "Image"},{"bounds": "881,133,86,13","text": "<<web server>>","type": "Text"},{"bounds": "907,146,34,13","fontStyle": "2","text": "NGINX","type": "Text"}],"type": "UMLArtifactView"} + 859,107,130,80 + + + {"model": "a3fzLVl3B0GGi60jCLekUw","name": "","render": [{"lineWidth": "0","points": "360,454,319,576,","type": "Line"},{"bounds": "308,546,6,13","text": "*","type": "Text"}],"type": "UMLAssociationView"} + 360,454,319,576, + + + true + false + 336,514,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 321,519,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 332,491,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + false + 299,462,81,13 + 16 + 20,15 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 323,537,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 308,546,6,13 + 18 + 20,-15 + * + 132 + {toMultiplicity} + true + true + + + true + false + 353,455,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 312,565,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + {"model": "tiMrIUewf0CYv9iVdAAZ0g","name": "","render": [{"lineWidth": "0","points": "329,454,196,576,","type": "Line"},{"bounds": "198,545,6,13","text": "*","type": "Text"}],"type": "UMLAssociationView"} + 329,454,196,576, + + + true + false + 255,520,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 236,531,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 281,486,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + false + 264,450,81,13 + 16 + 20,15 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 213,554,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 198,545,6,13 + 18 + 20,-15 + * + 132 + {toMultiplicity} + true + true + + + true + false + 322,455,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 189,565,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + {"model": "bAveau2tQEGqoOWwUztzKg","name": "","render": [{"lineWidth": "0","points": "392,454,450,576,","type": "Line"},{"bounds": "425,558,6,13","text": "*","type": "Text"}],"type": "UMLAssociationView"} + 392,454,450,576, + + + true + false + 417,503,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 401,496,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 394,478,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + false + 347,473,81,13 + 16 + 20,15 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 423,527,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 425,558,6,13 + 18 + 20,-15 + * + 132 + {toMultiplicity} + true + true + + + true + false + 385,455,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 443,565,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + {"model": "BPRi0Fmt/kOCowEXh26uWw","name": "","render": [{"lineWidth": "0","points": "423,454,576,576,","type": "Line"},{"bounds": "548,569,6,13","text": "*","type": "Text"}],"type": "UMLAssociationView"} + 423,454,576,576, + + + true + false + 491,497,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 472,486,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 435,461,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + false + 389,472,81,13 + 16 + 20,15 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 531,533,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 548,569,6,13 + 18 + 20,-15 + * + 132 + {toMultiplicity} + true + true + + + true + false + 416,455,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 569,565,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + {"model": "dvgraY4s8EG1YRNFL4I92Q","name": "","render": [{"lineWidth": "0","points": "373,306,373,375,","type": "Line"},{"bounds": "355,320,6,13","text": "1","type": "Text"},{"bounds": "355,349,6,13","text": "1","type": "Text"}],"type": "UMLAssociationView"} + 373,306,373,375, + + + true + false + 370,335,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 356,335,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 359,340,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + 355,320,6,13 + 16 + 20,15 + 1 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 365,329,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 355,349,6,13 + 18 + 20,-15 + 1 + 132 + {toMultiplicity} + true + true + + + true + false + 366,307,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 366,364,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + {"model": "jc0ng+UQr0uqOGFNWYls6Q","name": "","render": [{"lineWidth": "0","points": "456,392,591,357,","type": "Line"},{"bounds": "572,371,6,13","text": "1","type": "Text"}],"type": "UMLAssociationView"} + 456,392,591,357, + + + true + false + 502,354,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 469,340,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + false + 462,361,59,13 + 16 + 40,-15 + 132 + {fromName} + true + true + + + fromMultiView + true + false + 439,396,81,13 + 16 + 20,15 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 526,347,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + 572,371,6,13 + 18 + 20,-15 + 1 + 132 + {toMultiplicity} + true + true + + + true + false + 457,387,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 576,352,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + {"model": "InbMdRFUy0CQqafHHGgcqA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "247,613,216,613,","type": "Line"},{"bounds": "216,604,16,18","path": ":/images/dummy/arrow.svg","rotate": "-900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 247,613,216,613, + + + true + false + 214,622,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 185,637,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "uXBYfjACfUiDMLEejN+nWw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "216,442,291,429,","type": "Line"},{"bounds": "291,420,16,18","path": ":/images/dummy/arrow.svg","rotate": "801","type": "EdgeEnd"},{"bounds": "217,400,64,13","text": "<<deploy>>","type": "Text"}],"type": "UMLDependencyView"} + 216,442,291,429, + + + true + false + 233,415,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 217,400,64,13 + 17 + 0,-30 + <<deploy>> + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "58ton5tBSUaDQ59frULkfw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "216,340,291,375,","type": "Line"},{"bounds": "291,366,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2449","type": "EdgeEnd"},{"bounds": "235,325,64,13","text": "<<deploy>>","type": "Text"}],"type": "UMLDependencyView"} + 216,340,291,375, + + + true + false + 242,338,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 235,325,64,13 + 17 + 0,-30 + <<deploy>> + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + aasportal-users + MongoDB + 23 + + + {"bounds": "889,245,140,80","model": "fUCEV8SyUkiKgOKj6d69ZA","name": "aasportal-users","render": [{"bounds": "889,245,140,80","path": "shapes/artifact.png","preserveRatio": "true","sliceMargin": "5,22,19,22","type": "Image"},{"bounds": "921,271,77,13","text": "<<MongoDB>>","type": "Text"},{"bounds": "912,284,95,13","fontStyle": "2","text": "aasportal-users","type": "Text"}],"type": "UMLArtifactView"} + 889,245,140,80 + + + {"model": "x0WSXqCmsU2F06qK3KNU3Q","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "889,296,756,320,","type": "Line"},{"bounds": "756,311,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1002","type": "EdgeEnd"},{"bounds": "797,321,64,13","text": "<<deploy>>","type": "Text"}],"type": "UMLDependencyView"} + 889,296,756,320, + + + true + false + 808,317,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 797,321,64,13 + 17 + -2,-20 + <<deploy>> + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "msqagNoCsUmfXbUckUzT7Q","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "859,160,456,248,","type": "Line"},{"bounds": "456,239,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1023","type": "EdgeEnd"},{"bounds": "630,217,64,13","text": "<<deploy>>","type": "Text"}],"type": "UMLDependencyView"} + 859,160,456,248, + + + true + false + 643,213,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 630,217,64,13 + 17 + 0,-19 + <<deploy>> + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + aas-portal + browser app + 23 + + + {"bounds": "558,66,138,80","model": "P6w27jhd6EePFn9YYQjiIA","name": "aas-portal","render": [{"bounds": "558,66,138,80","path": "shapes/artifact.png","preserveRatio": "true","sliceMargin": "5,22,19,22","type": "Image"},{"bounds": "581,92,92,13","text": "<<browser app>>","type": "Text"},{"bounds": "598,105,59,13","fontStyle": "2","text": "aas-portal","type": "Text"}],"type": "UMLArtifactView"} + 558,66,138,80 + + + {"model": "FvMJfXPq/U2OmC+aKBoZ5A","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "558,105,456,105,","type": "Line"},{"bounds": "456,96,16,18","path": ":/images/dummy/arrow.svg","rotate": "-900","type": "EdgeEnd"},{"bounds": "479,113,64,13","text": "<<deploy>>","type": "Text"}],"type": "UMLDependencyView"} + 558,105,456,105, + + + true + false + 489,114,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + 479,113,64,13 + 17 + -4,-14 + <<deploy>> + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + reset + 7 + + + {"bounds": "364,492,80,60","model": "fMw8fPNPm0CDAK2+p2Z5+Q","name": "reset","render": [{"bounds": "389,539,30,13","fontStyle": "2","text": "reset","type": "Text"},{"bounds": "364,494,80,37","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 364,492,80,60 + + + {"model": "/pd5Y5qx1kioPXexJLKJpg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "190,433,364,505,","type": "Line"},{"bounds": "364,496,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2475","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 190,433,364,505, + + + true + false + 265,449,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 241,435,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + start-use-cases + 8 + + + Start + 9 + + + {"bounds": "38,46,105,70","model": "45R3d27K5UGa9q3EVdK9Aw","name": "Start","render": [{"bounds": "38,46,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "79,84,24,13","text": "Start","type": "Text"}],"type": "UMLPackageView"} + 38,46,105,70 + + + AAS + 9 + + + {"bounds": "178,46,105,70","model": "GcnWyv7b+E6N+hH4hy6gWg","name": "AAS","render": [{"bounds": "178,46,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "221,84,20,13","text": "AAS","type": "Text"}],"type": "UMLPackageView"} + 178,46,105,70 + + + Dashboard + 10 + + + {"bounds": "318,46,105,70","model": "enyUurvMikWREAi4+mmwUg","name": "Dashboard","render": [{"bounds": "318,46,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "345,84,52,13","text": "Dashboard","type": "Text"}],"type": "UMLPackageView"} + 318,46,105,70 + + + About + 11 + + + {"bounds": "458,46,105,70","model": "UTpsZuQMq0+gqQdSPTnJEQ","name": "About","render": [{"bounds": "458,46,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "496,84,29,13","text": "About","type": "Text"}],"type": "UMLPackageView"} + 458,46,105,70 + + + upload AASX file + 3 + + + {"bounds": "321,252,107,60","model": "NSsSjerobEC835ennOiNiQ","name": "upload AASX file","render": [{"bounds": "329,299,91,13","fontStyle": "2","text": "upload AASX file","type": "Text"},{"bounds": "328,252,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 321,252,107,60 + + + {"model": "zEsB593Eukyt01Cl3ZjJsA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "190,384,321,311,","type": "Line"},{"bounds": "321,302,16,18","path": ":/images/dummy/arrow.svg","rotate": "608","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 190,384,321,311, + + + true + false + 231,329,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 194,316,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + filter AAS collection + 4 + + + {"bounds": "410,147,128,71","model": "J5mT6UU6R06nJoqTaGtVSw","name": "filter AAS collection","render": [{"bounds": "419,205,110,13","fontStyle": "2","text": "filter AAS collection","type": "Text"},{"bounds": "415,147,116,54","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 410,147,128,71 + + + {"model": "dUU1vtdeZU6QpTGEYEizeg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "163,182,410,182,","type": "Line"},{"bounds": "410,173,16,18","path": ":/images/dummy/arrow.svg","rotate": "900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 163,182,410,182, + + + true + false + 269,161,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 240,146,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + delete AAS from container + 5 + + + {"bounds": "581,363,173,60","model": "Q7ThvFDoL0m7YCN3EQY1lQ","name": "delete AAS from container","render": [{"bounds": "593,410,149,13","fontStyle": "2","text": "delete AAS from container","type": "Text"},{"bounds": "621,363,92,43","path": "shapes/usecase.png","preserveRatio": "true","type": "Image"}],"type": "UMLUseCaseView"} + 581,363,173,60 + + + {"model": "HafkkheF90ewItcyCGOkcw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "190,410,581,395,","type": "Line"},{"bounds": "581,386,16,18","path": ":/images/dummy/arrow.svg","rotate": "878","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 190,410,581,395, + + + true + false + 367,382,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 338,367,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + aas-lib + workspace + 5 + + + {"bounds": "297,157,107,70","model": "Tu7y1wXKj0+cIDAoE8pQ1A","name": "aas-lib","render": [{"bounds": "297,157,107,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "302,186,97,16","text": "<<workspace>>","type": "Text"},{"bounds": "332,202,38,16","text": "aas-lib","type": "Text"}],"type": "UMLPackageView"} + 259,101,107,70 + + + {"model": "aVxI1VRPlEyASeqjYS2S/A","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "203,191,297,191,","type": "Line"},{"bounds": "297,182,16,18","path": ":/images/dummy/arrow.svg","rotate": "900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 203,191,297,191, + + + true + false + 232,170,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 203,155,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "p5uV+AtgckSjMHnIRcLbYw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "350,226,350,337,","type": "Line"},{"bounds": "350,328,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1800","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 350,226,350,337, + + + true + false + 347,276,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 333,276,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + aas-lib + 13 + + + aasportal + package + 6 + + + {"fill-color": "255,255,255,255"} + {"bounds": "38,56,603,385","model": "oUNKi+15okyeKIB7PKKVWA","name": "aasportal","render": [{"bounds": "38,56,603,385","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "298,81,83,16","text": "<<package>>","type": "Text"},{"bounds": "313,97,53,16","text": "aasportal","type": "Text"}],"type": "UMLPackageView"} + 38,56,603,385 + + + {"bounds": "138,56,383,305","model": "09ZDFMDrFUyf7OuCrLmopQ","name": "common","render": [{"bounds": "138,56,383,305","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "288,205,83,13","text": "<<workspace>>","type": "Text"},{"bounds": "310,218,39,13","text": "common","type": "Text"}],"type": "UMLPackageView"} + 138,56,383,305 + + + Package1 + 4 + + + + docker host + 18 + + + {"bounds": "804,436,185,115","model": "8QtrHo63z0OObUKRB4L2kQ","name": "","render": [{"bounds": "804,436,185,115","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "850,482,88,13","text": "<<docker host>>","type": "Text"}],"type": "UMLNodeView"} + 804,436,185,115 + + + AASPortal + service + 19 + + + {"bounds": "736,626,175,105","model": "JyPxzzEW2kq2VIg4oln9ZA","name": "AASPortal","render": [{"bounds": "736,626,175,105","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "788,667,66,13","text": "<<service>>","type": "Text"},{"bounds": "793,680,57,13","fontStyle": "2","text": "AASPortal","type": "Text"}],"type": "UMLNodeView"} + 736,626,175,105 + + + aasportal + docker image + 20 + + + {"bounds": "650,781,136,70","model": "W2oDpgF/l0+GosDZXdfq1w","name": "aasportal","render": [{"bounds": "650,781,136,70","path": "shapes/node.png","preserveRatio": "true","sliceMargin": "28,22,29,22","type": "Image"},{"bounds": "668,805,95,13","text": "<<docker image>>","type": "Text"},{"bounds": "689,818,54,13","fontStyle": "2","text": "aasportal","type": "Text"}],"type": "UMLNodeView"} + 650,781,136,70 + + + {"model": "8tv4YE60C0+oljMiiatNQw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "874,550,844,626,","type": "Line"},{"bounds": "844,617,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1584","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 874,550,844,626, + + + true + false + 855,588,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 840,593,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "zqz68FPNuUimTQKsjmnrsA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "783,730,743,781,","type": "Line"},{"bounds": "743,772,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1418","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 783,730,743,781, + + + true + false + 757,759,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 740,769,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + Main + + + aas-portal + + + {"bounds": "40,287,163,141","model": "dpevynsRpkywZ1F5q3o1PQ","name": "aas-portal","render": [{"bounds": "40,287,163,141","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "93,312,58,16","text": "aas-portal","type": "Text"}],"type": "UMLPackageView"} + 40,287,163,141 + + + aas-server + 1 + + + aas-lib + 5 + + + {"bounds": "50,336,105,70","model": "fmw4iXIgcE6VJrorBoxcLQ","name": "aas-lib","render": [{"bounds": "50,336,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "84,373,38,16","text": "aas-lib","type": "Text"}],"type": "UMLPackageView"} + 10,49,105,70 + + + Angular + 3 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "348,323,105,70","model": "QVMYcxbb0EOwIs31av7nGg","name": "Angular","render": [{"bounds": "348,323,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "379,360,44,16","text": "Angular","type": "Text"}],"type": "UMLPackageView"} + 348,323,105,70 + + + NgRx + 2 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "348,457,105,70","model": "zM8ZCKYDsEKoE07Ww3TOtA","name": "NgRx","render": [{"bounds": "348,457,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "386,494,29,16","text": "NgRx","type": "Text"}],"type": "UMLPackageView"} + 348,457,105,70 + + + ng-bootstrap + 1 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "348,147,105,70","model": "5H4BtwGdM0u8NQORIuIfmw","name": "ng-bootstrap","render": [{"bounds": "348,147,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "364,184,73,16","text": "ng-bootstrap","type": "Text"}],"type": "UMLPackageView"} + 348,147,105,70 + + + Bootstrap 5 + 4 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "69,146,105,70","model": "Hw7aqkhTO0mTCc8OTXgMIA","name": "Bootstrap 5","render": [{"bounds": "69,146,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "89,183,65,16","text": "Bootstrap 5","type": "Text"}],"type": "UMLPackageView"} + 69,146,105,70 + + + {"model": "/MRL3pwHrUCY67xvpFBPrA","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "400,216,400,323,","type": "Line"},{"bounds": "400,314,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1800","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 400,216,400,323, + + + true + false + 397,264,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 383,264,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "XN6aP83xakWvoI3LvDk/aQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "400,457,400,392,","type": "Line"},{"bounds": "400,383,16,18","path": ":/images/dummy/arrow.svg","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 400,457,400,392, + + + true + false + 367,419,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 323,419,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "pKe3eQdBAUil5Cfl2atb5A","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "348,181,173,180,","type": "Line"},{"bounds": "173,171,16,18","path": ":/images/dummy/arrow.svg","rotate": "-896","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 348,181,173,180, + + + true + false + 243,190,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 214,205,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "c/SpgsExcE+KZeGVmU4ugg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "121,287,121,215,","type": "Line"},{"bounds": "121,206,16,18","path": ":/images/dummy/arrow.svg","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 121,287,121,215, + + + true + false + 88,245,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 44,245,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "xM65sbxz5EamYwJbL2tGrg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "202,306,348,214,","type": "Line"},{"bounds": "348,205,16,18","path": ":/images/dummy/arrow.svg","rotate": "577","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 202,306,348,214, + + + true + false + 249,241,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 212,229,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "kBVVirezLECqp3ZqSe6Kgw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "202,357,348,357,","type": "Line"},{"bounds": "348,348,16,18","path": ":/images/dummy/arrow.svg","rotate": "900","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 202,357,348,357, + + + true + false + 257,336,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 228,321,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "DdiIsnFI10SHqldlpxqHdg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "202,396,348,466,","type": "Line"},{"bounds": "348,457,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2443","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 202,396,348,466, + + + true + false + 263,411,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 241,398,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + Main + 1 + + + {"bounds": "388,56,105,70","model": "26G7XaR5cEWSVR4xO388Yw","name": "aas-server","render": [{"bounds": "388,56,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "410,93,61,16","text": "aas-server","type": "Text"}],"type": "UMLPackageView"} + 388,56,105,70 + + + Express + 3 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "108,236,105,70","model": "sAaBUbFqoE6yfvlavXigtA","name": "Express","render": [{"bounds": "108,236,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "139,273,44,16","text": "Express","type": "Text"}],"type": "UMLPackageView"} + 108,236,105,70 + + + {"model": "x7bf6AO6+Uu9qQc8wnv0UQ","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "388,123,212,236,","type": "Line"},{"bounds": "212,227,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1227","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 388,123,212,236, + + + true + false + 290,187,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 269,199,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + node-opcua + 4 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "518,236,105,70","model": "5v1XvNW1AEWVdoUy4DqX4Q","name": "node-opcua","render": [{"bounds": "518,236,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "537,273,67,16","text": "node-opcua","type": "Text"}],"type": "UMLPackageView"} + 518,236,105,70 + + + {"model": "lwnnUTNTxE6fu5FrE9Hu2A","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "465,125,545,236,","type": "Line"},{"bounds": "545,227,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2157","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 465,125,545,236, + + + true + false + 499,166,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 482,157,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + tsyringe + 5 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "648,236,105,70","model": "S8kfhwEFY0iRUJDnOgOVCw","name": "tsyringe","render": [{"bounds": "648,236,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "678,273,45,16","text": "tsyringe","type": "Text"}],"type": "UMLPackageView"} + 648,236,105,70 + + + {"model": "5Pr6rWJPok2T6WENxzT8xg","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "491,125,651,236,","type": "Line"},{"bounds": "651,227,16,18","path": ":/images/dummy/arrow.svg","rotate": "-2352","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 491,125,651,236, + + + true + false + 562,163,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 541,150,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + jsonwebtoken + 6 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "238,236,105,70","model": "b1hz50qYtE6yK/Zmd952Vw","name": "jsonwebtoken","render": [{"bounds": "238,236,105,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "251,273,79,16","text": "jsonwebtoken","type": "Text"}],"type": "UMLPackageView"} + 238,236,105,70 + + + swagger-ui-express + 7 + + + {"border-color": "64,64,64,255","fill-color": "255,255,255,255","font-color": "0,0,0,255","gradient": false,"shadow": false} + {"bounds": "370,236,123,70","model": "G5su2KgTZk2FWFTCqSs9PA","name": "swagger-ui-express","render": [{"bounds": "370,236,123,70","path": "shapes/package.png","preserveRatio": "true","sliceMargin": "35,15,3,20","type": "Image"},{"bounds": "375,273,113,16","text": "swagger-ui-express","type": "Text"}],"type": "UMLPackageView"} + 370,236,123,70 + + + {"model": "YjPh6kta+0+ZBz0lomilQw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "411,125,318,236,","type": "Line"},{"bounds": "318,227,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1400","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 411,125,318,236, + + + true + false + 358,185,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 341,194,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + {"model": "WzOx3c3qmk28T0C0gCCaRw","name": "","render": [{"lineStyle": "2","lineWidth": "0","points": "438,125,433,236,","type": "Line"},{"bounds": "433,227,16,18","path": ":/images/dummy/arrow.svg","rotate": "-1774","type": "EdgeEnd"}],"type": "UMLDependencyView"} + 438,125,433,236, + + + true + false + 433,176,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditName(view, model, text) + + + true + false + 419,176,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + common + 2 + + + AASDocument + 1 + + + AASDocument + 2 + + + {"bounds": "251,118,141,187","model": "ZoH1FHrvmE691ktxD0M92w","name": "AASDocument","render": [{"bounds": "251,118,141,187","type": "Rect"},{"bounds": "275,123,93,16","fontStyle": "2","text": "AASDocument","type": "Text"},{"bounds": "251,144,141,150","fillColor": "0,0,0,0","type": "Rect"},{"bounds": "256,147,59,16","text": "+id: string","type": "Text"},{"bounds": "256,163,90,16","text": "+idShort: string","type": "Text"},{"bounds": "256,179,98,16","text": "+endpoint: string","type": "Text"},{"bounds": "256,195,102,16","text": "+container: string","type": "Text"},{"bounds": "256,211,105,16","text": "+thumbnail: string","type": "Text"},{"bounds": "256,227,123,16","text": "+timeStamp: number","type": "Text"},{"bounds": "256,243,113,16","text": "+readOnly: boolean","type": "Text"},{"bounds": "256,259,131,16","text": "+onlineReady: boolean","type": "Text"},{"bounds": "256,275,111,16","text": "+modified: boolean","type": "Text"},{"bounds": "251,294,141,11","fillColor": "0,0,0,0","type": "Rect"}],"type": "UMLClassView"} + 251,118,141,187 + + + Environment + + + {"bounds": "262,408,120,48","model": "Z4oc8VZNd0KpnjmskRKiIQ","name": "Environment","render": [{"bounds": "262,408,120,48","type": "Rect"},{"bounds": "282,413,81,16","fontStyle": "2","text": "Environment","type": "Text"},{"bounds": "262,434,120,11","fillColor": "0,0,0,0","type": "Rect"},{"bounds": "262,445,120,11","fillColor": "0,0,0,0","type": "Rect"}],"type": "UMLClassView"} + 262,408,120,48 + + + {"model": "rWjij/JuSUS5AAQ3LKeT1w","name": "","render": [{"lineWidth": "0","points": "321,408,321,304,","type": "Line"},{"bounds": "321,290,14,28","path": "shapes/composition.png","type": "EdgeEnd"},{"bounds": "261,383,54,16","text": "+ content","type": "Text"},{"bounds": "328,382,26,16","text": "0...1","type": "Text"}],"type": "UMLCompositionView"} + 321,408,321,304, + shapes/composition.png + + + true + false + 288,350,36,13 + 17 + 0,-15 + 132 + {name} + true + true + uml.onEditAssociationName(view, model, text) + + + true + false + 244,350,95,13 + 17 + 0,-30 + 132 + <<{stereotype}>> + true + true + uml.onEditStereotype(view, model, text) + + + fromNameView + true + 261,383,54,16 + 16 + 17,-33 + + content + 132 + {fromName} + true + true + + + fromMultiView + true + 328,382,26,16 + 16 + 18,20 + 0...1 + 132 + {fromMultiplicity} + true + true + + + toNameView + true + false + 283,338,47,13 + 18 + 40,15 + 132 + {toName} + true + true + + + toMultiView + true + false + 302,318,69,13 + 18 + 20,-15 + 132 + {toMultiplicity} + true + true + + + true + false + 314,397,15,11 + 21 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {fromQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + true + false + 314,305,15,11 + 22 + true + false + false + true + true + + + false + 0,0,15,11 + 5 + 0 + true + {toQualifiers} + uml.updateAttribute(view, model) + uml.onEditAttribute(view, model, text) + + + id + string + + + container + 3 + string + + + thumbnail + 4 + string + + + idShort + 1 + string + + + timeStamp + 5 + number + + + readOnly + 6 + boolean + + + onlineReady + 7 + boolean + + + modified + 8 + boolean + + + endpoint + 2 + string + + + aas + 4 + + + + + extend + + + * + l + 1 + + + 1 + http://localhost:1337/api/… + 1 + + + * + ws://.../websocket + 1 + + + 1 + 1 + + + * + http://.../web-aas.html + 1 + + + * + 1 + + + 1 + 1 + + + 1 + + + * + + + 1 + 1 + + + * + + + 1 + + + 1 + * + + + * + + + * + 1 + + + * + + + * + + + * + + + * + + + 1 + 1 + + + 1 + + + deploy + + + deploy + + + deploy + + + deploy + + + deploy + + + + content + 0...1 + + + diff --git a/angular.json b/angular.json new file mode 100644 index 00000000..1b4d1ecc --- /dev/null +++ b/angular.json @@ -0,0 +1,183 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "aas-portal": { + "projectType": "application", + "schematics": { + "@schematics/angular:application": { + "strict": true, + "style": "scss" + } + }, + "root": "projects/aas-portal", + "sourceRoot": "projects/aas-portal/src", + "prefix": "fhg", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "projects/aas-portal/dist", + "index": "projects/aas-portal/src/index.html", + "main": "projects/aas-portal/src/main.ts", + "polyfills": [ + "zone.js" + ], + "tsConfig": "projects/aas-portal/tsconfig.app.json", + "inlineStyleLanguage": "scss", + "assets": [ + "projects/aas-portal/src/favicon.ico", + "projects/aas-portal/src/assets" + ], + "styles": [ + "projects/aas-portal/src/styles.scss" + ], + "scripts": [ + "node_modules/bootstrap/dist/js/bootstrap.min.js" + ], + "allowedCommonJsDependencies": [ + "lodash-es" + ] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "3mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "fileReplacements": [ + { + "replace": "projects/aas-portal/src/environments/environment.ts", + "with": "projects/aas-portal/src/environments/environment.prod.ts" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "aas-portal:build:production", + "proxyConfig": "projects/aas-portal/proxy.conf.json" + }, + "development": { + "browserTarget": "aas-portal:build:development", + "proxyConfig": "projects/aas-portal/proxy.conf.json" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "aas-portal:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": [ + "zone.js", + "zone.js/testing" + ], + "tsConfig": "projects/aas-portal/tsconfig.spec.json", + "karmaConfig": "projects/aas-portal/karma.conf.cjs", + "inlineStyleLanguage": "scss", + "codeCoverage": true, + "assets": [ + "projects/aas-portal/src/favicon.ico", + "projects/aas-portal/src/assets" + ], + "styles": [ + "projects/aas-portal/src/styles.scss" + ], + "scripts": [ + "node_modules/bootstrap/dist/js/bootstrap.min.js" + ] + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": [ + "projects/aas-portal/src/app/**/*.ts", + "projects/aas-portal/src/app/**/*.html" + ] + } + } + } + }, + "aas-lib": { + "projectType": "library", + "root": "projects/aas-lib", + "sourceRoot": "projects/aas-lib/src", + "prefix": "fhg", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:ng-packagr", + "options": { + "project": "projects/aas-lib/ng-package.json" + }, + "configurations": { + "production": { + "tsConfig": "projects/aas-lib/tsconfig.lib.prod.json" + }, + "development": { + "tsConfig": "projects/aas-lib/tsconfig.lib.json" + } + }, + "defaultConfiguration": "production" + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "tsConfig": "projects/aas-lib/tsconfig.spec.json", + "karmaConfig": "projects/aas-lib/karma.conf.cjs", + "codeCoverage": true, + "polyfills": [ + "zone.js", + "zone.js/testing" + ] + } + }, + "lint": { + "builder": "@angular-eslint/builder:lint", + "options": { + "lintFilePatterns": [ + "projects/aas-lib/src/lib/**/*.ts", + "projects/aas-lib/src/lib/**/*.html" + ] + } + } + }, + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + } + } + }, + "cli": { + "analytics": false + } +} \ No newline at end of file diff --git a/copyright-header.js b/copyright-header.js new file mode 100644 index 00000000..2cc8329c --- /dev/null +++ b/copyright-header.js @@ -0,0 +1,293 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo,", + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft", + * zur Foerderung der angewandten Forschung e.V.", + * + *****************************************************************************/ +"use strict"; + +import fs from 'fs'; +import * as $path from 'path'; +import readline from 'readline'; +import os from 'os'; + +const jsHeader = [ + "/******************************************************************************", + " *", + " * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo,", + " * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft", + " * zur Foerderung der angewandten Forschung e.V.", + " *", + " *****************************************************************************/", + ""]; + +const htmlHeader = [ + "", + ""]; + +checkFilesAsync([ + "./projects/aas-portal/src", + "./projects/aas-server/src", + "./projects/aas-lib/src", + "./projects/common/src" +]); + +async function checkFilesAsync(dirs) { + const files = []; + for (const dir of dirs) { + await traverseFilesAsync(dir, [".ts", ".js", ".html", ".css"], files); + } + + for (const file of files) { + const extension = $path.extname(file).toLowerCase(); + const text = await readFileAsync(file); + if (hasValidCopyrightHeader(text, extension)) { + console.log(`${file}: header is Ok`); + } else { + const removed = removeCopyrightHeader(text, extension); + insertCopyrightHeader(text, extension); + await writeFileAsync(file, text); + console.log(`${file}: ${removed ? "header updated" : "header inserted"}`); + } + } + + async function traverseFilesAsync(dir, extensions, files) { + const entries = await fs.promises.readdir(dir); + for (const entry of entries) { + let path = $path.join(dir, entry); + const stat = fs.statSync(path); + if (stat.isFile() && matchExtensions(path, extensions)) { + files.push(path); + } else if (stat.isDirectory()) { + await traverseFilesAsync(path, extensions, files); + } + } + } + + function matchExtensions(file, extensions) { + const extension = $path.extname(file).toLowerCase(); + return extensions.indexOf(extension) >= 0; + } + + async function readFileAsync(path) { + const text = []; + return await new Promise((result, reject) => { + const file = readline.createInterface({ + input: fs.createReadStream(path), + output: process.stdout, + terminal: false + }); + + file.on("line", (line) => { + text.push(line); + }); + + file.on("error", (error) => { + reject(error); + }); + + file.on("close", () => { + result(text); + }); + }); + } + + /** + * Determines wether the specified text has a valid copyright header. + * @param {string[]} text The current text. + * @param {string} extension The file type. + * @returns `true` if the existing header is valid. + */ + function hasValidCopyrightHeader(text, extension) { + switch (extension) { + case ".ts": + case ".js": + case ".css": + return hasValidJsCopyrightHeader(text); + case ".html": + return hasValidHtmlCopyrightHeader(text); + default: + return true; + } + } + + /** + * Determines wether the specified text has a valid copyright header. + * @param {string[]} text The current text. + * @returns `true` if the existing header is valid. + */ + function hasValidJsCopyrightHeader(text) { + let result = Array.isArray(text) && text.length >= jsHeader.length; + for (let i = 0; i < jsHeader.length; i++) { + if (jsHeader[i] !== text[i]) { + result = false; + break; + } + } + + return result; + } + + /** + * Determines wether the specified text has a valid copyright header. + * @param {string[]} text The current text. + * @returns `true` if the existing header is valid. + */ + function hasValidHtmlCopyrightHeader(text) { + let result = Array.isArray(text) && text.length >= htmlHeader.length; + for (let i = 0; i < htmlHeader.length; i++) { + if (htmlHeader[i] !== text[i]) { + result = false; + break; + } + } + + return result; + } + + /** + * Removes an existing header from the specified text. + * @param {string} text The current text. + * @returns `true` if an existing header has been removed. + */ + function removeCopyrightHeader(text, extension) { + switch (extension) { + case ".ts": + case ".js": + case ".css": + return removeJsCopyrightHeader(text); + case ".html": + return removeHtmlCopyrightHeader(text); + default: + return false; + } + } + + /** + * Removes an existing header from the specified text. + * @param {string} text The current text. + * @returns `true` if an existing header has been removed. + */ + function removeJsCopyrightHeader(text) { + let count = 0; + let start = false; + let end = false; + for (let i = 0; i < text.length; i++) { + let line = text[i].trim(); + if (line.length === 0) { + ++count; + } + else if (!start && !end && line.startsWith("/**********")) { + ++count; + start = true; + } + else if (start && !end && line.startsWith("*")) { + ++count; + } + else if (start && !end && line.endsWith("**********/")) { + ++count; + end = true; + } + else { + break; + } + } + + if (count > 0) { + text.splice(0, count); + } + + return count > 0; + } + + /** + * Removes an existing header from the specified text. + * @param {string} text The current text. + * @returns `true` if an existing header has been removed. + */ + function removeHtmlCopyrightHeader(text) { + let count = 0; + let start = false; + let end = false; + for (let i = 0; i < text.length; i++) { + let line = text[i].trim(); + if (line.length === 0) { + ++count; + } + else if (!start && !end && line.startsWith("")) { + ++count; + end = true; + } + else { + break; + } + } + + if (count > 0) { + text.splice(0, count); + } + + return count > 0; + } + + /** + * Inserts a copyright header. + * @param {string[]} text The text. + * @param {string} extension The file type. + */ + function insertCopyrightHeader(text, extension) { + switch (extension) { + case ".ts": + case ".js": + case ".css": + insertJsCopyrightHeader(text); + break; + case ".html": + insertHtmlCopyrightHeader(text); + break; + } + } + + /** + * Inserts a copyright header. + * @param {string[]} text The text. + */ + function insertJsCopyrightHeader(text) { + for (let i = 0; i < jsHeader.length; i++) { + text.splice(i, 0, jsHeader[i]); + } + } + + /** + * Inserts a copyright header. + * @param {string[]} text The text. + */ + function insertHtmlCopyrightHeader(text) { + for (let i = 0; i < htmlHeader.length; i++) { + text.splice(i, 0, htmlHeader[i]); + } + } + + /** + * Write the text to the specified file. + * @param {string} file The destination file. + * @param {string[]} text The text; + */ + async function writeFileAsync(file, text) { + await fs.promises.writeFile(file, text.join(os.EOL)); + } +} \ No newline at end of file diff --git a/coverage-summary.js b/coverage-summary.js new file mode 100644 index 00000000..bdec0b6d --- /dev/null +++ b/coverage-summary.js @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo,", + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft", + * zur Foerderung der angewandten Forschung e.V.", + * + *****************************************************************************/ +"use strict"; + +import { readFileSync } from 'fs'; + +main(); + +function main() { + const commonSummary = read('./reports/common/coverage-summary.json'); + const aasServerSummary = read('./reports/aas-server/coverage-summary.json'); + const aasLibSummary = read('./reports/aas-lib/coverage-summary.json'); + const aasPortalSummary = read('./reports/aas-portal/coverage-summary.json'); + + let statementsTotal = commonSummary.total.statements.total + + aasServerSummary.total.statements.total + + aasLibSummary.total.statements.total + + aasPortalSummary.total.statements.total; + + let statementsCovered = commonSummary.total.statements.covered + + aasServerSummary.total.statements.covered + + aasLibSummary.total.statements.covered + + aasPortalSummary.total.statements.covered; + + let branchesTotal = commonSummary.total.branches.total + + aasServerSummary.total.branches.total + + aasLibSummary.total.branches.total + + aasPortalSummary.total.branches.total; + + let branchesCovered = commonSummary.total.branches.covered + + aasServerSummary.total.branches.covered + + aasLibSummary.total.branches.covered + + aasPortalSummary.total.branches.covered; + + let functionsTotal = commonSummary.total.functions.total + + aasServerSummary.total.functions.total + + aasLibSummary.total.functions.total + + aasPortalSummary.total.functions.total; + + let functionsCovered = commonSummary.total.functions.covered + + aasServerSummary.total.functions.covered + + aasLibSummary.total.functions.covered + + aasPortalSummary.total.functions.covered; + + let total = commonSummary.total.lines.total + + aasServerSummary.total.lines.total + + aasLibSummary.total.lines.total + + aasPortalSummary.total.lines.total; + + let covered = commonSummary.total.lines.covered + + aasServerSummary.total.lines.covered + + aasLibSummary.total.lines.covered + + aasPortalSummary.total.lines.covered; + + console.info('=============================== Coverage summary ==============================='); + console.info(`Statements : ${(statementsCovered / statementsTotal * 100).toFixed(2)}% ( ${statementsCovered}/${statementsTotal} )`); + console.info(`Branches : ${(branchesCovered / branchesTotal * 100).toFixed(2)}% ( ${branchesCovered}/${branchesTotal} )`); + console.info(`Functions : ${(functionsCovered / functionsTotal * 100).toFixed(2)}% ( ${functionsCovered}/${functionsTotal} )`); + console.info(`Lines : ${(covered / total * 100).toFixed(2)}% ( ${covered}/${total} )`); + console.info('================================================================================'); +} + +function read(path) { + return JSON.parse(readFileSync(path).toString()); +} diff --git a/create-app-info.js b/create-app-info.js new file mode 100644 index 00000000..ccc28185 --- /dev/null +++ b/create-app-info.js @@ -0,0 +1,56 @@ +import { readFile, writeFile } from 'fs/promises'; +import { existsSync } from 'fs'; +import { dirname, resolve, join } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +main(); + +async function main() { + const project = await read(resolve(__dirname, 'package.json')); + const file = resolve(__dirname, 'projects/aas-server/app-info.json'); + const appInfo = await read(file); + for (const item in appInfo) { + appInfo[item] = project[item]; + } + + appInfo.libraries = await readLibrariesAsync(project); + + await write(file, appInfo); +} + +async function read(file) { + return JSON.parse(await readFile(file)); +} + +async function write(file, data) { + return writeFile(file, JSON.stringify(data)); +} + +async function readLibrariesAsync(project) { + const libraries = []; + let nodeModulesFolder = join(__dirname, 'node_modules'); + if (existsSync(nodeModulesFolder)) { + for (const name in project.dependencies) { + let packageFile = join(nodeModulesFolder, name, 'package.json'); + if (existsSync(packageFile)) { + try { + const pkg = JSON.parse((await readFile(packageFile)).toString()); + libraries.push({ + name: pkg.name, + version: pkg.version, + description: pkg.description, + license: pkg.license, + homepage: pkg.homepage + }); + } catch (error) { + noop(); + } + } + } + } + + return libraries; +} + diff --git a/create-jwt.js b/create-jwt.js new file mode 100644 index 00000000..83879219 --- /dev/null +++ b/create-jwt.js @@ -0,0 +1,9 @@ +import jwt from 'jsonwebtoken'; + +const token = jwt.sign({ + id: 'john.doe@email.com', + name: 'John Doe', + role: 'editor' +}, 'The quick brown fox jumps over the lazy dog.'); + +console.log(token); \ No newline at end of file diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..d0c3cbf1 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..9534b018 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..e0aaa3a0 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +myst_parser +sphinx-markdown-tables diff --git a/docs/source/about/.gitkeep b/docs/source/about/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/source/about/about.md b/docs/source/about/about.md new file mode 100644 index 00000000..dc7ecb6a --- /dev/null +++ b/docs/source/about/about.md @@ -0,0 +1,15 @@ +# About the Project + +AASPortal is a Node.js based web portal for the visualization and management of Asset Administration Shells (AAS). The implementation uses the concepts of the document “Details of the Asset Administration Shell” published on https://www.plattform-i40.de and licensed under Creative Commons CC BY 4.0. + +## Contact + +aasportal@iosb-ina.fraunhofer.de + +## License + +Distributed under the Apache 2.0 License. See `LICENSE` for more information. + +Copyright (C) 2022 Fraunhofer Institut IOSB, Fraunhoferstr. 1, D 76131 Karlsruhe, Germany. + +You should have received a copy of the Apache 2.0 License along with this program. If not, see [https://www.apache.org/licenses/LICENSE-2.0.html](https://www.apache.org/licenses/LICENSE-2.0.html). diff --git a/docs/source/architecture.md b/docs/source/architecture.md new file mode 100644 index 00000000..7b21afcd --- /dev/null +++ b/docs/source/architecture.md @@ -0,0 +1,15 @@ +# Architecture and Design +## Main Package +![Main](./images/main.png "Main") + +## AASPortal +AASPortal is an Angular based WEB application. The UI is implemented with the Bootstrap 5 frontend toolkit in conjunction with Bootstrap widgets (ng-bootstrap). For managing the global and local state of the application the NgRx framework is used. + +![aas-portal-dependencies](./images/aas-portal-dependencies.png "AASPortal main dependencies") + +## AASServer +AASServer is a Node.js WEB application. The REST API provided by AASServer is realized with the WEB framework *Express*. For authentication the concept JSON Web Tokens is used. The implementation uses the module *jsonwebtoken*. The AASServer provides an OpenAPI-compliant REST API. To create the living documentation of the REST API the module *swagger-ui-express* is used. + +For the access to Asset Administration Shells in an OPC UA server the *node-opcua* framework is used. + +![aas-server-dependencies](./images/aas-server-dependencies.png "AASServer main dependencies") diff --git a/docs/source/changelog/.gitkeep b/docs/source/changelog/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/source/changelog/changelog.md b/docs/source/changelog/changelog.md new file mode 100644 index 00000000..52059952 --- /dev/null +++ b/docs/source/changelog/changelog.md @@ -0,0 +1,13 @@ +# Changelog + +## Current development version (x.y.z) + +**New Features & Major Changes** + +**Internal changes & bugfixes** + +## Release version x.y.z + +**New Features & Major Changes** + +**Internal changes & bugfixes** diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..f1367e2d --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,36 @@ +# Configuration file for the Sphinx documentation builder. + +# -- Project information + +project = 'AASPortal' +copyright = '2023, Fraunhofer IOSB-INA Lemgo, eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V.' +author = 'Fraunhofer IOSB-INA' + +release = '0.1' +version = '0.1.0' + +# -- General configuration + +extensions = [ + 'sphinx.ext.duration', + 'sphinx.ext.doctest', + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'sphinx.ext.intersphinx', + 'myst_parser', +] + +intersphinx_mapping = { + 'python': ('https://docs.python.org/3/', None), + 'sphinx': ('https://www.sphinx-doc.org/en/master/', None), +} +intersphinx_disabled_domains = ['std'] + +templates_path = ['_templates'] + +# -- Options for HTML output + +html_theme = 'sphinx_rtd_theme' + +# -- Options for EPUB output +epub_show_urls = 'footnote' diff --git a/docs/source/gettingstarted.md b/docs/source/gettingstarted.md new file mode 100644 index 00000000..c21bc151 --- /dev/null +++ b/docs/source/gettingstarted.md @@ -0,0 +1,141 @@ +# Getting Started +## Prerequisites +- Visual Studio Code +- Node.js v18.10.0 +- GIT 2.36.0.windows.1 +- Docker Desktop 4.x + +*AASPortal* is a mono-repository project. It is implemented using the *npm workspaces* concept. The project consists of four workspaces: +- aas-portal: The browser app of *AASPortal*. +- aas-server: The Node.js server app of *AASPortal*. +- aas-lib: UI components and services in an Angular library. +- common: Types and functions used by aas-portal and aas-server. + +```txt +aasportal + ├── projects + │ ├── aas-portal + │ │ └── package.json + │ ├── aas-server + │ │ └── package.json + │ ├── aas-lib + │ │ └── package.json + │ └── common + │ └── package.json + └── package.json + +``` + +## Setup Visual Studio Code +The preferred development environment is Visual Studio Code. Clone *AASPortal*'s GIT repository. Open aasportal in Visual Studio Code. In a terminal window execute the the following commands: + +`npm install` + +and + +`npm run build -ws` + +restart Visual Studio Code. + +## Start AASPortal +The following command creates and executes a composed Docker image: + +`npm run start` + +Open one of the supported web browsers and go to the Web site: + + http://localhost/ + +Alternatively, the application can be started by specifying an Asset Administration Shell: + + http://localhost/?id='value' + +`value` can be the AAS identification: + + http://localhost/?id=http://boschrexroth.com/shells/0608842005/917004878 + +the identification base64URL encoded + + http://localhost/?id=aHR0cDovL2Jvc2NocmV4cm90aC5jb20vc2hlbGxzLzA2MDg4NDIwMDUvOTE3MDA0ODc4 + +or the name (idShort) of the AAS + + http://localhost/?id=Bosch_NexoPistolGripNutrunner + +# AASServer +ToDo. + +## Environment Variables +| Name | | default | +| ---------------- | --------------------------------------------------------------------- | ---------------------------------------------- | +| ASSETS | AASServer root directory local endpoints and templates. | './assets' | +| CONTENT_ROOT | The root directory where AASServer is located. | './' | +| CORS_ORIGIN | | '*' | +| ENDPOINTS | The URLs of the initial AAS container endpoints. | ['file:///samples'] | +| HTTPS_CERT_FILE | Certification file to enable HTTPS. | | +| HTTPS_KEY_FILE | Key file to enable HTTPS. | | +| JWT_EXPIRES_IN | The period for the validity of a JWT. | 604800 (1 week) | +| JWT_PUBLIC_KEY | Public key file for RS256 encryption. | | +| JWT_SECRET | Secret for HS256 encryption or private key file for RS256 encryption. | 'The quick brown fox jumps over the lazy dog.' | +| MAX_WORKERS | Number of background worker that scan AAS containers. | 8 | +| NODE_SERVER_PORT | The port number where AASServer is listening. | 80 | +| USER_STORAGE | URL of the user database. | './users' | +| TEMPLATE_STORAGE | URL of the template storage | | +| TIMEOUT | Timeout until a new scan starts (ms). | 5000 | +| WEB_ROOT | The root directory for static file resources. | './wwwroot' | + +## Endpoints +An endpoint is an URL and a unique name to an AAS container. An AAS container can be: +- AASX Server +- OPC UA Server +- AAS Registry +- Directory in a file system that contains *.aasx files + +## Users +AASPortal supports anonymous (guest) and authenticated access. The guest has limited read-only access to data and functions of AASPortal. AASPortal offers the possibility to manage data of registered users in a MongoDB. For this purpose, a URL to a MongoDB must be entered in the environment variable USER_STORAGE: + +`USER_STORAGE=mongodb://
:/aasportal-users` + +A local, file-based user database is available for testing purposes. + +## AAS Templates +Templates denote submodels or concrete submodel elements for creating and editing Asset Administration Shells. + +```txt +templates + ├── submodel + │ └── *.json + └── submodel-element + └── *.json +``` + +## OpenAPI (Swagger) +The AASServer provides an OpenAPI-compliant REST API. The Swagger UI is accessible via the URL: + +`http://localhost/api-docs` + +## Authentication with Json Web Tokens (JWT) +AASPortal uses JSON web tokens for authorization. Environment variables can be used to choose between HS256 or RS256 encryption. The expiration date of a token can also be defined via an environment variable. + +`JWT_EXPIRES_IN=`*``* + +The value is to be entered in seconds. By default, a token is valid for one week. + +### HS256 Encryption +HS256 (HMAC with SHA-256) involves a combination of a hashing function and one (secret) key that is shared between the two parties used to generate the hash that will serve as the signature. Since the same key is used both to generate the signature and to validate it, care must be taken to ensure that the key is not compromised. + +`JWT_SECRET=`*``* + +### RS256 Encryption +RS256 (RSA Signature with SHA-256) is an asymmetric algorithm, and it uses a public/private key pair: the identity provider has a private (secret) key used to generate the signature, and the consumer of the JWT gets a public key to validate the signature. + +`JWT_SECRET=`*``* + +`JWT_PUBLIC_KEY=`*``* + +# HTTPS +To enable HTTPS + +`HTTPS_CERT_FILE=`*``* + +`HTTPS_KEY_FILE=`*``* diff --git a/docs/source/images/AASPortal.png b/docs/source/images/AASPortal.png new file mode 100644 index 00000000..15697f8e Binary files /dev/null and b/docs/source/images/AASPortal.png differ diff --git a/docs/source/images/AASPortal_mid.png b/docs/source/images/AASPortal_mid.png new file mode 100644 index 00000000..556f581c Binary files /dev/null and b/docs/source/images/AASPortal_mid.png differ diff --git a/docs/source/images/AASPortal_smaller.png b/docs/source/images/AASPortal_smaller.png new file mode 100644 index 00000000..f5e789c6 Binary files /dev/null and b/docs/source/images/AASPortal_smaller.png differ diff --git a/docs/source/images/aas-document.png b/docs/source/images/aas-document.png new file mode 100644 index 00000000..b3f2b652 Binary files /dev/null and b/docs/source/images/aas-document.png differ diff --git a/docs/source/images/aas-portal-dependencies.png b/docs/source/images/aas-portal-dependencies.png new file mode 100644 index 00000000..ca46cf61 Binary files /dev/null and b/docs/source/images/aas-portal-dependencies.png differ diff --git a/docs/source/images/aas-portal-project.png b/docs/source/images/aas-portal-project.png new file mode 100644 index 00000000..84a8280f Binary files /dev/null and b/docs/source/images/aas-portal-project.png differ diff --git a/docs/source/images/aas-server-dependencies.png b/docs/source/images/aas-server-dependencies.png new file mode 100644 index 00000000..1c683b8c Binary files /dev/null and b/docs/source/images/aas-server-dependencies.png differ diff --git a/docs/source/images/main.png b/docs/source/images/main.png new file mode 100644 index 00000000..7f148d92 Binary files /dev/null and b/docs/source/images/main.png differ diff --git a/docs/source/index.md b/docs/source/index.md new file mode 100644 index 00000000..1dcaa1ea --- /dev/null +++ b/docs/source/index.md @@ -0,0 +1,45 @@ +# AASPortal +![AASPortal Logo <](./images/AASPortal_mid.png "AASPortal Logo") + +**AASPortal** is a Node.js based web portal for the visualization and management of Asset Administration Shells (AAS). The implementation uses the concepts of the document "Details of the Asset Administration Shell" published on https://www.plattform-i40.de and licensed under Creative Commons CC BY 4.0. + +Check out the [Getting Started](gettingstarted.md) section to learn how to setup Visual Studio Code and start using and developing the *AASPortal*. Learn more about the [Architecture](architecture.md) of *AASPortal*, and check out the [Usage](usage.md) section to learn about available search filters for AAS and which Endpoints can be connected to the *AASPortal*. + +*This project is under active development and we are looking forward to your active contributions!* + +```{toctree} +:hidden: +:caption: Getting Started +:maxdepth: 3 +gettingstarted.md +``` + +```{toctree} +:hidden: +:caption: Architecture +:maxdepth: 3 +Architecture +``` + +```{toctree} +:hidden: +:caption: Usage +:maxdepth: 3 +usage.md +``` + +```{toctree} +:hidden: +:caption: About +:maxdepth: 2 +about/about.md +``` + +```{toctree} +:hidden: +:caption: Changelog +:maxdepth: 2 +changelog/changelog.md +``` + +[![Documentation Status](https://readthedocs.org/projects/fpethig-rtd-tutorial/badge/?version=latest "Documentation Status")](https://fpethig-rtd-tutorial.readthedocs.io/en/latest/?badge=latest) diff --git a/docs/source/usage.md b/docs/source/usage.md new file mode 100644 index 00000000..ea5acc3b --- /dev/null +++ b/docs/source/usage.md @@ -0,0 +1,77 @@ +# Usage + +## Filter AAS Collection +This feature displays AAS in which a certain search text occurs. The search refers to the name, the identification and the endpoint type of the AAS. + +A search within the structure of an AAS is started if the search text begins with a `#`. It is possible to search for a specific model type with a specific name and, depending on the model type, a specific value. The search text has the following format: + +`#:[=, !=, <, <=, >=, >]` + +`#:=...` + +*Supported Model Types:* + + | Abbreviation | Model Type | + | ------------ | ---------------------------- | + | AAS | Asset Administration Shell | + | Asset | Asset | + | Cap | Capability | + | CD | Concept Description | + | DE | DataElement | + | DST | DataSpecification Template | + | InOut | inoutputVariable | + | In | inputVariable | + | Id | Identifier/id | + | Prop | Property | + | MLP | MultiLanguageProperty | + | Range | Range | + | Ent | Entity | + | Evt | Event | + | File | File | + | Blob | Blob | + | Opr | Operation | + | Out | outputVariable | + | Qfr | Qualifier | + | Ref | ReferenceElement | + | Rel | RelationshipElement | + | RelA | AnnotatedRelationshipElement | + | SM | Submodel | + | SMC | SubmodelElementCollection | + | SME | SubmodelElement | + | View | View | + +By using the logical operators `||` and / or `&&` several expressions can be combined in the search text. + +## Examples +All AAS that contain at least one operation element: + +`#Opr` + +All AAS that contain at least one submodel with the name *Nameplate*: + +`#SM:Nameplate` + +All AAS that contain at least one property with the value *SmartFactoryOWL*: + +`#Prop=SmartFactoryOWL` + +All AAS that contain at least one property with the name *Producer* and the value *SmartFactoryOWL*: + +`#Prop:producer=SmartFactoryOWL` + +All AAS where *RotationSpeed* is greater or equal then *5000*: + +`#Prop=RotationSpeed >= 5000` + +All AAS where *ProductionDate* is between *12/24/2022* and *12/31/2022*: + +`#Prop=ProductionDate = 12/24/2022...12/31/2022` + +## Supported Endpoints + +| Endpoint | Format | +| -------------- | ---------------------------------------------------------------- | +| AASXServer | `http://:51310` | +| AAS Registry | `http://:50000/registry/api/v1/registry/` | +| OPC UA (I4AAS) | `opc.tcp://:30001/I4AASServer` | +| Files | `file:///samples` | diff --git a/init-mongo.js b/init-mongo.js new file mode 100644 index 00000000..d5d0e379 --- /dev/null +++ b/init-mongo.js @@ -0,0 +1,10 @@ +db.createUser({ + user: 'aasportal@iosb-ina.fraunhofer.de', + pwd: 'aas-portal', + roles: [ + { + role: 'readWrite', + db: 'aasportal-users' + } + ] +}) \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..4942e576 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,54134 @@ +{ + "name": "aas-portal-project", + "version": "2.26.29", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "aas-portal-project", + "version": "2.26.29", + "license": "Apache-2.0", + "workspaces": [ + "./projects/common", + "./projects/aas-server", + "./projects/aas-lib", + "./projects/aas-portal" + ], + "devDependencies": { + "@semantic-release/git": "^10.0.1", + "@semantic-release/gitlab": "^12.0.5" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@angular-devkit/architect": { + "version": "0.1602.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.0.tgz", + "integrity": "sha512-ZRmUTBeD+uGr605eOHnsovEn6f1mOBI+kxP64DRvagNweX5TN04s3iyQ8jmLSAHQD9ush31LFxv3dVNxv3ceXQ==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.0", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/build-angular": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.0.tgz", + "integrity": "sha512-miylwjOqvlKmYrzS84bjRaJrecZxOXH9xsPVvQE8VBe8UKePJjRAL6yyOqXUOGtzlch2YmT98RAnuni7y0FEAw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "2.2.1", + "@angular-devkit/architect": "0.1602.0", + "@angular-devkit/build-webpack": "0.1602.0", + "@angular-devkit/core": "16.2.0", + "@babel/core": "7.22.9", + "@babel/generator": "7.22.9", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.22.6", + "@babel/plugin-proposal-async-generator-functions": "7.20.7", + "@babel/plugin-transform-async-to-generator": "7.22.5", + "@babel/plugin-transform-runtime": "7.22.9", + "@babel/preset-env": "7.22.9", + "@babel/runtime": "7.22.6", + "@babel/template": "7.22.5", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "16.2.0", + "@vitejs/plugin-basic-ssl": "1.0.1", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.14", + "babel-loader": "9.1.3", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "^4.21.5", + "chokidar": "3.5.3", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.20", + "css-loader": "6.8.1", + "esbuild-wasm": "0.18.17", + "fast-glob": "3.3.1", + "guess-parser": "0.4.22", + "https-proxy-agent": "5.0.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "karma-source-map-support": "1.4.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.30.1", + "mini-css-extract-plugin": "2.7.6", + "mrmime": "1.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "2.3.1", + "piscina": "4.0.0", + "postcss": "8.4.27", + "postcss-loader": "7.3.3", + "resolve-url-loader": "5.0.0", + "rxjs": "7.8.1", + "sass": "1.64.1", + "sass-loader": "13.3.2", + "semver": "7.5.4", + "source-map-loader": "4.0.1", + "source-map-support": "0.5.21", + "terser": "5.19.2", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.6.1", + "vite": "4.4.7", + "webpack": "5.88.2", + "webpack-dev-middleware": "6.1.1", + "webpack-dev-server": "4.15.1", + "webpack-merge": "5.9.0", + "webpack-subresource-integrity": "5.1.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "optionalDependencies": { + "esbuild": "0.18.17" + }, + "peerDependencies": { + "@angular/compiler-cli": "^16.0.0", + "@angular/localize": "^16.0.0", + "@angular/platform-server": "^16.0.0", + "@angular/service-worker": "^16.0.0", + "jest": "^29.5.0", + "jest-environment-jsdom": "^29.5.0", + "karma": "^6.3.0", + "ng-packagr": "^16.0.0", + "protractor": "^7.0.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "typescript": ">=4.9.3 <5.2" + }, + "peerDependenciesMeta": { + "@angular/localize": { + "optional": true + }, + "@angular/platform-server": { + "optional": true + }, + "@angular/service-worker": { + "optional": true + }, + "jest": { + "optional": true + }, + "jest-environment-jsdom": { + "optional": true + }, + "karma": { + "optional": true + }, + "ng-packagr": { + "optional": true + }, + "protractor": { + "optional": true + }, + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/android-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/darwin-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/freebsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-loong64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-mips64el": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-ppc64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-riscv64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-s390x": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/linux-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/netbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/openbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/sunos-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", + "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/@esbuild/win32-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@angular-devkit/build-angular/node_modules/esbuild": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" + } + }, + "node_modules/@angular-devkit/build-webpack": { + "version": "0.1602.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.0.tgz", + "integrity": "sha512-KdSr6iAcO30i/LIGL8mYi+d1buVXuDCp2dptzEJ4vxReOMFJca90KLwb+tVHEqqnDb0WkNfWm8Ii2QYh2FrNyA==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1602.0", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "webpack": "^5.30.0", + "webpack-dev-server": "^4.0.0" + } + }, + "node_modules/@angular-devkit/core": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.0.tgz", + "integrity": "sha512-l1k6Rqm3YM16BEn3CWyQKrk9xfu+2ux7Bw3oS+h1TO4/RoxO2PgHj8LLRh/WNrYVarhaqO7QZ5ePBkXNMkzJ1g==", + "dev": true, + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.0.tgz", + "integrity": "sha512-QMDJXPE0+YQJ9Ap3MMzb0v7rx6ZbBEokmHgpdIjN3eILYmbAdsSGE8HTV8NjS9nKmcyE9OGzFCMb7PFrDTlTAw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.0", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.1", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-eslint/builder": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.0.tgz", + "integrity": "sha512-KIkE2SI1twFKoCiF/k2VR3ojOcc7TD1xPyY4kbUrx/Gxp+XEzar7O29I/ztzL4eHPBM+Uh3/NwS/jvjjBxjgAg==", + "dev": true, + "dependencies": { + "@nx/devkit": "16.5.1", + "nx": "16.5.1" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/bundled-angular-compiler": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.1.0.tgz", + "integrity": "sha512-5EFAWXuFJADr3imo/ZYshY8s0K7U7wyysnE2LXnpT9PAi5rmkzt70UNZNRuamCbXr4tdIiu+fXWOj7tUuJKnnw==", + "dev": true + }, + "node_modules/@angular-eslint/eslint-plugin": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.1.0.tgz", + "integrity": "sha512-BFzzJJlgQgWc8avdSBkaDWAzNSUqcwWy0L1iZSBdXGoIOxj72kLbwe99emb8M+rUfCveljQkeM2pcYu8XLbJIA==", + "dev": true, + "dependencies": { + "@angular-eslint/utils": "16.1.0", + "@typescript-eslint/utils": "5.62.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/eslint-plugin-template": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.1.0.tgz", + "integrity": "sha512-wQHWR5vqWGgO7mqoG5ixXeplIlz/OmxBJE9QMLPTZE8GdaTx8+F/5J37OWh84zCpD3mOa/FHYZxBDm2MfUmA1Q==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "16.1.0", + "@angular-eslint/utils": "16.1.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "aria-query": "5.3.0", + "axobject-query": "3.1.1" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/schematics": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.1.0.tgz", + "integrity": "sha512-L1tmP3R2krHyveaRXAvn/SeDoBFNpS1VtPPrzZm1NYr1qPcAxf3NtG2nnoyVFu6WZGt59ZGHNQ/dZxnXvm0UGg==", + "dev": true, + "dependencies": { + "@angular-eslint/eslint-plugin": "16.1.0", + "@angular-eslint/eslint-plugin-template": "16.1.0", + "@nx/devkit": "16.5.1", + "ignore": "5.2.4", + "nx": "16.5.1", + "strip-json-comments": "3.1.1", + "tmp": "0.2.1" + }, + "peerDependencies": { + "@angular/cli": ">= 16.0.0 < 17.0.0" + } + }, + "node_modules/@angular-eslint/template-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.1.0.tgz", + "integrity": "sha512-DOQtzVehtbO7+BQ+FMOXRsxGRjHb3ve6M+S4qASKTiI+twtONjRODcHezD3N4PDkjpKPbOnk7YnFsHur5csUNw==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "16.1.0", + "eslint-scope": "^7.0.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular-eslint/utils": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.1.0.tgz", + "integrity": "sha512-u5XscYUq1F/7RuwyVIV2a280QL27lyQz434VYR+Np/oO21NGj5jxoRKb55xhXT9EFVs5Sy4JYeEUp6S75J/cUw==", + "dev": true, + "dependencies": { + "@angular-eslint/bundled-angular-compiler": "16.1.0", + "@typescript-eslint/utils": "5.62.0" + }, + "peerDependencies": { + "eslint": "^7.20.0 || ^8.0.0", + "typescript": "*" + } + }, + "node_modules/@angular/animations": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.1.tgz", + "integrity": "sha512-XVabK9fRKJaYPhW5wn8ySL4KL45N5Np+xOssWhLPDRDBdZjl62MExfpvMkamdkos6E1n1IGsy9wSemjnR4WKhg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "16.2.1" + } + }, + "node_modules/@angular/cli": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.0.tgz", + "integrity": "sha512-xT8vJOyw6Rc2364XDW2jHagLgKu7342ktd/lt+c0u6R+AB2XVFMePR7VceLohX9N/vRUsbQ0nVSZr+ru/hA+HA==", + "dev": true, + "dependencies": { + "@angular-devkit/architect": "0.1602.0", + "@angular-devkit/core": "16.2.0", + "@angular-devkit/schematics": "16.2.0", + "@schematics/angular": "16.2.0", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "4.1.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "npm-package-arg": "10.1.0", + "npm-pick-manifest": "8.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "pacote": "15.2.0", + "resolve": "1.22.2", + "semver": "7.5.4", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + }, + "bin": { + "ng": "bin/ng.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular/common": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.1.tgz", + "integrity": "sha512-druackA5JQpvfS8cD8DFtPRXGRKbhx3mQ778t1n6x3fXpIdGaAX+nSAgAKhIoF7fxWmu0KuHGzb+3BFlZRyTXw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "16.2.1", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/compiler": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.1.tgz", + "integrity": "sha512-dPauu+ESn79d66U9nBvnunNuBk/UMqnm7iL9Q31J8OKYN/4vrKbsO57pmULOft/GRAYsE3FdLBH0NkocFZKIMQ==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/core": "16.2.1" + }, + "peerDependenciesMeta": { + "@angular/core": { + "optional": true + } + } + }, + "node_modules/@angular/compiler-cli": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.1.tgz", + "integrity": "sha512-A5SyNZTZnXSCL5JVXHKbYj9p2dRYoeFnb6hGQFt2AuCcpUjVIIdwHtre3YzkKe5sFwepPctdoRe2fRXlTfTRjA==", + "dependencies": { + "@babel/core": "7.22.5", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "ng-xi18n": "bundles/src/bin/ng_xi18n.js", + "ngc": "bundles/src/bin/ngc.js", + "ngcc": "bundles/ngcc/index.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/compiler": "16.2.1", + "typescript": ">=4.9.3 <5.2" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/compiler-cli/node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/core": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.1.tgz", + "integrity": "sha512-Y+0jssQnJPovxMv9cDKYlp6BBHeFBLOHd/+FPv5IIGD1c7NwBP/TImJxCaIV78a57xnO8L0SFacDg/kULzvKrg==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "rxjs": "^6.5.3 || ^7.4.0", + "zone.js": "~0.13.0" + } + }, + "node_modules/@angular/forms": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.1.tgz", + "integrity": "sha512-cCygiLfBAsVHdtKmNptlk2IgXu0wjRc8kSiiSnJkfK6U/NiNg8ADMiN7iYgKW2TD1ZRw+7dYZV856lxEy2n0+A==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "16.2.1", + "@angular/core": "16.2.1", + "@angular/platform-browser": "16.2.1", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@angular/localize": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-16.2.1.tgz", + "integrity": "sha512-IMlDEuDNYtVTZ135ATm+YAksdCaFjkOsrtTPu3aIg08Dsyqw7awZ1lEmmmSpiflOqEfPjgHScLWhUMhER70aUg==", + "dependencies": { + "@babel/core": "7.22.5", + "fast-glob": "3.3.0", + "yargs": "^17.2.1" + }, + "bin": { + "localize-extract": "tools/bundles/src/extract/cli.js", + "localize-migrate": "tools/bundles/src/migrate/cli.js", + "localize-translate": "tools/bundles/src/translate/cli.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/compiler": "16.2.1", + "@angular/compiler-cli": "16.2.1" + } + }, + "node_modules/@angular/localize/node_modules/@babel/core": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@angular/localize/node_modules/fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@angular/localize/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@angular/platform-browser": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.1.tgz", + "integrity": "sha512-SH8zRiRAcw0B5/tVlEc5U/lN5F8g+JizSuu7BQvpCAQEDkM6IjF9LP36Bjav7JuadItbWLfT6peWYa1sJvax2w==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/animations": "16.2.1", + "@angular/common": "16.2.1", + "@angular/core": "16.2.1" + }, + "peerDependenciesMeta": { + "@angular/animations": { + "optional": true + } + } + }, + "node_modules/@angular/platform-browser-dynamic": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.1.tgz", + "integrity": "sha512-dKMCSrbD/joOMXM1mhDOKNDZ1BxwO9r9uu5ZxY0L/fWm/ousgMucNikLr38vBudgWM8CN6BuabzkxWKcqi3k4g==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "16.2.1", + "@angular/compiler": "16.2.1", + "@angular/core": "16.2.1", + "@angular/platform-browser": "16.2.1" + } + }, + "node_modules/@angular/router": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.1.tgz", + "integrity": "sha512-C0WfcktsC25G37unxdH/5I7PbkVBSEB1o+0DJK9/HG97r1yzEkptF6fbRIzDBTS7dX0NfWN/PTAKF0ep7YlHvA==", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": "16.2.1", + "@angular/core": "16.2.1", + "@angular/platform-browser": "16.2.1", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "node_modules/@babel/code-frame": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "dependencies": { + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", + "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.10", + "@babel/parser": "^7.22.10", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "dependencies": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "dependencies": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", + "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz", + "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", + "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", + "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-wrap-function": "^7.22.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", + "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", + "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", + "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz", + "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", + "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", + "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", + "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", + "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", + "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", + "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", + "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", + "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", + "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", + "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", + "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", + "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", + "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz", + "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", + "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", + "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz", + "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.7", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.5", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.5", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.6", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.5", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.5", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "node_modules/@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "dependencies": { + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "dependencies": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", + "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/console/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/console/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/console/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", + "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.6.2", + "@jest/reporters": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.6.2", + "jest-resolve-dependencies": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "jest-watcher": "^29.6.2", + "micromatch": "^4.0.4", + "pretty-format": "^29.6.2", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/environment": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", + "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "jest-mock": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", + "dev": true, + "dependencies": { + "expect": "^29.6.2", + "jest-snapshot": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", + "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.4.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", + "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", + "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", + "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/reporters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/reporters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", + "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", + "dev": true, + "dependencies": { + "@jest/console": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", + "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.6.2", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", + "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.6.2", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/transform/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/transform/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/@jest/transform/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/transform/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types": { + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@jest/types/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@jest/types/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/types/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jimp/bmp": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.10.tgz", + "integrity": "sha512-1UXRl1Nw1KptZ1r0ANqtXOst9vGH51dq7keVKQzyyTO2lz4dOaezS9StuSTNh+RmiHg/SVPaFRpPfB0S/ln4Kg==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "bmp-js": "^0.1.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/core": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.10.tgz", + "integrity": "sha512-ZKyrehVy6wu1PnBXIUpn/fXmyMRQiVSbvHDubgXz4bfTOao3GiOurKHjByutQIgozuAN6ZHWiSge1dKA+dex3w==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^16.5.4", + "isomorphic-fetch": "^3.0.0", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.6.0" + } + }, + "node_modules/@jimp/custom": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.10.tgz", + "integrity": "sha512-sPZkUYe1hu0iIgNisjizxPJqq2vaaKvkCkPoXq2U6UV3ZA1si/WVdrg25da3IcGIEV+83AoHgM8TvqlLgrCJsg==", + "dependencies": { + "@jimp/core": "^0.22.10" + } + }, + "node_modules/@jimp/gif": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.10.tgz", + "integrity": "sha512-yEX2dSpamvkSx1PPDWGnKeWDrBz0vrCKjVG/cn4Zr68MRRT75tbZIeOrBa+RiUpY3ho5ix7d36LkYvt3qfUIhQ==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "gifwrap": "^0.10.1", + "omggif": "^1.0.9" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/jpeg": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.10.tgz", + "integrity": "sha512-6bu98pAcVN4DY2oiDLC4TOgieX/lZrLd1tombWZOFCN5PBmqaHQxm7IUmT+Wj4faEvh8QSHgVLSA+2JQQRJWVA==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "jpeg-js": "^0.4.4" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.10.tgz", + "integrity": "sha512-6EI8Sl+mxYHEIy6Yteh6eknD+EZguKpNdr3sCKxNezmLR0+vK99vHcllo6uGSjXXiwtwS67Xqxn8SsoatL+UJQ==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.10.tgz", + "integrity": "sha512-4XRTWuPVdMXJeclJMisXPGizeHtTryVaVV5HnuQXpKqIZtzXReCCpNGH8q/i0kBQOQMXhGWS3mpqOEwtpPePKw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.10.tgz", + "integrity": "sha512-mhcwTO1ywRxiCgtLGge6tDDIDPlX6qkI3CY+BjgGG/XhVHccCddXgOGLdlf+5OuKIEF2Nqs0V01LQEQIJFTmEw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.10.tgz", + "integrity": "sha512-e4t3L7Kedd96E0x1XjsTM6NcgulKUU66HdFTao7Tc9FYJRFSlttARZ/C6LEryGDm/i69R6bJEpo7BkNz0YL55Q==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "tinycolor2": "^1.6.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.10.tgz", + "integrity": "sha512-eP8KrzctuEoqibQAxi9WhbnoRosydhiwg+IYya3dKuKDBTrD9UHt+ERlPQ/lTNWHzV/l4S1ntV3r9s9saJgsXA==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.10.tgz", + "integrity": "sha512-kJCwL5T1igfa0InCfkE7bBeqg26m46aoRt10ug+rvm11P6RrvRMGrgINFyIKB+mnB7CiyBN/MOula1CvLhSInQ==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5", + "@jimp/plugin-scale": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.10.tgz", + "integrity": "sha512-BOZ+YGaZlhU7c5ye65RxikicXH0Ki0It6/XHISvipR5WZrfjLjL2Ke20G+AGnwBQc76gKenVcMXVUCnEjtZV+Q==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.10.tgz", + "integrity": "sha512-llNiWWMTKISDXt5+cXI0GaFmZWAjlT+4fFLYf4eXquuL/9wZoQsEBhv2GdGd48mkiS8jZq1Nnb2Q4ehEPTvrzw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.10.tgz", + "integrity": "sha512-05WLmeV5M+P/0FS+bWf13hMew2X0oa8w9AtmevL2UyA/5GqiyvP2Xm5WfGQ8oFiiMvpnL6RFomJQOZtWca0C2w==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.10.tgz", + "integrity": "sha512-InjiXvc7Gkzrx8VWtU97kDqV7ENnhHGPULymJWeZaF2aicud9Fpk4iCtd/DcZIrk7Cbe60A8RwNXN00HXIbSCg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.10.tgz", + "integrity": "sha512-42GkGtTHWnhnwTMPVK/kXObZbkYIpQWfuIfy5EMEMk6zRj05zpv4vsjkKWfuemweZINwfvD7wDJF7FVFNNcZZg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-rotate": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-gaussian": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.10.tgz", + "integrity": "sha512-ykrG/6lTp9Q5YA8jS5XzwMHtRxb9HOFMgtmnrUZ8kU+BK8REecfy9Ic5BUEOjCYvS1a/xLsnrZQU07iiYxBxFg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-invert": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.10.tgz", + "integrity": "sha512-d8j9BlUJYs/c994t4azUWSWmQq4LLPG4ecm8m6SSNqap+S/HlVQGqjYhJEBbY9EXkOTYB9vBL9bqwSM1Rr6paA==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.10.tgz", + "integrity": "sha512-yRBs1230XZkz24uFTdTcSlZ0HXZpIWzM3iFQN56MzZ7USgdVZjPPDCQ8I9RpqfZ36nDflQkUO0wV7ucsi4ogow==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-normalize": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.10.tgz", + "integrity": "sha512-Wk9GX6eJMchX/ZAazVa70Fagu+OXMvHiPY+HrcEwcclL+p1wo8xAHEsf9iKno7Ja4EU9lLhbBRY5hYJyiKMEkg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.10.tgz", + "integrity": "sha512-1U3VloIR+beE1kWPdGEJMiE2h1Do29iv3w8sBbvPyRP4qXxRFcDpmCGtctsrKmb1krlBFlj8ubyAY90xL+5n9w==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "load-bmfont": "^1.4.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.10.tgz", + "integrity": "sha512-ixomxVcnAONXDgaq0opvAx4UAOiEhOA/tipuhFFOvPKFd4yf1BAnEviB5maB0SBHHkJXPUSzDp/73xVTMGSe7g==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.10.tgz", + "integrity": "sha512-eeFX8dnRyf3LAdsdXWKWuN18hLRg8zy1cP0cP9rHzQVWRK7ck/QsLxK1vHq7MADGwQalNaNTJ9SQxH6c8mz6jw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blit": ">=0.3.5", + "@jimp/plugin-crop": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-scale": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.10.tgz", + "integrity": "sha512-TG/H0oUN69C9ArBCZg4PmuoixFVKIiru8282KzSB/Tp1I0xwX0XLTv3dJ5pobPlIgPcB+TmD4xAIdkCT4rtWxg==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-shadow": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.10.tgz", + "integrity": "sha512-TN9xm6fI7XfxbMUQqFPZjv59Xdpf0tSiAQdINB4g6pJMWiVANR/74OtDONoy3KKpenu5Y38s+FkrtID/KcQAhw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-blur": ">=0.3.5", + "@jimp/plugin-resize": ">=0.3.5" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.10.tgz", + "integrity": "sha512-DA2lSnU0TgIRbAgmXaxroYw3Ad6J2DOFEoJp0NleSm2h3GWbZEE5yW9U2B6hD3iqn4AenG4E2b2WzHXZyzSutw==", + "dependencies": { + "@jimp/utils": "^0.22.10" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5", + "@jimp/plugin-color": ">=0.8.0", + "@jimp/plugin-resize": ">=0.8.0" + } + }, + "node_modules/@jimp/plugins": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.10.tgz", + "integrity": "sha512-KDMZyM6pmvS8freB+UBLko1TO/k4D7URS/nphCozuH+P7i3UMe7NdckXKJ8u+WD6sqN0YFYvBehpkpnUiw/91w==", + "dependencies": { + "@jimp/plugin-blit": "^0.22.10", + "@jimp/plugin-blur": "^0.22.10", + "@jimp/plugin-circle": "^0.22.10", + "@jimp/plugin-color": "^0.22.10", + "@jimp/plugin-contain": "^0.22.10", + "@jimp/plugin-cover": "^0.22.10", + "@jimp/plugin-crop": "^0.22.10", + "@jimp/plugin-displace": "^0.22.10", + "@jimp/plugin-dither": "^0.22.10", + "@jimp/plugin-fisheye": "^0.22.10", + "@jimp/plugin-flip": "^0.22.10", + "@jimp/plugin-gaussian": "^0.22.10", + "@jimp/plugin-invert": "^0.22.10", + "@jimp/plugin-mask": "^0.22.10", + "@jimp/plugin-normalize": "^0.22.10", + "@jimp/plugin-print": "^0.22.10", + "@jimp/plugin-resize": "^0.22.10", + "@jimp/plugin-rotate": "^0.22.10", + "@jimp/plugin-scale": "^0.22.10", + "@jimp/plugin-shadow": "^0.22.10", + "@jimp/plugin-threshold": "^0.22.10", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/png": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.10.tgz", + "integrity": "sha512-RYinU7tZToeeR2g2qAMn42AU+8OUHjXPKZZ9RkmoL4bguA1xyZWaSdr22/FBkmnHhOERRlr02KPDN1OTOYHLDQ==", + "dependencies": { + "@jimp/utils": "^0.22.10", + "pngjs": "^6.0.0" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/tiff": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.10.tgz", + "integrity": "sha512-OaivlSYzpNTHyH/h7pEtl3A7F7TbsgytZs52GLX/xITW92ffgDgT6PkldIrMrET6ERh/hdijNQiew7IoEEr2og==", + "dependencies": { + "utif2": "^4.0.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/types": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.10.tgz", + "integrity": "sha512-u/r+XYzbCx4zZukDmxx8S0er3Yq3iDPI6+31WKX0N18i2qPPJYcn8qwIFurfupRumGvJ8SlGLCgt/T+Y8zzUIw==", + "dependencies": { + "@jimp/bmp": "^0.22.10", + "@jimp/gif": "^0.22.10", + "@jimp/jpeg": "^0.22.10", + "@jimp/png": "^0.22.10", + "@jimp/tiff": "^0.22.10", + "timm": "^1.6.1" + }, + "peerDependencies": { + "@jimp/custom": ">=0.3.5" + } + }, + "node_modules/@jimp/utils": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.10.tgz", + "integrity": "sha512-ztlOK9Mm2iLG2AMoabzM4i3WZ/FtshcgsJCbZCRUs/DKoeS2tySRJTnQZ1b7Roq0M4Ce+FUAxnCAcBV0q7PH9w==", + "dependencies": { + "regenerator-runtime": "^0.13.3" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "node_modules/@ng-bootstrap/ng-bootstrap": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-15.1.1.tgz", + "integrity": "sha512-nZlIMMggtI3IHkGs0XPrUIUdpeEzQvfGV9M4I9IvCqiS2n4RwWoUvWK1ICo4csZqFNBDlCQx956gO6ZZUSL2mw==", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/common": "^16.0.0", + "@angular/core": "^16.0.0", + "@angular/forms": "^16.0.0", + "@angular/localize": "^16.0.0", + "@popperjs/core": "^2.11.6", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, + "node_modules/@ngrx/effects": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-16.2.0.tgz", + "integrity": "sha512-zZfq47LNoiRK+uS66Xm36mN07zm11AER1D9lTalX/G6jrV0bywgnAaukNNav9E33ZRrPEnCD8uu9BXZoboEYgA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "^16.0.0", + "@ngrx/store": "16.2.0", + "rxjs": "^6.5.3 || ^7.5.0" + } + }, + "node_modules/@ngrx/eslint-plugin": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/eslint-plugin/-/eslint-plugin-16.2.0.tgz", + "integrity": "sha512-BeCBRLQge0OIUTS1bCNfXB0WjAdXvHl8RgdrkQ4n4gsvvfzO8zetNmQREcHJsvpyMz3YjJuiOueuaiBRdbZfMA==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.4.0", + "eslint-etc": "^5.1.0", + "semver": "^7.3.5", + "strip-json-comments": "3.1.1" + }, + "peerDependencies": { + "eslint": ">=8.0.0", + "typescript": ">=4.4.0" + } + }, + "node_modules/@ngrx/store": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-16.2.0.tgz", + "integrity": "sha512-C7oIUC87xXV+1dTGUwYG/L4p0IZdYv/Ou1nTL/LffyAHllmmygTA5gzLB87abLOhucAxlFIQMQ8t/GSxdk/+QA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "peerDependencies": { + "@angular/core": "^16.0.0", + "rxjs": "^6.5.3 || ^7.5.0" + } + }, + "node_modules/@ngtools/webpack": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.0.tgz", + "integrity": "sha512-c9jv4r7GnLTpnPOeF+a9yAm/3/2wwl9lMBU32i9hlY+q/Hqde4PiL95bUOLnRRL1I64DV7BFTlSZqSPgDpFXZQ==", + "dev": true, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^16.0.0", + "typescript": ">=4.9.3 <5.2", + "webpack": "^5.54.0" + } + }, + "node_modules/@ngx-translate/core": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-15.0.0.tgz", + "integrity": "sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==", + "engines": { + "node": "^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, + "node_modules/@ngx-translate/http-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz", + "integrity": "sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==", + "engines": { + "node": "^16.13.0 || >=18.10.0" + }, + "peerDependencies": { + "@angular/common": ">=16.0.0", + "@angular/core": ">=16.0.0", + "@ngx-translate/core": ">=15.0.0", + "rxjs": "^6.5.5 || ^7.4.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/git/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@npmcli/git/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/promise-spawn/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "dev": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@npmcli/run-script/node_modules/which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@nrwl/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-NB+DE/+AFJ7lKH/WBFyatJEhcZGj25F24ncDkwjZ6MzEiSOGOJS0LaV/R+VUsmS5EHTPXYOpn3zHWWAcJhyOmA==", + "dev": true, + "dependencies": { + "@nx/devkit": "16.5.1" + } + }, + "node_modules/@nrwl/tao": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.5.1.tgz", + "integrity": "sha512-x+gi/fKdM6uQNIti9exFlm3V5LBP3Y8vOEziO42HdOigyrXa0S0HD2WMpccmp6PclYKhwEDUjKJ39xh5sdh4Ig==", + "dev": true, + "dependencies": { + "nx": "16.5.1" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==", + "dev": true, + "dependencies": { + "@nrwl/devkit": "16.5.1", + "ejs": "^3.1.7", + "ignore": "^5.0.4", + "semver": "7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "nx": ">= 15 <= 17" + } + }, + "node_modules/@nx/devkit/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/devkit/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@nx/devkit/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.5.1.tgz", + "integrity": "sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-darwin-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.5.1.tgz", + "integrity": "sha512-j9HmL1l8k7EVJ3eOM5y8COF93gqrydpxCDoz23ZEtsY+JHY77VAiRQsmqBgEx9GGA2dXi9VEdS67B0+1vKariw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-freebsd-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.5.1.tgz", + "integrity": "sha512-CXSPT01aVS869tvCCF2tZ7LnCa8l41wJ3mTVtWBkjmRde68E5Up093hklRMyXb3kfiDYlfIKWGwrV4r0eH6x1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.5.1.tgz", + "integrity": "sha512-BhrumqJSZCWFfLFUKl4CAUwR0Y0G2H5EfFVGKivVecEQbb+INAek1aa6c89evg2/OvetQYsJ+51QknskwqvLsA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.5.1.tgz", + "integrity": "sha512-x7MsSG0W+X43WVv7JhiSq2eKvH2suNKdlUHEG09Yt0vm3z0bhtym1UCMUg3IUAK7jy9hhLeDaFVFkC6zo+H/XQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.5.1.tgz", + "integrity": "sha512-J+/v/mFjOm74I0PNtH5Ka+fDd+/dWbKhpcZ2R1/6b9agzZk+Ff/SrwJcSYFXXWKbPX+uQ4RcJoytT06Zs3s0ow==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.5.1.tgz", + "integrity": "sha512-igooWJ5YxQ94Zft7IqgL+Lw0qHaY15Btw4gfK756g/YTYLZEt4tTvR1y6RnK/wdpE3sa68bFTLVBNCGTyiTiDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-linux-x64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.5.1.tgz", + "integrity": "sha512-zF/exnPqFYbrLAduGhTmZ7zNEyADid2bzNQiIjJkh8Y6NpDwrQIwVIyvIxqynsjMrIs51kBH+8TUjKjj2Jgf5A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.5.1.tgz", + "integrity": "sha512-qtqiLS9Y9TYyAbbpq58kRoOroko4ZXg5oWVqIWFHoxc5bGPweQSJCROEqd1AOl2ZDC6BxfuVHfhDDop1kK05WA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.5.1.tgz", + "integrity": "sha512-kUJBLakK7iyA9WfsGGQBVennA4jwf5XIgm0lu35oMOphtZIluvzItMt0EYBmylEROpmpEIhHq0P6J9FA+WH0Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/types": "^11.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^11.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "dev": true, + "peer": true + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", + "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/types": "^11.0.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.0.tgz", + "integrity": "sha512-a1/A4A+PB1QoAHQfLJxGHhLfSAT03bR1jJz3GgQJZvty2ozawFWs93MiBQXO7SL2YbO7CIq0Goj4qLOBj8JeMQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": ">=5" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-7.0.0.tgz", + "integrity": "sha512-KL2k/d0uANc8XqP5S64YcNFCudR3F5AaKO39XWdUtlJIjT9Ni79ekWJ6Kj5xvAw87udkOMEPcVf9xEge2+ahew==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/types": "^11.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "^5.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.1.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/types": "^11.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", + "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@peculiar/asn1-cms": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.6.tgz", + "integrity": "sha512-Kr0XsyjuElTc4NijuPYyd6YkTlbz0KCuoWnNkfPFhXjHTzbUIh/s15ixjxLj8XDrXsI1aPQp3D64uHbrs3Kuyg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-csr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.6.tgz", + "integrity": "sha512-gCTEB/PvUxapmxo4SzGZT1JtEdevRnphRGZZmc9oJE7+pLuj2Px0Q6x+w8VvObfozA3pyPRTq+Wkocnu64+oLw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.6.tgz", + "integrity": "sha512-Hu1xzMJQWv8/GvzOiinaE6XiD1/kEhq2C/V89UEoWeZ2fLUcGNIvMxOr/pMyL0OmpRWj/mhCTXOZp4PP+a0aTg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pfx": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.6.tgz", + "integrity": "sha512-bScrrpQ59mppcoZLkDEW/Wruu+daSWQxpR2vqGjg69+v7VoQ1Le/Elm10ObfNShV2eNNridNQcOQvsHMLvUOCg==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-rsa": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pkcs8": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.6.tgz", + "integrity": "sha512-poqgdjsHNiyR0gnxP8l5VjRInSgpQvOM3zLULF/ZQW67uUsEiuPfplvaNJUlNqNOCd2szGo9jKW9+JmVVpWojA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-pkcs9": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.6.tgz", + "integrity": "sha512-uaxSBF60glccuu5BEZvoPsaJzebVYcQRjXx2wXsGe7Grz/BXtq5RQAJ/3i9fEXawFK/zIbvbXBBpy07cnvrqhA==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pfx": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.6.tgz", + "integrity": "sha512-DswjJyAXZnvESuImGNTvbNKvh1XApBVqU+r3UmrFFTAI23gv62byl0f5OFKWTNhCf66WQrd3sklpsCZc/4+jwA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", + "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.6.tgz", + "integrity": "sha512-dRwX31R1lcbIdzbztiMvLNTDoGptxdV7HocNx87LfKU0fEWh7fTWJjx4oV+glETSy6heF/hJHB2J4RGB3vVSYg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "ipaddr.js": "^2.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/asn1-x509-attr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.6.tgz", + "integrity": "sha512-x5Kax8xp3fz+JSc+4Sq0/SUXIdbJeOePibYqvjHMGkP6AoeCOVcP+gg7rZRRGkTlDSyQnAoUTgTEsfAfFEd1/g==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", + "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.5.0", + "webcrypto-core": "^1.7.7" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@peculiar/x509": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.9.4.tgz", + "integrity": "sha512-Gcic9DV965oR2qr1uoir+mM6RQnxKQZpkz1bD4kiYSZtMBF2qWVfsCOA6748+87L85xoRrQrb58/vULG1/8vXg==", + "dependencies": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-csr": "^2.3.6", + "@peculiar/asn1-ecc": "^2.3.6", + "@peculiar/asn1-pkcs9": "^2.3.6", + "@peculiar/asn1-rsa": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "pvtsutils": "^1.3.3", + "reflect-metadata": "^0.1.13", + "tslib": "^2.6.1", + "tsyringe": "^4.8.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "dev": true, + "peer": true, + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", + "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz", + "integrity": "sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.3.tgz", + "integrity": "sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==", + "dev": true, + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@schematics/angular": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.0.tgz", + "integrity": "sha512-Ib0/ZCkjWt7a5p3209JVwEWwf41v03K3ylvlxLIEo1ZGijAZAlrBj4GrA5YQ+TmPm2hRyt+owss7x91/x+i0Gw==", + "dev": true, + "dependencies": { + "@angular-devkit/core": "16.2.0", + "@angular-devkit/schematics": "16.2.0", + "jsonc-parser": "3.2.0" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@semantic-release/commit-analyzer": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-10.0.1.tgz", + "integrity": "sha512-9ejHzTAijYs9z246sY/dKBatmOPcd0GQ7lH4MgLCkv1q4GCiDZRkjHJkaQZXZVaK7mJybS+sH3Ng6G8i3pYMGQ==", + "dev": true, + "peer": true, + "dependencies": { + "conventional-changelog-angular": "^6.0.0", + "conventional-commits-filter": "^3.0.0", + "conventional-commits-parser": "^4.0.0", + "debug": "^4.0.0", + "import-from": "^4.0.0", + "lodash-es": "^4.17.21", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", + "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", + "dev": true, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@semantic-release/git": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", + "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/github": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-9.0.4.tgz", + "integrity": "sha512-kQCGFAsBErvCR6hzNuzu63cj4erQN2krm9zQlg8vl4j5X0mL0d/Ras0wmL5Gkr1TuSS2lweME7M4J5zvtDDDSA==", + "dev": true, + "peer": true, + "dependencies": { + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^8.0.0", + "@octokit/plugin-retry": "^6.0.0", + "@octokit/plugin-throttling": "^7.0.0", + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^4.0.1", + "debug": "^4.3.4", + "dir-glob": "^3.0.1", + "globby": "^13.1.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "issue-parser": "^6.0.0", + "lodash-es": "^4.17.21", + "mime": "^3.0.0", + "p-filter": "^3.0.0", + "url-join": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@semantic-release/github/node_modules/agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "peer": true, + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@semantic-release/github/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "peer": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "peer": true, + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@semantic-release/github/node_modules/https-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.1.tgz", + "integrity": "sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==", + "dev": true, + "peer": true, + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@semantic-release/github/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "peer": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@semantic-release/github/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/github/node_modules/url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/@semantic-release/gitlab": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@semantic-release/gitlab/-/gitlab-12.0.5.tgz", + "integrity": "sha512-7iLeD5J0BF34jBUKTYbJT+Z+J9j55PXeR78wKWq9Lqbc8Y566D0g8BNVl9HUVSv6eipELdkqS+zMyTDGqiUL1w==", + "dev": true, + "dependencies": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^4.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "escape-string-regexp": "^5.0.0", + "form-data": "^4.0.0", + "fs-extra": "^11.0.0", + "globby": "^11.0.0", + "got": "^13.0.0", + "hpagent": "^1.0.0", + "lodash-es": "^4.17.21", + "parse-url": "^8.0.0", + "url-join": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/gitlab/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-10.0.4.tgz", + "integrity": "sha512-6R3timIQ7VoL2QWRkc9DG8v74RQtRp7UOe/2KbNaqwJ815qOibAv65bH3RtTEhs4axEaHoZf7HDgFs5opaZ9Jw==", + "dev": true, + "peer": true, + "dependencies": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^4.0.1", + "execa": "^7.0.0", + "fs-extra": "^11.0.0", + "lodash-es": "^4.17.21", + "nerf-dart": "^1.0.0", + "normalize-url": "^8.0.0", + "npm": "^9.5.0", + "rc": "^1.2.8", + "read-pkg": "^8.0.0", + "registry-auth-token": "^5.0.0", + "semver": "^7.1.2", + "tempy": "^3.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@semantic-release/npm/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/@semantic-release/npm/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/@semantic-release/npm/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "peer": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/npm/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@semantic-release/release-notes-generator": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-11.0.4.tgz", + "integrity": "sha512-j0Znnwq9IdWTCGzqSlkLv4MpALTsVDZxcVESzJCNN8pK2BYQlYaKsdZ1Ea/+7RlppI3vjhEi33ZKmjSGY1FLKw==", + "dev": true, + "peer": true, + "dependencies": { + "conventional-changelog-angular": "^6.0.0", + "conventional-changelog-writer": "^6.0.0", + "conventional-commits-filter": "^3.0.0", + "conventional-commits-parser": "^4.0.0", + "debug": "^4.0.0", + "get-stream": "^7.0.0", + "import-from": "^4.0.0", + "into-stream": "^7.0.0", + "lodash-es": "^4.17.21", + "read-pkg-up": "^10.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "semantic-release": ">=20.1.0" + } + }, + "node_modules/@semantic-release/release-notes-generator/node_modules/get-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", + "integrity": "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "node_modules/@ster5/global-mutex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ster5/global-mutex/-/global-mutex-2.0.0.tgz", + "integrity": "sha512-nlp5BM4E7ybkGt6ouZsohSnliWtXgRoUWHMl8uzi64gKwZSONsssEstfBGnQ0OpdQlE0HBP0qq9RDxP0JTW57w==", + "dependencies": { + "@types/proper-lockfile": "^4.1.2", + "proper-lockfile": "^4.1.2" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "node_modules/@tsoa/cli": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@tsoa/cli/-/cli-5.1.1.tgz", + "integrity": "sha512-krvp6Qr2yPUfj6bJRs0vwQhLANeINzyusNnzgSoerDfBBBnjZ+VhvR4rWguAcLc1kgP/kFAJz5kIp4iqLFmILQ==", + "dependencies": { + "@tsoa/runtime": "^5.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.1.0", + "glob": "^8.0.3", + "handlebars": "^4.7.7", + "merge": "^2.1.1", + "minimatch": "^5.1.0", + "typescript": "^4.9.5", + "validator": "^13.7.0", + "yamljs": "^0.3.0", + "yargs": "^17.5.1" + }, + "bin": { + "tsoa": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "yarn": ">=1.9.4" + } + }, + "node_modules/@tsoa/cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tsoa/cli/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@tsoa/cli/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@tsoa/cli/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tsoa/cli/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/@tsoa/runtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@tsoa/runtime/-/runtime-5.0.0.tgz", + "integrity": "sha512-DY0x7ZhNRF9FcwCZXQQbQhVj3bfZe0LScNyqp0c8PhDTj0gRMjY4ESVpihopRzhQtamReJoDRg3FhEu4BlSVtA==", + "dependencies": { + "@types/multer": "^1.4.7", + "promise.any": "^2.0.5", + "reflect-metadata": "^0.1.13", + "validator": "^13.7.0" + }, + "engines": { + "node": ">=12.0.0", + "yarn": ">=1.9.4" + } + }, + "node_modules/@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", + "dev": true, + "dependencies": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tufjs/models/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@types/async": { + "version": "3.2.20", + "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.20.tgz", + "integrity": "sha512-6jSBQQugzyX1aWto0CbvOnmxrU9tMoXfA9gc4IrLEtvr3dTwSg5GLGoWiZnGLI6UG/kqpB3JOQKQrqnhUWGKQA==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/bcryptjs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", + "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==", + "dev": true + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bootstrap": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.6.tgz", + "integrity": "sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==", + "dev": true, + "dependencies": { + "@popperjs/core": "^2.9.2" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "dev": true, + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "node_modules/@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, + "node_modules/@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/dns-packet": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.2.4.tgz", + "integrity": "sha512-OAruArypdNxR/tzbmrtoyEuXeNTLaZCpO19BXaNC10T5ACIbvjmvhmV2RDEy2eLc3w8IjK7SY3cvUCcAW+sfoQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "dev": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jasmine": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.5.tgz", + "integrity": "sha512-9YHUdvuNDDRJYXZwHqSsO72Ok0vmqoJbNn73ttyITQp/VA60SarnZ+MPLD37rJAhVoKp+9BWOvJP5tHIRfZylQ==", + "dev": true + }, + "node_modules/@types/jquery": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", + "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", + "dev": true, + "dependencies": { + "@types/sizzle": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/jsrsasign": { + "version": "10.5.8", + "resolved": "https://registry.npmjs.org/@types/jsrsasign/-/jsrsasign-10.5.8.tgz", + "integrity": "sha512-1oZ3TbarAhKtKUpyrCIqXpbx3ZAfoSulleJs6/UzzyYty0ut+kjRX7zHLAaHwVIuw8CBjIymwW4J2LK944HoHQ==" + }, + "node_modules/@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.8.tgz", + "integrity": "sha512-euY3XQcZmIzSy7YH5+Unb3b2X12Wtk54YWINBvvGQ5SmMvwb11JQskGsfkH/5HXK77Kr8GF0wkVDIxzAisWtog==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true, + "peer": true + }, + "node_modules/@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/morgan": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.4.tgz", + "integrity": "sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/multicast-dns": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.1.tgz", + "integrity": "sha512-A2PmB8MRcNVEkw6wzGT5rtBHqyHOVjiRMkJH+zpJKXipSi+GGkHg6JjNFApDiYK9WefJqkVG0taln1VMl4TGfw==", + "dependencies": { + "@types/dns-packet": "*", + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", + "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" + }, + "node_modules/@types/nodemailer": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.9.tgz", + "integrity": "sha512-XYG8Gv+sHjaOtUpiuytahMy2mM3rectgroNbs6R3djZEKmPNiIJwe9KqOJBGzKKnNZNKvnuvmugBgpq3w/S0ig==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true, + "peer": true + }, + "node_modules/@types/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-kd4LMvcnpYkspDcp7rmXKedn8iJSCoa331zRRamUp5oanKt/CefbEGPQP7G89enz7sKD4bvsr8mHSsC8j5WOvA==", + "dependencies": { + "@types/retry": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dev": true, + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "node_modules/@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "node_modules/@types/superagent": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "dev": true, + "dependencies": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "node_modules/@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "dependencies": { + "@types/superagent": "*" + } + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz", + "integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" + }, + "node_modules/@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.0.tgz", + "integrity": "sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.4.0", + "@typescript-eslint/type-utils": "6.4.0", + "@typescript-eslint/utils": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.0.tgz", + "integrity": "sha512-TvqrUFFyGY0cX3WgDHcdl2/mMCWCDv/0thTtx/ODMY1QhEiyFtv/OlLaNIiYLwRpAxAtOLOY9SUf1H3Q3dlwAg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "6.4.0", + "@typescript-eslint/utils": "6.4.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.0.tgz", + "integrity": "sha512-BvvwryBQpECPGo8PwF/y/q+yacg8Hn/2XS+DqL/oRsOPK+RPt29h5Ui5dqOKHDlbXrAeHUTnyG3wZA0KTDxRZw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.4.0", + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/typescript-estree": "6.4.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.0.tgz", + "integrity": "sha512-I1Ah1irl033uxjxO9Xql7+biL3YD7w9IU8zF+xlzD/YxY6a4b7DYA08PXUUCbm2sEljwJF6ERFy2kTGAGcNilg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "6.4.0", + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/typescript-estree": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.0.tgz", + "integrity": "sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.0.tgz", + "integrity": "sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.0.tgz", + "integrity": "sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.0.tgz", + "integrity": "sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.4.0", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-basic-ssl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", + "integrity": "sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==", + "dev": true, + "engines": { + "node": ">=14.6.0" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@wessberg/ts-evaluator": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/@wessberg/ts-evaluator/-/ts-evaluator-0.0.27.tgz", + "integrity": "sha512-7gOpVm3yYojUp/Yn7F4ZybJRxyqfMNf0LXK5KJiawbPfL0XTsJV+0mgrEDjOIR6Bi0OYk2Cyg4tjFu1r8MCZaA==", + "deprecated": "this package has been renamed to ts-evaluator. Please install ts-evaluator instead", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "jsdom": "^16.4.0", + "object-path": "^0.11.5", + "tslib": "^2.0.3" + }, + "engines": { + "node": ">=10.1.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/wessberg/ts-evaluator?sponsor=1" + }, + "peerDependencies": { + "typescript": ">=3.2.x || >= 4.x" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@wessberg/ts-evaluator/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wessberg/ts-evaluator/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "node_modules/@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.15.0" + } + }, + "node_modules/@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@zkochan/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aas-lib": { + "resolved": "projects/aas-lib", + "link": true + }, + "node_modules/aas-portal": { + "resolved": "projects/aas-portal", + "link": true + }, + "node_modules/aas-server": { + "resolved": "projects/aas-server", + "link": true + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "engines": { + "node": ">=8.9" + } + }, + "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", + "dev": true, + "peer": true + }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argv-formatter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", + "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", + "dev": true, + "peer": true + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "peer": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", + "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "peer": true, + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/babel-jest": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", + "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.6.2", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.5.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-jest/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/babel-jest/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/babel-jest/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dev": true, + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", + "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz", + "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2", + "core-js-compat": "^3.31.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", + "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.4.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-import-meta": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-import-meta/-/babel-plugin-transform-import-meta-2.2.1.tgz", + "integrity": "sha512-AxNh27Pcg8Kt112RGa3Vod2QS2YXKKJ6+nSvRtv7qQTJAdx0MZa4UHZ4lnxHUWA2MNbLuZQv5FVab4P1CoLOWw==", + "dev": true, + "dependencies": { + "@babel/template": "^7.4.4", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@babel/core": "^7.10.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.5.0", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==", + "dependencies": { + "precond": "0.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", + "peer": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true, + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "peer": true + }, + "node_modules/better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha512-bYeph2DFlpK1XmGs6fvlLRUN29QISM3GBuUwSFsMY2XRx4AvC0WNCS57j4c/xGrK2RS24C1w3YoBOsw9fT46tQ==", + "dependencies": { + "callsite": "1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/bonjour-service/node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "node_modules/bootstrap": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.1.tgz", + "integrity": "sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, + "node_modules/bootstrap-icons": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.5.tgz", + "integrity": "sha512-oSX26F37V7QV7NCE53PPEL45d7EGXmBgHG3pDpZvcRaKVzWMqIRL9wcqJUyEha1esFtM3NJzvmxFXDxjJYD0jQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ] + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true, + "peer": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "dependencies": { + "fast-json-stable-stringify": "2.x" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "engines": { + "node": ">=14.20.1" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz", + "integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==", + "peer": true + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.13", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.13.tgz", + "integrity": "sha512-3SD4rrMu1msNGEtNSt8Od6enwdo//U9s4ykmXfA2TD58kcLkCobtCDiby7kNyj7a/Q7lz/mAesAFI54rTdnvBA==", + "dev": true, + "dependencies": { + "@types/http-cache-semantics": "^4.0.1", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==", + "engines": { + "node": "*" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "peer": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001521", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", + "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "dev": true, + "peer": true, + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/chart.js": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz", + "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=7" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "dev": true, + "peer": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", + "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/common": { + "resolved": "projects/common", + "link": true + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "peer": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "peer": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "peer": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/connect/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/connect/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", + "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "dev": true, + "peer": true, + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", + "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", + "dev": true, + "peer": true, + "dependencies": { + "conventional-commits-filter": "^3.0.0", + "dateformat": "^3.0.3", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^8.1.2", + "semver": "^7.0.0", + "split": "^1.0.1" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", + "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", + "dev": true, + "peer": true, + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", + "dev": true, + "peer": true, + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js-compat": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.0.tgz", + "integrity": "sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==", + "dev": true, + "dependencies": { + "browserslist": "^4.21.9" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dev": true, + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/cosmiconfig/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/cosmiconfig/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/critters": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", + "integrity": "sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "pretty-bytes": "^5.3.0" + } + }, + "node_modules/critters/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/critters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/critters/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/critters/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/critters/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/critters/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "peer": true, + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", + "dev": true + }, + "node_modules/custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "dev": true + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "peer": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "peer": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "peer": true + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/dequeue": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/dequeue/-/dequeue-1.0.5.tgz", + "integrity": "sha512-2FIVJZTaWhUj0Y2uKmDAasTP6ZwFWRjkRc01MYN5jFm96iIzkYyNzGADfJ13C5W7CTN7XO9mBYDcVB68eNybBA==", + "engines": { + "node": "*" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "dev": true + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "node_modules/dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "dev": true, + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "dependencies": { + "webidl-conversions": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/domexception/node_modules/webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "peer": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.494", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.494.tgz", + "integrity": "sha512-KF7wtsFFDu4ws1ZsSOt4pdmO1yWVNWCFtijVYZPUeW4SV7/hy/AESjLn/+qIWgq7mHscNOKAwN5AIM1+YAy+Ww==" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/engine.io": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", + "dev": true, + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/engine.io/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "dev": true + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-ci": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-9.1.1.tgz", + "integrity": "sha512-Im2yEWeF4b2RAMAaWvGioXk6m0UNaIjD8hj28j2ij5ldnIFrDQT0+pzDvpbRkcjurhXhf/AsBKv8P2rtmGi9Aw==", + "dev": true, + "peer": true, + "dependencies": { + "execa": "^7.0.0", + "java-properties": "^1.0.2" + }, + "engines": { + "node": "^16.14 || >=18" + } + }, + "node_modules/env-ci/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/env-ci/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/env-ci/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "peer": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-ci/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-aggregate-error": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.9.tgz", + "integrity": "sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg==", + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "function-bind": "^1.1.1", + "functions-have-names": "^1.2.3", + "get-intrinsic": "^1.1.3", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-module-lexer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", + "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", + "dev": true + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/esbuild-wasm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.18.17.tgz", + "integrity": "sha512-9OHGcuRzy+I8ziF9FzjfKLWAPbvi0e/metACVg9k6bK+SI4FFxeV6PcZsz8RIVaMD4YNehw+qj6UMR3+qj/EuQ==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "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.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-etc": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-etc/-/eslint-etc-5.2.1.tgz", + "integrity": "sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "tsutils": "^3.17.1", + "tsutils-etc": "^1.4.1" + }, + "peerDependencies": { + "eslint": "^8.0.0", + "typescript": ">=4.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.6.2", + "@types/node": "*", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/express/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/external-editor/node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "node_modules/fast-xml-parser": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", + "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "peer": true, + "dependencies": { + "strnum": "^1.0.4" + }, + "bin": { + "xml2js": "cli.js" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-stream-rotator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", + "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", + "dependencies": { + "moment": "^2.29.1" + } + }, + "node_modules/file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "dependencies": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-versions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", + "dev": true, + "peer": true, + "dependencies": { + "semver-regex": "^4.0.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dev": true, + "dependencies": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, + "node_modules/git-log-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", + "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==", + "dev": true, + "peer": true, + "dependencies": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "~0.6.6" + } + }, + "node_modules/git-log-parser/node_modules/split2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", + "dev": true, + "peer": true, + "dependencies": { + "through2": "~2.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/guess-parser": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/guess-parser/-/guess-parser-0.4.22.tgz", + "integrity": "sha512-KcUWZ5ACGaBM69SbqwVIuWGoSAgD+9iJnchR9j/IarVI1jHVeXv+bUXBIMeqVMSKt3zrn0Dgf9UpcOEpPBLbSg==", + "dev": true, + "dependencies": { + "@wessberg/ts-evaluator": "0.0.27" + }, + "peerDependencies": { + "typescript": ">=3.7.5" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "dependencies": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "node_modules/hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "peer": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hexy": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", + "integrity": "sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==", + "bin": { + "hexy": "bin/hexy_cmd.js" + }, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/hook-std": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/hot-patcher": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-0.5.0.tgz", + "integrity": "sha512-2Uu2W0s8+dnqXzdlg0MRsRzPoDCs1wVjOGSyMRRaMzLDX4bgHw6xDYKccsWafXPPxQpkQfEjgW6+17pwcg60bw==", + "peer": true + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^1.0.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", + "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "dev": true, + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz", + "integrity": "sha512-bvZZ7vXpr1RKoImjuQ45hJb5OvE2oJafHysiD/AL3nkqTZH2hFCjQ3YZfCd63FefDitbJze/ispUPP0gfDsT2Q==", + "engines": { + "node": "*" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", + "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", + "dev": true, + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/ignore-walk/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "dependencies": { + "@types/node": "16.9.1" + } + }, + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/immutable": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz", + "integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==", + "dev": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", + "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/injection-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/injection-js/-/injection-js-2.4.0.tgz", + "integrity": "sha512-6jiJt0tCAo9zjHbcwLiPL+IuNe9SQ6a9g0PEzafThW3fOQi0mrmiJGBJvDD6tmhPh8cQHIQtCOrJuBfQME4kPA==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + } + }, + "node_modules/inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/into-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-7.0.0.tgz", + "integrity": "sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==", + "dev": true, + "peer": true, + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "node_modules/ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "peer": true + }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "peer": true, + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "dependencies": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "node_modules/issue-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", + "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", + "dev": true, + "peer": true, + "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" + }, + "engines": { + "node": ">=10.13" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dependencies": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jackspeak": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", + "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jasmine-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.1.0.tgz", + "integrity": "sha512-bFMMwpKuTZXCuGd51yClFobw5SOtad1kmdWnYO8dNwYV8i01Xj0C2+nyQpSKl1EKxiPfyd1ZgBl/rsusL3aS6w==", + "dev": true + }, + "node_modules/java-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", + "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/jest": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", + "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.6.2", + "@jest/types": "^29.6.1", + "import-local": "^3.0.2", + "jest-cli": "^29.6.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", + "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.6.2", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "p-limit": "^3.1.0", + "pretty-format": "^29.6.2", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-circus/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-circus/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-circus/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", + "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", + "dev": true, + "dependencies": { + "@jest/core": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/types": "^29.6.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-cli/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-cli/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", + "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.6.2", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.2", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.6.2", + "jest-environment-node": "^29.6.2", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.6.2", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-config/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-config/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-config/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", + "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-diff/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-diff/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-diff/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-diff/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-docblock": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", + "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", + "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "chalk": "^4.0.0", + "jest-get-type": "^29.4.3", + "jest-util": "^29.6.2", + "pretty-format": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-each/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-each/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-each/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-each/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-environment-node": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", + "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", + "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", + "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.4.3", + "pretty-format": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", + "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.6.2", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-matcher-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-matcher-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", + "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-message-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-message-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-message-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-mock": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", + "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "@types/node": "*", + "jest-util": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", + "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", + "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-resolve/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-resolve/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-resolve/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-resolve/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", + "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", + "dev": true, + "dependencies": { + "@jest/console": "^29.6.2", + "@jest/environment": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-leak-detector": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-resolve": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-util": "^29.6.2", + "jest-watcher": "^29.6.2", + "jest-worker": "^29.6.2", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runner/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runner/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runner/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runner/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", + "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/globals": "^29.6.2", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-runtime/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-runtime/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-runtime/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", + "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.6.2", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.6.2", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^29.6.2", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-snapshot/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-snapshot/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", + "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-util/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-util/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-util/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", + "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.4.3", + "leven": "^3.1.0", + "pretty-format": "^29.6.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-validate/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-validate/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-validate/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", + "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.6.2", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jest-watcher/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/jest-watcher/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-watcher/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", + "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.6.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jimp": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.10.tgz", + "integrity": "sha512-lCaHIJAgTOsplyJzC1w/laxSxrbSsEBw4byKwXgUdMmh+ayPsnidTblenQm+IvhIs44Gcuvlb6pd2LQ0wcKaKg==", + "dependencies": { + "@jimp/custom": "^0.22.10", + "@jimp/plugins": "^0.22.10", + "@jimp/types": "^0.22.10", + "regenerator-runtime": "^0.13.3" + } + }, + "node_modules/jiti": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "node_modules/jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "dependencies": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/jsdom/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "peer": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "peer": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsrsasign": { + "version": "10.8.6", + "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.8.6.tgz", + "integrity": "sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==", + "funding": { + "url": "https://github.com/kjur/jsrsasign#donations" + } + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/karma": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", + "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", + "dev": true, + "dependencies": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "bin": { + "karma": "bin/karma" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/karma-chrome-launcher": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", + "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", + "dev": true, + "dependencies": { + "which": "^1.2.1" + } + }, + "node_modules/karma-chrome-launcher/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/karma-coverage": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", + "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.0.5", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "dev": true, + "dependencies": { + "jasmine-core": "^4.1.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "karma": "^6.0.0" + } + }, + "node_modules/karma-jasmine-html-reporter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", + "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", + "dev": true, + "peerDependencies": { + "jasmine-core": "^4.0.0 || ^5.0.0", + "karma": "^6.0.0", + "karma-jasmine": "^5.0.0" + } + }, + "node_modules/karma-jasmine/node_modules/jasmine-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", + "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", + "dev": true + }, + "node_modules/karma-junit-reporter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-2.0.1.tgz", + "integrity": "sha512-VtcGfE0JE4OE1wn0LK8xxDKaTP7slN8DO3I+4xg6gAi1IoAHAXOJ1V9G/y45Xg6sxdxPOR3THCFtDlAfBo9Afw==", + "dev": true, + "dependencies": { + "path-is-absolute": "^1.0.0", + "xmlbuilder": "12.0.0" + }, + "engines": { + "node": ">= 8" + }, + "peerDependencies": { + "karma": ">=0.9" + } + }, + "node_modules/karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "dependencies": { + "source-map-support": "^0.5.5" + } + }, + "node_modules/karma/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "node_modules/launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "dev": true, + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" + } + }, + "node_modules/layerr": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/layerr/-/layerr-0.1.2.tgz", + "integrity": "sha512-ob5kTd9H3S4GOG2nVXyQhOu9O8nBgP555XxWPkJI0tR0JeRilfyTp8WtPdIJHLXBmHMSdEq5+KMxiYABeScsIQ==", + "peer": true + }, + "node_modules/less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "dependencies": { + "klona": "^2.0.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/less/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/less/node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/less/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/less/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, + "dependencies": { + "webpack-sources": "^3.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-sources": { + "optional": true + } + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "dependencies": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, + "node_modules/load-bmfont/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "peer": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "peer": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true, + "peer": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true, + "peer": true + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "dev": true, + "peer": true + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "peer": true + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "peer": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true, + "peer": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/logform": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", + "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", + "dependencies": { + "@colors/colors": "1.5.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/ltx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ltx/-/ltx-3.0.0.tgz", + "integrity": "sha512-bu3/4/ApUmMqVNuIkHaRhqVtEi6didYcBDIF56xhPRCzVpdztCipZ62CUuaxMlMBUzaVL93+4LZRqe02fuAG6A==", + "engines": { + "node": ">= 12.4.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", + "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.2.tgz", + "integrity": "sha512-ahRPGXJpjMjwSOlBoTMZAK7ATXkli5qCPxZ21TG44rx1KEo44bii4ekgTDQPNRQ4Kh7JMb9Ub1PVk1NxRSsorg==", + "dev": true, + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 16" + } + }, + "node_modules/marked-terminal": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "engines": { + "node": ">=14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/marked-terminal/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "peer": true, + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "peer": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "peer": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "peer": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "peer": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "peer": true + }, + "node_modules/meow/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "peer": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "peer": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/meow/node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "peer": true + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==" + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dev": true, + "dependencies": { + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "peer": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-json-stream/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "dependencies": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.201.0", + "@mongodb-js/zstd": "^1.1.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/mongodb-connection-string-url/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/mongoose": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.3.tgz", + "integrity": "sha512-eok0lW6mZJHK2vVSWyJb9tUfPMUuRF3h7YC4pU2K2/YSZBlNDUwvKsHgftMOANbokP2Ry+4ylvzAdW4KjkRFjw==", + "dependencies": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/morgan/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/needle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, + "optional": true, + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/needle/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", + "dev": true, + "peer": true + }, + "node_modules/nested-property": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz", + "integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==", + "peer": true + }, + "node_modules/ng-packagr": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-16.2.0.tgz", + "integrity": "sha512-3u2FVSpKDa0EJRSGOAhYIZwjtnG7SVFBnUf5fk/VfDOxVV4kFRea6DEK7f/mb1D4WV/yqSZB9JmvBZp0uuIGeA==", + "dev": true, + "dependencies": { + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "ajv": "^8.11.0", + "ansi-colors": "^4.1.3", + "autoprefixer": "^10.4.12", + "browserslist": "^4.21.4", + "cacache": "^17.0.0", + "chokidar": "^3.5.3", + "commander": "^11.0.0", + "convert-source-map": "^2.0.0", + "dependency-graph": "^0.11.0", + "esbuild-wasm": "^0.19.0", + "fast-glob": "^3.2.12", + "find-cache-dir": "^3.3.2", + "injection-js": "^2.4.0", + "jsonc-parser": "^3.2.0", + "less": "^4.1.3", + "ora": "^5.1.0", + "piscina": "^4.0.0", + "postcss": "^8.4.16", + "postcss-url": "^10.1.3", + "rollup": "^3.0.0", + "rxjs": "^7.5.6", + "sass": "^1.55.0" + }, + "bin": { + "ng-packagr": "cli/main.js" + }, + "engines": { + "node": "^16.14.0 || >=18.10.0" + }, + "optionalDependencies": { + "esbuild": "^0.19.0" + }, + "peerDependencies": { + "@angular/compiler-cli": "^16.0.0 || ^16.2.0-next.0", + "tailwindcss": "^2.0.0 || ^3.0.0", + "tslib": "^2.3.0", + "typescript": ">=4.9.3 <5.2" + }, + "peerDependenciesMeta": { + "tailwindcss": { + "optional": true + } + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/android-arm": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.2.tgz", + "integrity": "sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/android-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.2.tgz", + "integrity": "sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/android-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.2.tgz", + "integrity": "sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.2.tgz", + "integrity": "sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/darwin-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.2.tgz", + "integrity": "sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.2.tgz", + "integrity": "sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.2.tgz", + "integrity": "sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-arm": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.2.tgz", + "integrity": "sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.2.tgz", + "integrity": "sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-ia32": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.2.tgz", + "integrity": "sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-loong64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.2.tgz", + "integrity": "sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.2.tgz", + "integrity": "sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.2.tgz", + "integrity": "sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.2.tgz", + "integrity": "sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-s390x": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.2.tgz", + "integrity": "sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/linux-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.2.tgz", + "integrity": "sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.2.tgz", + "integrity": "sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.2.tgz", + "integrity": "sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/sunos-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.2.tgz", + "integrity": "sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/win32-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.2.tgz", + "integrity": "sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/win32-ia32": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.2.tgz", + "integrity": "sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/@esbuild/win32-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.2.tgz", + "integrity": "sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/ng-packagr/node_modules/esbuild": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.2.tgz", + "integrity": "sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.19.2", + "@esbuild/android-arm64": "0.19.2", + "@esbuild/android-x64": "0.19.2", + "@esbuild/darwin-arm64": "0.19.2", + "@esbuild/darwin-x64": "0.19.2", + "@esbuild/freebsd-arm64": "0.19.2", + "@esbuild/freebsd-x64": "0.19.2", + "@esbuild/linux-arm": "0.19.2", + "@esbuild/linux-arm64": "0.19.2", + "@esbuild/linux-ia32": "0.19.2", + "@esbuild/linux-loong64": "0.19.2", + "@esbuild/linux-mips64el": "0.19.2", + "@esbuild/linux-ppc64": "0.19.2", + "@esbuild/linux-riscv64": "0.19.2", + "@esbuild/linux-s390x": "0.19.2", + "@esbuild/linux-x64": "0.19.2", + "@esbuild/netbsd-x64": "0.19.2", + "@esbuild/openbsd-x64": "0.19.2", + "@esbuild/sunos-x64": "0.19.2", + "@esbuild/win32-arm64": "0.19.2", + "@esbuild/win32-ia32": "0.19.2", + "@esbuild/win32-x64": "0.19.2" + } + }, + "node_modules/ng-packagr/node_modules/esbuild-wasm": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.19.2.tgz", + "integrity": "sha512-ak2XIIJKby+Uo3Iqh8wtw4pn2uZcnfLgtcmBHIgkShpun5ZIJsFigWXp7uLt7gXk3QAOCMmv0TSsIxD5qdn+Vw==", + "dev": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/ng-packagr/node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/ng-packagr/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ng-packagr/node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ng-packagr/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "!win32" + ], + "dependencies": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "peer": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true, + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-gyp": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", + "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "dev": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "dev": true, + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node_modules/node-opcua": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua/-/node-opcua-2.109.0.tgz", + "integrity": "sha512-9E8u5O6ZNMxLLGxvK7CqgwUEa/6+bb2tyJF2KdCietHz4H6njLgrw2zNQH1KVwM20+NZMCeDoo3Al73sbGSMQQ==", + "dependencies": { + "@types/semver": "^7.5.0", + "chalk": "4.1.2", + "node-opcua-address-space": "2.109.0", + "node-opcua-address-space-for-conformance-testing": "2.109.0", + "node-opcua-aggregates": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-client": "2.109.0", + "node-opcua-client-crawler": "2.109.0", + "node-opcua-client-proxy": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-nodesets": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-packet-analyzer": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-server-discovery": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-filter": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-node-management": "2.109.0", + "node-opcua-service-query": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-register-node": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-service-session": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-transport": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "node-opcua-vendor-diagnostic": "2.109.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=8.10" + }, + "funding": { + "url": "https://github.com/sponsors/erossignon" + } + }, + "node_modules/node-opcua-address-space": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-address-space/-/node-opcua-address-space-2.109.0.tgz", + "integrity": "sha512-JVNcUL9NErjCux2GIOVjhI8Vav7Mo0CwiQimxxdTidXs7LB6bkhapd3O9hZ9FEAHyCgwquFEmSa3KSfHKu3M/Q==", + "dependencies": { + "@types/lodash": "4.14.197", + "@types/semver": "^7.5.0", + "async": "^3.2.4", + "chalk": "4.1.2", + "dequeue": "^1.0.5", + "lodash": "4.17.21", + "node-opcua-address-space-base": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-client-dynamic-extension-object": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-nodeset-ua": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "node-opcua-xml2json": "2.109.0", + "semver": "^7.5.4", + "set-prototype-of": "^1.0.0", + "thenify": "^3.3.1", + "xml-writer": "^1.7.0" + }, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/node-opcua-address-space-base": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-address-space-base/-/node-opcua-address-space-base-2.109.0.tgz", + "integrity": "sha512-NYZxc1v3NrQiA1k58xPEeiDMRHbkBTr4R87MTqypm2YAfWGx/SphtAslXlgdLu3YksvQDqFefj85/z7qNtOXug==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + }, + "engines": { + "node": ">=6.10" + } + }, + "node_modules/node-opcua-address-space-for-conformance-testing": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-address-space-for-conformance-testing/-/node-opcua-address-space-for-conformance-testing-2.109.0.tgz", + "integrity": "sha512-9lIvbdrbxTotmaLwRxu562JLm8qDN1eJhZmLQComWR3Bx8dlz+5IL+WAyA94h7AhRdOah8Aorol08nnkGpIIHw==", + "dependencies": { + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-address-space/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-address-space/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-address-space/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-address-space/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-address-space/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-address-space/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-aggregates": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-aggregates/-/node-opcua-aggregates-2.109.0.tgz", + "integrity": "sha512-DU4ik5t+0NSOqRlFQ5gDcAEddxPrk88E9ezPgOLRle9PYdiX+h3rij4/h2T5+4AyZVNQiSUoHUWOfuszSt5ABQ==", + "dependencies": { + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-assert": { + "version": "2.105.0", + "resolved": "https://registry.npmjs.org/node-opcua-assert/-/node-opcua-assert-2.105.0.tgz", + "integrity": "sha512-q4VVsbfeXdXarTRga8d100NxkALvhEeAeN/YMBUsOkDIHh/VjrozknSSUT1c0h406QRZdmcoz7MnHCLG0+Rwxw==", + "dependencies": { + "chalk": "4.1.2" + } + }, + "node_modules/node-opcua-assert/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-assert/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-assert/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-assert/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-assert/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-assert/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-basic-types": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-basic-types/-/node-opcua-basic-types-2.109.0.tgz", + "integrity": "sha512-jSTIHx9yW4OodTL3KEDIDVnmX79omkmYSlafJQIXoJsdgP7sg6xEqC5n6eWjqfFJi0CC4FF8mojBlhkoyLX1Ng==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-guid": "2.98.1", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0" + } + }, + "node_modules/node-opcua-binary-stream": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-binary-stream/-/node-opcua-binary-stream-2.109.0.tgz", + "integrity": "sha512-XuJ/YlXm2uzPPE0SCEVfzfiZ5NAOZYrjqSJVS6Ge+bBvXV4ecKz5PyLokQ8F8g7GS3Z8Zb4LOKOYa+ei2Mn2Qw==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-buffer-utils": "2.109.0" + } + }, + "node_modules/node-opcua-buffer-utils": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-buffer-utils/-/node-opcua-buffer-utils-2.109.0.tgz", + "integrity": "sha512-wi52xeXIX8X8nrar43uvnRS5JJwHPGS8AW/CQWZ7+nS57suQO2hGosLrRL/wpiVEvFZl1LLOrfJIcX3Y54qj8A==" + }, + "node_modules/node-opcua-certificate-manager": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-certificate-manager/-/node-opcua-certificate-manager-2.109.0.tgz", + "integrity": "sha512-5l2eE7zNlPCWlIPesHM5wmxMO/EGP8mwBmi6YZmOBHC4yV1acT2j2spL6+ij99vp92Y8byYu6IAzx5N98O5/8Q==", + "dependencies": { + "@types/mkdirp": "1.0.2", + "env-paths": "2.2.1", + "mkdirp": "1.0.4", + "node-opcua-assert": "2.105.0", + "node-opcua-crypto": "4.1.0", + "node-opcua-debug": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-pki": "4.3.0", + "node-opcua-status-code": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-certificate-manager/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-opcua-chunkmanager": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-chunkmanager/-/node-opcua-chunkmanager-2.109.0.tgz", + "integrity": "sha512-bwY+BVJHAgU13X3dWsfFGSnv2XZm1EyZIY/XeKlhXGV58eURv9lBNe7y7Orp3RJh4zSO0LxA1rwATc5eT7aqZQ==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-packet-assembler": "2.109.0" + } + }, + "node_modules/node-opcua-client": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client/-/node-opcua-client-2.109.0.tgz", + "integrity": "sha512-DPXhu2VCIVcoHUMY6qrFeULj5IIeK035dlrj3gZyNMhm90A37FU5WaH67GLbmEdbvHRcEL5aN+ITstxJr54sVg==", + "dependencies": { + "@ster5/global-mutex": "^2.0.0", + "@types/async": "^3.2.20", + "async": "^3.2.4", + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-client-dynamic-extension-object": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-pki": "4.3.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-filter": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-query": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-register-node": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-service-session": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-client-crawler": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client-crawler/-/node-opcua-client-crawler-2.109.0.tgz", + "integrity": "sha512-hpZdcOPLlQoA1pYNQctp8i8OD7tL0WehlbFMrBLCEEeByVZHgLmgFdq88k4U/jjGvAIW8x/dV4A3xw5gvQP1iA==", + "dependencies": { + "async": "^3.2.4", + "chalk": "4.1.2", + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-client": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-client-crawler/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-client-crawler/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-client-crawler/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-client-crawler/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-client-crawler/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-client-crawler/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-client-dynamic-extension-object": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client-dynamic-extension-object/-/node-opcua-client-dynamic-extension-object-2.109.0.tgz", + "integrity": "sha512-Wc2dwmQnjzqcYla5+tlkdzQKZAguEtqVOaR4dH+XRjr5+ismJjs/O8bIvJbl5rT3SFmQVPXQgMYDLpq1nWg3UA==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-client-dynamic-extension-object/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-client-dynamic-extension-object/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-client-dynamic-extension-object/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-client-dynamic-extension-object/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-client-dynamic-extension-object/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-client-dynamic-extension-object/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-client-proxy": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client-proxy/-/node-opcua-client-proxy-2.109.0.tgz", + "integrity": "sha512-gr75WZojmylSjcW9PFhvSB0gZ6BrvKBcuQMwEEhlhs3JeALsJ+YQxG5FxxvJ5TkCNSHxe6XpjTFop8+RuhwyAA==", + "dependencies": { + "async": "^3.2.4", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-client/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-client/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-client/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-client/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-client/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-client/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-common": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-common/-/node-opcua-common-2.109.0.tgz", + "integrity": "sha512-N/Dgh21qT/kwcceJfrlQ46eJllQCNghIwCUneJyLzDH0UfwjW/JP2JRAdHIl0Sbb/l0tjx+FD+qERVA5v2lEbQ==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-crypto": "4.1.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-constants": { + "version": "2.98.1", + "resolved": "https://registry.npmjs.org/node-opcua-constants/-/node-opcua-constants-2.98.1.tgz", + "integrity": "sha512-7RDmofF6vajYmmsbm/t0obqZlL0K7KKgYe4V+QT8qSGdNFrmDANHiAUhgPljur8e8taaDUXFcaOhS4fYjMN1WQ==" + }, + "node_modules/node-opcua-crypto": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/node-opcua-crypto/-/node-opcua-crypto-4.1.0.tgz", + "integrity": "sha512-2MOWvkArDaJj5iJ5QeVmFME32BuAYcx06RF/h6J23QrqhU9L5j+0OCx8ksC+OfGw4LHt8o8gkcZ+opSrBfoUWQ==", + "dependencies": { + "@peculiar/webcrypto": "^1.4.3", + "@peculiar/x509": "^1.9.3", + "@types/jsrsasign": "^10.5.8", + "assert": "^2.0.0", + "better-assert": "^1.0.2", + "chalk": "^4.1.2", + "hexy": "0.3.5", + "jsrsasign": "^10.8.6", + "sshpk": "^1.17.0" + } + }, + "node_modules/node-opcua-crypto/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-crypto/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-crypto/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-crypto/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-crypto/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-crypto/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-data-access": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-data-access/-/node-opcua-data-access-2.109.0.tgz", + "integrity": "sha512-v5n5bCj/yWhOjCvxoo1HfdOrCJ+Hmc8k6nVOBx3NIcn5DTAfNuFw7Aqk3vwEEFyJ3nDyoUasRr0zPo1HMp/E6w==", + "dependencies": { + "node-opcua-data-model": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-data-model": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-data-model/-/node-opcua-data-model-2.109.0.tgz", + "integrity": "sha512-SfeJwylz4fHjrhM9/iEsTiOZhxAPD3oxiyJ49DDE7WVddSzb6jfxevtoyPRDU2UqvqGCjwNkgglYF1RCvNs0Kg==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0" + } + }, + "node_modules/node-opcua-data-value": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-data-value/-/node-opcua-data-value-2.109.0.tgz", + "integrity": "sha512-bxSGWj3qDjYVvxCtLVscjO2iLgWGu8wnlAP+9XoxKYouBNxQNwlby4yz99i6Trt4AYyIEMMJ2tKRF1Bqzt2+4A==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-date-time": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-date-time/-/node-opcua-date-time-2.109.0.tgz", + "integrity": "sha512-REua4ngOEiwOVlePAhCiNLgDchiGFdRWuP381uuunl4dQhj+6HsAVibvMttEBTytrpZ7VyP/hZJYxcTPgazz1Q==", + "dependencies": { + "long": "^4.0.0", + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-debug": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-debug/-/node-opcua-debug-2.109.0.tgz", + "integrity": "sha512-VUnaE47oWsSDtrzUok4QQtGBaeSzEEKKUh1vLxpEuA05PiCQK6l9s18Pme7Ql0DzSgrpJ03QzplAh3UEyF5GVg==", + "dependencies": { + "chalk": "4.1.2", + "hexy": "0.3.5", + "node-opcua-assert": "2.105.0", + "node-opcua-buffer-utils": "2.109.0" + } + }, + "node_modules/node-opcua-debug/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-debug/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-debug/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-debug/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-debug/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-debug/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-enum": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-enum/-/node-opcua-enum-2.109.0.tgz", + "integrity": "sha512-CN38NujK6Tt+EECNNPwBmCyrBNbiB7YkGYW6TEMV7TUBpEcBieYLb/NtS66V7kFcZDFRlXx4mmcraem0QELZ2A==" + }, + "node_modules/node-opcua-extension-object": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-extension-object/-/node-opcua-extension-object-2.109.0.tgz", + "integrity": "sha512-z1BUljLKUSRwpxhEVTZhVEtz6zQCdbrkVzUqWInvx88zH2Gn6iJMLns6Vy2LUpphn1V4BRBGTyxCok8zpshCpA==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0" + } + }, + "node_modules/node-opcua-extension-object/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-extension-object/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-extension-object/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-extension-object/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-extension-object/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-extension-object/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-factory": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-factory/-/node-opcua-factory-2.109.0.tgz", + "integrity": "sha512-S3MhKpQe2PVKOEgfrZ3OKQNgoFgu3HEzTTvXh5YoKb0c7BwddrYK4gONuyiOr7JAKZg2I17fHkkUTZrQSFBFbw==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-debug": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-guid": "2.98.1", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-factory/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-factory/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-factory/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-factory/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-factory/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-factory/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-generator": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-generator/-/node-opcua-generator-2.109.0.tgz", + "integrity": "sha512-mLXf723UTukIGqOvfORwbIM000pnHcThe6N7CTMj7UB8pfVGLjygM/vzjsfrZNlXBZCCG2WQSgRrJG4VMqbxMw==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-generator/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-generator/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-generator/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-generator/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-generator/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-generator/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-guid": { + "version": "2.98.1", + "resolved": "https://registry.npmjs.org/node-opcua-guid/-/node-opcua-guid-2.98.1.tgz", + "integrity": "sha512-09hWgnEUhq6t0QPrCIklAa4/x2aNhp1te0l2IkFQdNkJ8iYEBEKk0lJG7+nA+fNyys0ccUohvHdvuFae2fSGTw==" + }, + "node_modules/node-opcua-hostname": { + "version": "2.105.0", + "resolved": "https://registry.npmjs.org/node-opcua-hostname/-/node-opcua-hostname-2.105.0.tgz", + "integrity": "sha512-nb55yjaaRaxxyypcy3QQ1brml1eK1lBTECy6+36v9v/gs0Kuv9rtdQbu4sZ089qOeuvsWNCFHPDULlLyfDMgeQ==" + }, + "node_modules/node-opcua-nodeid": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-nodeid/-/node-opcua-nodeid-2.109.0.tgz", + "integrity": "sha512-9I/JiYhaDlxJ1xr8083V13Qpu58WrEMTZtzmIPRlxb61KCYWvmHNIiCpo5hHkOvnn1bv4+oW4ICK96sqv16vbw==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-guid": "2.98.1" + } + }, + "node_modules/node-opcua-nodeset-ua": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-nodeset-ua/-/node-opcua-nodeset-ua-2.109.0.tgz", + "integrity": "sha512-EMMAvEMPX5uUgN7dlCGtkYH0z4YzMPeTNY7G0WEdcKaDc5eK6TLBMeUnqtD/VM16hI4a1sYDq1wp6yqvZfwLdg==", + "dependencies": { + "node-opcua-address-space-base": "2.109.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-nodesets": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-nodesets/-/node-opcua-nodesets-2.109.0.tgz", + "integrity": "sha512-WwP5otCcU1HmEhAt8BuhzphiZ3EtkTk+S6C+xO9kYvON5GA9Ie/2Cwh6cyWXaSBi7Nb7EOWumlWokV8USZ5g/Q==" + }, + "node_modules/node-opcua-numeric-range": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-numeric-range/-/node-opcua-numeric-range-2.109.0.tgz", + "integrity": "sha512-iwYvqZ3Hp7eCNdidTLd1y4faVBGV7takgG1mjHvTHojCHsxntjKUJ0AfwIMzKrw0YGzc400aVN5tPPOk3xW57w==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-status-code": "2.109.0" + } + }, + "node_modules/node-opcua-object-registry": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-object-registry/-/node-opcua-object-registry-2.109.0.tgz", + "integrity": "sha512-4MiWKVtveaKYbwpYkjAXsGRvxbK8zSBTaPVQPvuG8ZO3FN0er/ZoJjXRkisCTmJIRkap/0YH8rMJH1Wx1X3vyQ==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-debug": "2.109.0" + } + }, + "node_modules/node-opcua-packet-analyzer": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-packet-analyzer/-/node-opcua-packet-analyzer-2.109.0.tgz", + "integrity": "sha512-TB2qJlin7Bzdl1U0S1TbDIjUGR4o6KoPCA7ylkySvao/SdQLa4EzjYcIjl7qvheMeqgz8EEKGsBaKGPJsept8A==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-packet-analyzer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-packet-analyzer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-packet-analyzer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-packet-analyzer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-packet-analyzer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-packet-analyzer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-packet-assembler": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-packet-assembler/-/node-opcua-packet-assembler-2.109.0.tgz", + "integrity": "sha512-1+JR5ssPMbI8/1m+7RufvdPBQzRhjj4fgLoEQzq0C4BgzpzEWCKrTmz2Pxbdm7d/CGYCt6G7ga8iTAKqNz50fw==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-debug": "2.109.0" + } + }, + "node_modules/node-opcua-pki": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-opcua-pki/-/node-opcua-pki-4.3.0.tgz", + "integrity": "sha512-7GJ2fm9d9L8VSVtj4cW8tlehkcsB/HS1tje2qYcUUxlbF9AJfW4JCInjNBrXYaq7DGPlpF92GgbFDOVmp5D7WQ==", + "dependencies": { + "@ster5/global-mutex": "^2.0.0", + "async": "^3.2.4", + "byline": "^5.0.0", + "chalk": "4.1.2", + "chokidar": "^3.5.3", + "cli-table": "^0.3.11", + "minimist": "^1.2.8", + "node-opcua-crypto": "4.1.0", + "progress": "^2.0.3", + "rimraf": "3.0.2", + "thenify": "^3.3.1", + "wget-improved-2": "^3.3.0", + "yargs": "17.7.2", + "yauzl": "^2.10.0" + }, + "bin": { + "pki": "bin/crypto_create_CA.js" + } + }, + "node_modules/node-opcua-pki/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-pki/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-pki/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-pki/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-pki/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-pki/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-opcua-pki/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-pseudo-session": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-pseudo-session/-/node-opcua-pseudo-session-2.109.0.tgz", + "integrity": "sha512-YmMV53BfTT9wEP/stuZlE2SWx1bodybEnW2CC322JPvhRuwDjyO/TOTXgUO+4DPJnTp/hFfPR1Hj6lqbJeQaBw==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-schemas": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-schemas/-/node-opcua-schemas-2.109.0.tgz", + "integrity": "sha512-xQgOP10+X0xpcZkPqufUbIzrdTF5+Gl1QgmkwFeSvSGIhuxJY5cHSLLDvHg14nfaSraTeks+eMS6xum1WpkSsQ==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-variant": "2.109.0", + "node-opcua-xml2json": "2.109.0" + } + }, + "node_modules/node-opcua-schemas/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-schemas/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-schemas/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-schemas/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-schemas/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-schemas/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-secure-channel": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-secure-channel/-/node-opcua-secure-channel-2.109.0.tgz", + "integrity": "sha512-silNrmvcOU+TTN6inrXdYPTQ4o0yqV8JcFMqxTiHkED/AL6b/2K9NxvYwlzAA2aSIIJQ8JTDxKJcaJcVQwPw0Q==", + "dependencies": { + "async": "^3.2.4", + "backoff": "^2.5.0", + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-chunkmanager": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-crypto": "4.1.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-packet-analyzer": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-transport": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-secure-channel/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-secure-channel/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-secure-channel/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-secure-channel/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-secure-channel/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-secure-channel/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-server": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-server/-/node-opcua-server-2.109.0.tgz", + "integrity": "sha512-ZKZDv1pt2l29m9XhhocmbXFxTi8HldhBmN9GUGJqK8wrK7J1CRqmNHbrXkw5tVD4sFT12OUGriTWgedSgVnW0A==", + "dependencies": { + "@ster5/global-mutex": "^2.0.0", + "async": "^3.2.4", + "chalk": "4.1.2", + "dequeue": "^1.0.5", + "lodash": "4.17.21", + "node-opcua-address-space": "2.109.0", + "node-opcua-address-space-base": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-client": "2.109.0", + "node-opcua-client-dynamic-extension-object": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-nodesets": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-filter": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-node-management": "2.109.0", + "node-opcua-service-query": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-register-node": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-service-session": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-server-discovery": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-server-discovery/-/node-opcua-server-discovery-2.109.0.tgz", + "integrity": "sha512-IRqI6eKABxP+t7Loi7qskE/baoryRuC8eduNtLaBNQyP5WlG/4vqv1MW8oNz3YNr15nwEve2AsD1qbRdBQKk+g==", + "dependencies": { + "chalk": "4.1.2", + "env-paths": "2.2.1", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-status-code": "2.109.0", + "sterfive-bonjour-service": "1.1.4", + "thenify": "^3.3.1" + } + }, + "node_modules/node-opcua-server-discovery/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-server-discovery/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-server-discovery/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-server-discovery/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-server-discovery/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-server-discovery/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-server/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-server/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-server/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-server/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-server/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-server/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-service-browse": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-browse/-/node-opcua-service-browse-2.109.0.tgz", + "integrity": "sha512-HgqnzfZOkBoJFpmGlI5bVk6U1lpKZl7GYNhp8U1+c8+nWvfqu2P9+1bA64oWQN3Gav9rKBL+6ZXWQYfsqM2Blw==", + "dependencies": { + "node-opcua-data-model": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-call": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-call/-/node-opcua-service-call-2.109.0.tgz", + "integrity": "sha512-Uqoi27BZ+Ia3d4PxLE9jnxjEGuTf2N6kreu1uZfwb3j/pzira0dxmudWrq3826XkxZ24+Marhrcc8O0hsw1Chw==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-service-discovery": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-discovery/-/node-opcua-service-discovery-2.109.0.tgz", + "integrity": "sha512-ELh7s1QP20A2FvexHlnk8r3CrDd7eBiSiuoOfQ34UP+41lW2Dt5++/BDfGLqTonG60Zkd2SRP5XYRml+qmmDfw==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-debug": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-types": "2.109.0", + "sterfive-bonjour-service": "1.1.4" + } + }, + "node_modules/node-opcua-service-discovery/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-service-discovery/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-service-discovery/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-service-discovery/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-service-discovery/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-service-discovery/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-service-endpoints": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-endpoints/-/node-opcua-service-endpoints-2.109.0.tgz", + "integrity": "sha512-rFdzGAOdXMWBRAgle4hyHnG5LgAHIdlixBJfpjPzaSNX9eveir9fduY8KPfsNAMMk39SWv4oNyl9QiyAXvA9Ew==", + "dependencies": { + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-filter": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-filter/-/node-opcua-service-filter-2.109.0.tgz", + "integrity": "sha512-YDBR+ArqKFCUYsplSDzw7+GalgKnyJMHLA3srCMSvex44bQdEZRJuZkI5siZLopL5Aaw/BwGdxQE+Li/8oH7Fg==", + "dependencies": { + "node-opcua-address-space-base": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-service-history": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-history/-/node-opcua-service-history-2.109.0.tgz", + "integrity": "sha512-VT8V8zJm4N/PmGU9wWXBJrdWuYsTmP2Pc4sM7HDC3aulMLxRcvPRQiP7nz51dVChVvekGW797aW0tSTXl/50rA==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-node-management": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-node-management/-/node-opcua-service-node-management-2.109.0.tgz", + "integrity": "sha512-SNQa9+kCOv6OEJvcKICbx7A4FdQKtkf26xL4zG3sIhvi0Gp5LUh9XsRus88Rs7/00R7nn43u8tDUIUhcqhdxrg==", + "dependencies": { + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-query": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-query/-/node-opcua-service-query-2.109.0.tgz", + "integrity": "sha512-KRygFtynmEFAuYA29GVN1dRVD4WF3FpM+6YBLnlsuaVCE68hYN5D9QruOPZmjJ7Yk0vfJVzqJVGReooaObpa5A==", + "dependencies": { + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-read": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-read/-/node-opcua-service-read-2.109.0.tgz", + "integrity": "sha512-exiJUI6uRQqaqNo29XqZUO2gp3SFa9wKRU/2ImENw7latqzdh8hwO/U8Sbg1YjrM7L6moVhdtXcjp4KzzCbhxA==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-register-node": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-register-node/-/node-opcua-service-register-node-2.109.0.tgz", + "integrity": "sha512-DezkWT8dTeYEGpjXWcKlyj8J7rkkJ3aovRTXdtTiUUP8IbR0tNUSz8+3ElcBwqjG7DsAFCnoL81HMxnv1YIfcg==", + "dependencies": { + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-secure-channel": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-secure-channel/-/node-opcua-service-secure-channel-2.109.0.tgz", + "integrity": "sha512-pUx1a3d/H2Hz2yNfi+Lq5BCVHjjJjOKMnV0/8Muzdq2uBGjJ6Z1WCMNw0d8DE4D6gdjMho5Ql9tsYPC2YQFy7w==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-session": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-session/-/node-opcua-service-session-2.109.0.tgz", + "integrity": "sha512-E+3YDVSnFjvjt66kADTPeLcqxdNc7ytqm+BJ9+Fy+ccOvCBkBW5BaMRkQTS/fCiJbQYSeLA4XkmfQcfbKWECpQ==", + "dependencies": { + "node-opcua-factory": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-subscription": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-subscription/-/node-opcua-service-subscription-2.109.0.tgz", + "integrity": "sha512-L4Q5dae4wH26fmZ4IJyxDGBTJEcnGVX8Y/leGdxBYRhbyYeWTs0VvBqLHcc/YKHMXQBv5l0+Sc8oA559cWqKkg==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-service-translate-browse-path": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-translate-browse-path/-/node-opcua-service-translate-browse-path-2.109.0.tgz", + "integrity": "sha512-/b4f5UEDaWTroe0MmiqG+0pF1E0ut5TLiW2jHye8m3u+zpzGC60Qh0cSbXQ1ShSv9E8Pw3Xa1DUqlgTHn/ovrQ==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-service-write": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-write/-/node-opcua-service-write-2.109.0.tgz", + "integrity": "sha512-oIJofZDUsJQQMhhkfxSbo1qZKD8GWMO0I65VgC4qZ6jFmKo2KfGAy4iWgHKHdoqTXfjHKSs63bWJIsgWVeNr8Q==", + "dependencies": { + "node-opcua-types": "2.109.0" + } + }, + "node_modules/node-opcua-status-code": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-status-code/-/node-opcua-status-code-2.109.0.tgz", + "integrity": "sha512-j/017+dEy8o/UU3OzS6EDelr2nOPOCMOgJ/ghSADnl7y6qGRwQmpXHGQR2ayVFnDvgxUMFbOGVwCj0QchPt2vA==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0" + } + }, + "node_modules/node-opcua-transport": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-transport/-/node-opcua-transport-2.109.0.tgz", + "integrity": "sha512-IVsSB/tjHhl7Gs6nrQgVUBoRQkuBz3Ubhre+ZAOFj4UhG3hxX7hakM4xOYv/cLHFTBX3uiENNvCxCwXgFF9nyw==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-chunkmanager": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-packet-assembler": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-transport/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-transport/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-transport/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-transport/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-transport/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-transport/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-types": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-types/-/node-opcua-types-2.109.0.tgz", + "integrity": "sha512-5fBzKM/pLx+gJTV5dTKnLVPsBhGl34h096lyzvuwFN0XAiaT/oM0GapEXL/it16yhWmMesDifaoEsPgBSl/yAQ==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-generator": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-utils": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-utils/-/node-opcua-utils-2.109.0.tgz", + "integrity": "sha512-SB7jQAbWrfufQgkB0j0wUjcP9MhBQLGS0MtWXc7JK+7F8Wu4PLNJTz4S4Qidy6qpiPTokl92L1TRSuFhMlWObw==", + "dependencies": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0" + } + }, + "node_modules/node-opcua-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua-utils/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua-variant": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-variant/-/node-opcua-variant-2.109.0.tgz", + "integrity": "sha512-NmUbaWVyH9o7vD2o1xw4ManbU8/lCAThof5XDfQgkbw2FZ3tAu6+oo0psbvl7DHgOMJTY8a12gaDQ0Jwy1RnSQ==", + "dependencies": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node_modules/node-opcua-vendor-diagnostic": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-vendor-diagnostic/-/node-opcua-vendor-diagnostic-2.109.0.tgz", + "integrity": "sha512-z7OPToOF087syPkaYks63AqEvhpQTPzrL+fOTZHIkvY948kZKjt+VW5pJPmSl4KFCd5yYwSXC6CJS1kgErYvyg==", + "dependencies": { + "humanize": "0.0.9", + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-debug": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node_modules/node-opcua-xml2json": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-xml2json/-/node-opcua-xml2json-2.109.0.tgz", + "integrity": "sha512-jIsV74uvYQODEJInwgHpgeZCr43bq8gUoooUawo0No/acb1lYAJQN33NEioNM3I0nO0ISZ/AMjAFTaohoqoQ5A==", + "dependencies": { + "ltx": "^3.0.0", + "node-opcua-assert": "2.105.0", + "node-opcua-utils": "2.109.0", + "thenify": "^3.3.1", + "xml-writer": "^1.7.0" + } + }, + "node_modules/node-opcua/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/node-opcua/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/node-opcua/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/node-opcua/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/node-opcua/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-opcua/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "node_modules/nodemailer": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", + "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm": { + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-9.8.1.tgz", + "integrity": "sha512-AfDvThQzsIXhYgk9zhbk5R+lh811lKkLAeQMMhSypf1BM7zUafeIIBzMzespeuVEJ0+LvY36oRQYf7IKLzU3rw==", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/promise-spawn", + "@npmcli/run-script", + "abbrev", + "archy", + "cacache", + "chalk", + "ci-info", + "cli-columns", + "cli-table3", + "columnify", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "ms", + "node-gyp", + "nopt", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "npmlog", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "semver", + "sigstore", + "ssri", + "supports-color", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dev": true, + "peer": true, + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^6.3.0", + "@npmcli/config": "^6.2.1", + "@npmcli/fs": "^3.1.0", + "@npmcli/map-workspaces": "^3.0.4", + "@npmcli/package-json": "^4.0.1", + "@npmcli/promise-spawn": "^6.0.2", + "@npmcli/run-script": "^6.0.2", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^17.1.3", + "chalk": "^5.3.0", + "ci-info": "^3.8.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.3", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.2", + "glob": "^10.2.7", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^6.1.1", + "ini": "^4.1.1", + "init-package-json": "^5.0.0", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^3.0.0", + "libnpmaccess": "^7.0.2", + "libnpmdiff": "^5.0.19", + "libnpmexec": "^6.0.3", + "libnpmfund": "^4.0.19", + "libnpmhook": "^9.0.3", + "libnpmorg": "^5.0.4", + "libnpmpack": "^5.0.19", + "libnpmpublish": "^7.5.0", + "libnpmsearch": "^6.0.2", + "libnpmteam": "^5.0.3", + "libnpmversion": "^4.0.2", + "make-fetch-happen": "^11.1.1", + "minimatch": "^9.0.3", + "minipass": "^5.0.0", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^9.4.0", + "nopt": "^7.2.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.1.1", + "npm-package-arg": "^10.1.0", + "npm-pick-manifest": "^8.0.1", + "npm-profile": "^7.0.1", + "npm-registry-fetch": "^14.0.5", + "npm-user-validate": "^2.0.0", + "npmlog": "^7.0.1", + "p-map": "^4.0.0", + "pacote": "^15.2.0", + "parse-conflict-json": "^3.0.1", + "proc-log": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^2.1.0", + "semver": "^7.5.4", + "sigstore": "^1.7.0", + "ssri": "^10.0.4", + "supports-color": "^9.4.0", + "tar": "^6.1.15", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.0", + "which": "^3.0.1", + "write-file-atomic": "^5.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dev": true, + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-install-checks": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz", + "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==", + "dev": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "dependencies": { + "ignore-walk": "^6.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", + "dev": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", + "dev": true, + "dependencies": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm-registry-fetch/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/@colors/colors": { + "version": "1.5.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/@npmcli/arborist": { + "version": "6.3.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^5.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^4.0.0", + "@npmcli/query": "^3.0.0", + "@npmcli/run-script": "^6.0.0", + "bin-links": "^4.0.1", + "cacache": "^17.0.4", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.0", + "nopt": "^7.0.0", + "npm-install-checks": "^6.0.0", + "npm-package-arg": "^10.1.0", + "npm-pick-manifest": "^8.0.1", + "npm-registry-fetch": "^14.0.3", + "npmlog": "^7.0.1", + "pacote": "^15.0.8", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.2", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.1", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^3.8.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/disparity-colors": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "ansi-styles": "^4.3.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/fs": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/git": { + "version": "4.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/installed-package-contents": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "bin": { + "installed-package-contents": "lib/index.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/map-workspaces": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/metavuln-calculator": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "cacache": "^17.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^15.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/name-from-folder": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/node-gyp": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/package-json": { + "version": "4.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/git": "^4.1.0", + "glob": "^10.2.2", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/promise-spawn": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/query": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@npmcli/run-script": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/npm/node_modules/@sigstore/protobuf-specs": { + "version": "0.1.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@sigstore/tuf": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.1.0", + "tuf-js": "^1.1.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/@tufjs/canonical-json": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/@tufjs/models": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abbrev": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/abort-controller": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/npm/node_modules/agent-base": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/npm/node_modules/agentkeepalive": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/npm/node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/archy": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/are-we-there-yet": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^4.1.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/base64-js": { + "version": "1.5.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/bin-links": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/binary-extensions": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/npm/node_modules/buffer": { + "version": "6.0.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/npm/node_modules/builtins": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/npm/node_modules/cacache": { + "version": "17.1.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/chalk": { + "version": "5.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/npm/node_modules/chownr": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ci-info": { + "version": "3.8.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/cidr-regex": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "ip-regex": "^4.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/cli-columns": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/cli-table3": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/npm/node_modules/clone": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/npm/node_modules/cmd-shim": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/npm/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/color-support": { + "version": "1.1.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/npm/node_modules/columnify": { + "version": "1.6.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/npm/node_modules/common-ancestor-path": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/console-control-strings": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/npm/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/defaults": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/delegates": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/depd": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/npm/node_modules/diff": { + "version": "5.1.0", + "dev": true, + "inBundle": true, + "license": "BSD-3-Clause", + "peer": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/npm/node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/encoding": { + "version": "0.1.13", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/npm/node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/event-target-shim": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/npm/node_modules/events": { + "version": "3.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/npm/node_modules/exponential-backoff": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/npm/node_modules/fastest-levenshtein": { + "version": "1.0.16", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/npm/node_modules/foreground-child": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/fs-minipass": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/function-bind": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/gauge": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/glob": { + "version": "10.2.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/has": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/npm/node_modules/has-unicode": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/hosted-git-info": { + "version": "6.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/http-cache-semantics": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "peer": true + }, + "node_modules/npm/node_modules/http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/https-proxy-agent": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/humanize-ms": { + "version": "1.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/npm/node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/ieee754": { + "version": "1.2.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/npm/node_modules/ignore-walk": { + "version": "6.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minimatch": "^9.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/npm/node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/npm/node_modules/inherits": { + "version": "2.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/ini": { + "version": "4.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/init-package-json": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-package-arg": "^10.0.0", + "promzard": "^1.0.0", + "read": "^2.0.0", + "read-package-json": "^6.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/ip": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/ip-regex": { + "version": "4.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-cidr": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "cidr-regex": "^3.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/is-core-module": { + "version": "2.12.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/npm/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/is-lambda": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/jackspeak": { + "version": "2.2.1", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/npm/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/json-stringify-nice": { + "version": "1.1.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/just-diff": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/just-diff-apply": { + "version": "5.5.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/libnpmaccess": { + "version": "7.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-package-arg": "^10.1.0", + "npm-registry-fetch": "^14.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff": { + "version": "5.0.19", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/arborist": "^6.3.0", + "@npmcli/disparity-colors": "^3.0.0", + "@npmcli/installed-package-contents": "^2.0.2", + "binary-extensions": "^2.2.0", + "diff": "^5.1.0", + "minimatch": "^9.0.0", + "npm-package-arg": "^10.1.0", + "pacote": "^15.0.8", + "tar": "^6.1.13" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmexec": { + "version": "6.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/arborist": "^6.3.0", + "@npmcli/run-script": "^6.0.0", + "ci-info": "^3.7.1", + "npm-package-arg": "^10.1.0", + "npmlog": "^7.0.1", + "pacote": "^15.0.8", + "proc-log": "^3.0.0", + "read": "^2.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmfund": { + "version": "4.0.19", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/arborist": "^6.3.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmhook": { + "version": "9.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^14.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmorg": { + "version": "5.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^14.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpack": { + "version": "5.0.19", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/arborist": "^6.3.0", + "@npmcli/run-script": "^6.0.0", + "npm-package-arg": "^10.1.0", + "pacote": "^15.0.8" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmpublish": { + "version": "7.5.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "ci-info": "^3.6.1", + "normalize-package-data": "^5.0.0", + "npm-package-arg": "^10.1.0", + "npm-registry-fetch": "^14.0.3", + "proc-log": "^3.0.0", + "semver": "^7.3.7", + "sigstore": "^1.4.0", + "ssri": "^10.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmsearch": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-registry-fetch": "^14.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmteam": { + "version": "5.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^14.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/libnpmversion": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/git": "^4.0.1", + "@npmcli/run-script": "^6.0.0", + "json-parse-even-better-errors": "^3.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/lru-cache": { + "version": "7.18.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/npm/node_modules/make-fetch-happen": { + "version": "11.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "9.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-collect": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-fetch": { + "version": "3.0.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minipass": "^5.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/npm/node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-json-stream": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/npm/node_modules/minipass-json-stream/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/minizlib": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/mkdirp": { + "version": "1.0.4", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/mute-stream": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/negotiator": { + "version": "0.6.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/npm/node_modules/node-gyp": { + "version": "9.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/abbrev": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/nopt": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/npm/node_modules/node-gyp/node_modules/signal-exit": { + "version": "3.0.7", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/node-gyp/node_modules/which": { + "version": "2.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/nopt": { + "version": "7.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/normalize-package-data": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-audit-report": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-bundled": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-install-checks": { + "version": "6.1.1", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-normalize-package-bin": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-package-arg": { + "version": "10.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-packlist": { + "version": "7.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "ignore-walk": "^6.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-pick-manifest": { + "version": "8.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-profile": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-registry-fetch": { + "version": "14.0.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npm-user-validate": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/npmlog": { + "version": "7.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/once": { + "version": "1.4.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/npm/node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/pacote": { + "version": "15.2.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/parse-conflict-json": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm/node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/path-scurry": { + "version": "1.9.2", + "dev": true, + "inBundle": true, + "license": "BlueOak-1.0.0", + "peer": true, + "dependencies": { + "lru-cache": "^9.1.1", + "minipass": "^5.0.0 || ^6.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/path-scurry/node_modules/lru-cache": { + "version": "9.1.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/npm/node_modules/postcss-selector-parser": { + "version": "6.0.13", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm/node_modules/proc-log": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/process": { + "version": "0.11.10", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/npm/node_modules/promise-all-reject-late": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-call-limit": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/promise-inflight": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/promzard": { + "version": "1.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "read": "^2.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/qrcode-terminal": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "peer": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/npm/node_modules/read": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "mute-stream": "~1.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-cmd-shim": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json": { + "version": "6.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/read-package-json-fast": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/readable-stream": { + "version": "4.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/retry": { + "version": "0.12.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/npm/node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/npm/node_modules/safe-buffer": { + "version": "5.2.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "peer": true + }, + "node_modules/npm/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/signal-exit": { + "version": "4.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/sigstore": { + "version": "1.7.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@sigstore/protobuf-specs": "^0.1.0", + "@sigstore/tuf": "^1.0.1", + "make-fetch-happen": "^11.0.1" + }, + "bin": { + "sigstore": "bin/sigstore.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks": { + "version": "2.7.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/npm/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/npm/node_modules/spdx-correct": { + "version": "3.2.0", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-exceptions": { + "version": "2.3.0", + "dev": true, + "inBundle": true, + "license": "CC-BY-3.0", + "peer": true + }, + "node_modules/npm/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/npm/node_modules/spdx-license-ids": { + "version": "3.0.13", + "dev": true, + "inBundle": true, + "license": "CC0-1.0", + "peer": true + }, + "node_modules/npm/node_modules/ssri": { + "version": "10.0.4", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/string_decoder": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/npm/node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/supports-color": { + "version": "9.4.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/npm/node_modules/tar": { + "version": "6.1.15", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/npm/node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm/node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/tiny-relative-date": { + "version": "1.3.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/treeverse": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/tuf-js": { + "version": "1.1.7", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-filename": { + "version": "3.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/unique-slug": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/util-deprecate": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "inBundle": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/npm/node_modules/validate-npm-package-name": { + "version": "5.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/walk-up-path": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/wcwidth": { + "version": "1.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/npm/node_modules/which": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/wide-align": { + "version": "1.1.5", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/npm/node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/npm/node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npm/node_modules/write-file-atomic": { + "version": "5.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/npm/node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "peer": true + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "node_modules/nx": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/nx/-/nx-16.5.1.tgz", + "integrity": "sha512-I3hJRE4hG7JWAtncWwDEO3GVeGPpN0TtM8xH5ArZXyDuVeTth/i3TtJzdDzqXO1HHtIoAQN0xeq4n9cLuMil5g==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@nrwl/tao": "16.5.1", + "@parcel/watcher": "2.0.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.0.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^7.0.2", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "3.0.5", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "semver": "7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "v8-compile-cache": "2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "bin": { + "nx": "bin/nx.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "16.5.1", + "@nx/nx-darwin-x64": "16.5.1", + "@nx/nx-freebsd-x64": "16.5.1", + "@nx/nx-linux-arm-gnueabihf": "16.5.1", + "@nx/nx-linux-arm64-gnu": "16.5.1", + "@nx/nx-linux-arm64-musl": "16.5.1", + "@nx/nx-linux-x64-gnu": "16.5.1", + "@nx/nx-linux-x64-musl": "16.5.1", + "@nx/nx-win32-arm64-msvc": "16.5.1", + "@nx/nx-win32-x64-msvc": "16.5.1" + }, + "peerDependencies": { + "@swc-node/register": "^1.4.2", + "@swc/core": "^1.2.173" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/nx/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nx/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/nx/node_modules/axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/nx/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/nx/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nx/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/nx/node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nx/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/nx/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nx/node_modules/minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nx/node_modules/semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nx/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nx/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-path": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", + "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", + "dev": true, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/owncloud-sdk": { + "version": "3.1.0-alpha.7", + "resolved": "https://registry.npmjs.org/owncloud-sdk/-/owncloud-sdk-3.1.0-alpha.7.tgz", + "integrity": "sha512-YNZrwY7yesiQBKu+4Z2JWR9r5LwtPHXuozlChOlOCMzw/FUI6e7koh9+WRrEwoRQZAnWVvtVCre+zUeJXXcqZw==", + "peerDependencies": { + "axios": "^0.27.2", + "cross-fetch": "^3.0.6", + "promise": "^8.1.0", + "qs": "^6.10.3", + "utf8": "^3.0.0", + "uuid": "^8.2.0", + "webdav": "4.10.0", + "xml-js": "^1.6.11" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "dev": true, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-each-series": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-3.0.0.tgz", + "integrity": "sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==", + "dev": true, + "peer": true, + "dependencies": { + "p-map": "^5.1.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter/node_modules/p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dev": true, + "peer": true, + "dependencies": { + "aggregate-error": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", + "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-retry/node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "node_modules/p-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "dev": true, + "dependencies": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/pacote/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "node_modules/parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-json/node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dev": true, + "dependencies": { + "protocols": "^2.0.0" + } + }, + "node_modules/parse-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", + "dev": true, + "dependencies": { + "parse-path": "^7.0.0" + } + }, + "node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "node_modules/parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dev": true, + "dependencies": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-html-rewriting-stream/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dev": true, + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-sax-parser/node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-posix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", + "integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==", + "peer": true + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==", + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "node_modules/phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/piscina": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.0.0.tgz", + "integrity": "sha512-641nAmJS4k4iqpNUqfggqUBUMmlw0ZoM5VZKdQkV2e970Inn3Tk9kroCc1wpsYLD07vCwpys5iY0d3xI/9WkTg==", + "dev": true, + "dependencies": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0" + }, + "optionalDependencies": { + "nice-napi": "^1.0.2" + } + }, + "node_modules/pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", + "dependencies": { + "pngjs": "^3.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "dev": true, + "peer": true, + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "peer": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/pkg-dir/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/postcss": { + "version": "8.4.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", + "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-url": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.3.tgz", + "integrity": "sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==", + "dev": true, + "dependencies": { + "make-dir": "~3.1.0", + "mime": "~2.5.2", + "minimatch": "~3.0.4", + "xxhashjs": "~0.2.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-url/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/postcss-url/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/postcss-url/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/postcss-url/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "node_modules/precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-format": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", + "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.0", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "peer": true, + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise.any": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/promise.any/-/promise.any-2.0.5.tgz", + "integrity": "sha512-aM+D4cv0Sjkc90Qhg19XH8Mo5aw28YWqPTFWFkaOpE80MuPbjH/brgI7NI4YGWbcS3suOa0xjJrYznet7lSHhw==", + "dependencies": { + "array.prototype.map": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-aggregate-error": "^1.0.9", + "get-intrinsic": "^1.1.3", + "iterate-value": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "peer": true + }, + "node_modules/protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, + "node_modules/pvtsutils": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.4.tgz", + "integrity": "sha512-Y2lmrVPui6d2U0n8lWRSTQ2Ri/0VDcA/BHAPS8/+5ElWp5drG4oPryLaqnehJT71Q2GgmGeB4mau+lSR1gCCmA==", + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true, + "engines": { + "node": ">=0.9" + } + }, + "node_modules/qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "peer": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "peer": true + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/read-package-json": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "dev": true, + "dependencies": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "dependencies": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json-fast/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-pkg": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.0.0.tgz", + "integrity": "sha512-Ajb9oSjxXBw0YyOiwtQ2dKbAA/vMnUPnY63XcCk+mXo0BwIdQEMgZLZiMWGttQHcUhUgbK0mH85ethMPKXxziw==", + "dev": true, + "peer": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^5.0.0", + "parse-json": "^7.0.0", + "type-fest": "^3.8.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.0.0.tgz", + "integrity": "sha512-jgmKiS//w2Zs+YbX039CorlkOp8FIVbSAN8r8GJHDsGlmNPXo+VeHkqAwCiQVTTx5/LwLZTcEw59z3DvcLbr0g==", + "dev": true, + "peer": true, + "dependencies": { + "find-up": "^6.3.0", + "read-pkg": "^8.0.0", + "type-fest": "^3.12.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "peer": true, + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "peer": true, + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "peer": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "peer": true, + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "peer": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/read-pkg/node_modules/parse-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.0.0.tgz", + "integrity": "sha512-kP+TQYAzAiVnzOlWOe0diD6L35s9bJh0SCn95PIbZFKrOYuIRQsQkeWEYxzVDuHTt9V9YqvYCJ2Qo4z9wdfZPw==", + "dev": true, + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.21.4", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^3.0.0", + "lines-and-columns": "^2.0.3", + "type-fest": "^3.8.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "dependencies": { + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/readable-web-to-node-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "peer": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "dev": true, + "peer": true, + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dev": true, + "peer": true, + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "node_modules/resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "dependencies": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "dev": true, + "dependencies": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/resolve-url-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/resolve-url-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "node_modules/rimraf": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", + "dev": true, + "dependencies": { + "glob": "^10.2.5" + }, + "bin": { + "rimraf": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", + "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/sass": { + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz", + "integrity": "sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } + } + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "node_modules/selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, + "dependencies": { + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semantic-release": { + "version": "21.0.7", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-21.0.7.tgz", + "integrity": "sha512-peRDSXN+hF8EFSKzze90ff/EnAmgITHQ/a3SZpRV3479ny0BIZWEJ33uX6/GlOSKdaSxo9hVRDyv2/u2MuF+Bw==", + "dev": true, + "peer": true, + "dependencies": { + "@semantic-release/commit-analyzer": "^10.0.0", + "@semantic-release/error": "^4.0.0", + "@semantic-release/github": "^9.0.0", + "@semantic-release/npm": "^10.0.2", + "@semantic-release/release-notes-generator": "^11.0.0", + "aggregate-error": "^4.0.1", + "cosmiconfig": "^8.0.0", + "debug": "^4.0.0", + "env-ci": "^9.0.0", + "execa": "^7.0.0", + "figures": "^5.0.0", + "find-versions": "^5.1.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^6.0.0", + "lodash-es": "^4.17.21", + "marked": "^5.0.0", + "marked-terminal": "^5.1.1", + "micromatch": "^4.0.2", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-pkg-up": "^10.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^4.0.0", + "signale": "^1.2.1", + "yargs": "^17.5.1" + }, + "bin": { + "semantic-release": "bin/semantic-release.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/semantic-release/node_modules/@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/semantic-release/node_modules/aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "dependencies": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "peer": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/semantic-release/node_modules/figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dev": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/semantic-release/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "peer": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "peer": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semantic-release/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dev": true, + "peer": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "node_modules/set-prototype-of": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-prototype-of/-/set-prototype-of-1.0.0.tgz", + "integrity": "sha512-OeTRSF+prexqa0ZOjfYR2pdGG/9nyzoXhsDj9M/0R8cgK1r9SkiQiqGdQQcObmnalKVPaTLrF8P71OacYqcYGw==" + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/signale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/signale/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "peer": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sigstore": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "dev": true, + "dependencies": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" + }, + "bin": { + "sigstore": "bin/sigstore.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socket.io": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.2.0" + } + }, + "node_modules/socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "dependencies": { + "ws": "~8.11.0" + } + }, + "node_modules/socket.io-adapter/node_modules/ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.72.1" + } + }, + "node_modules/source-map-loader/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/spawn-error-forwarder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", + "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", + "dev": true, + "peer": true + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "peer": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/split2/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/sterfive-bonjour-service": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sterfive-bonjour-service/-/sterfive-bonjour-service-1.1.4.tgz", + "integrity": "sha512-QqDpnBb3KLD6ytdY2KSxsynw1jJAvzfOloQt83GQNXO6CGf84ZY+37tpOEZo1FzgUkFiVsL7pYyg71olDppI/w==", + "dependencies": { + "@types/multicast-dns": "^7.2.1", + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.4" + } + }, + "node_modules/sterfive-bonjour-service/node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "peer": true, + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/streamroller/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "peer": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, + "node_modules/strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "dependencies": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + }, + "bin": { + "sl-log-transformer": "bin/sl-log-transformer.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, + "node_modules/supertest": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", + "dev": true, + "dependencies": { + "methods": "^1.1.2", + "superagent": "^8.0.5" + }, + "engines": { + "node": ">=6.4.0" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.3.2.tgz", + "integrity": "sha512-NZ8YDKqf58+bWbD3v1NnF9QCveqtovT8e/4fJoc/ZgafJdFSqVEYiXM+OnS6rg9Yrb8z6bwpJ4H6hLk7mMs36Q==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "peer": true, + "dependencies": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "peer": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "dev": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/terser-webpack-plugin/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "node_modules/timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, + "node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "node_modules/tmp/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie/node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/traverse": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", + "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "dev": true, + "peer": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "engines": { + "node": ">=16.13.0" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "dependencies": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + }, + "bin": { + "ts-jest": "cli.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.0.0-beta.0 <8", + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@jest/types": { + "optional": true + }, + "babel-jest": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + }, + "node_modules/tsoa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tsoa/-/tsoa-5.1.1.tgz", + "integrity": "sha512-U6+5CyD3+u9Dtza0fBnv4+lgmbZEskYljzRpKf3edGCAGtMKD2rfjtDw9jUdTfWb1FEDvsnR3pRvsSGBXaOdsA==", + "dependencies": { + "@tsoa/cli": "^5.1.1", + "@tsoa/runtime": "^5.0.0" + }, + "bin": { + "tsoa": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "yarn": ">=1.9.4" + } + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils-etc": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tsutils-etc/-/tsutils-etc-1.4.2.tgz", + "integrity": "sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==", + "dev": true, + "dependencies": { + "@types/yargs": "^17.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "ts-flags": "bin/ts-flags", + "ts-kind": "bin/ts-kind" + }, + "peerDependencies": { + "tsutils": "^3.0.0", + "typescript": ">=4.0.0" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/tsyringe": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.8.0.tgz", + "integrity": "sha512-YB1FG+axdxADa3ncEtRnQCFq/M0lALGLxSZeVNbTU8NqhOVc51nnv2CISTcvc1kyv6EGPtXVr0v6lWeDxiijOA==", + "dependencies": { + "tslib": "^1.9.3" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/tsyringe/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tuf-js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "dev": true, + "dependencies": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/ua-parser-js": { + "version": "0.7.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", + "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "engines": { + "node": "*" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "peer": true, + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true, + "peer": true + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "peer": true + }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "dependencies": { + "pako": "^1.0.11" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vite": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz", + "integrity": "sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==", + "dev": true, + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.26", + "rollup": "^3.25.2" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "deprecated": "Use your platform's native performance.now() and performance.timeOrigin.", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "dependencies": { + "xml-name-validator": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "node_modules/webdav": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webdav/-/webdav-4.10.0.tgz", + "integrity": "sha512-8PevPYhFsgbDhVGQQyrfBDYHiCYtN01qVX9zjFDA/OjIFqu28SsZuZdvGxBIQu2/e3Wp8M5oUpYvLM3uLP8g6A==", + "peer": true, + "dependencies": { + "axios": "^0.27.2", + "base-64": "^1.0.0", + "byte-length": "^1.0.2", + "fast-xml-parser": "^3.19.0", + "he": "^1.2.0", + "hot-patcher": "^0.5.0", + "layerr": "^0.1.2", + "md5": "^2.3.0", + "minimatch": "^5.0.1", + "nested-property": "^4.0.0", + "path-posix": "^1.0.0", + "url-join": "^4.0.1", + "url-parse": "^1.5.10" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/webdav/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/webdav/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "peer": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true, + "engines": { + "node": ">=10.4" + } + }, + "node_modules/webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "dev": true, + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", + "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/webpack-dev-server/node_modules/webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-subresource-integrity": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", + "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", + "dev": true, + "dependencies": { + "typed-assert": "^1.0.8" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "html-webpack-plugin": ">= 5.0.0-beta.1 < 6", + "webpack": "^5.12.0" + }, + "peerDependenciesMeta": { + "html-webpack-plugin": { + "optional": true + } + } + }, + "node_modules/webpack/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/wget-improved-2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/wget-improved-2/-/wget-improved-2-3.3.0.tgz", + "integrity": "sha512-NSPde/8mUqgmznPhO7oB5gS8IVUlR7GOlY857IaAf3PkkHbx/6FwZxUhW+GRP1GQbZDnCMF5fPieWXFng8Z43A==", + "dependencies": { + "minimist": "1.2.6", + "tunnel": "0.0.6" + }, + "bin": { + "nwget": "bin/nwget" + }, + "engines": { + "node": ">= 0.6.18" + } + }, + "node_modules/wget-improved-2/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.17", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.17.tgz", + "integrity": "sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ==" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "dependencies": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "node_modules/winston": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.10.0.tgz", + "integrity": "sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g==", + "dependencies": { + "@colors/colors": "1.5.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-daily-rotate-file": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz", + "integrity": "sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==", + "dependencies": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "winston": "^3" + } + }, + "node_modules/winston-transport": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 6.4.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "peer": true, + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "node_modules/xml-writer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/xml-writer/-/xml-writer-1.7.0.tgz", + "integrity": "sha512-elFVMRiV5jb59fbc87zzVa0C01QLBEWP909mRuWqFqrYC5wNTH5QW4AaKMNv7d6zAsuOulkD7wnztZNLQW0Nfg==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-12.0.0.tgz", + "integrity": "sha512-lMo8DJ8u6JRWp0/Y4XLa/atVDr75H9litKlb2E5j3V3MesoL50EBgZDWoLT3F/LztVnG67GjPXLZpqcky/UMnQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/xpath": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.33.tgz", + "integrity": "sha512-NNXnzrkDrAzalLhIUc01jO2mOzXGXh1JwPgkihcLLzw98c0WgYDmmjSh1Kl3wzaxSVWMuA+fe0WTWOBDWCBmNA==", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "dependencies": { + "cuint": "^0.2.2" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zone.js": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.1.tgz", + "integrity": "sha512-+bIeDAFEBYuXRuU3qGQvzdPap+N1zjM4KkBAiiQuVVCrHrhjDuY6VkUhNa5+U27+9w0q3fbKiMCbpJ0XzMmSWA==", + "dependencies": { + "tslib": "^2.3.0" + } + }, + "projects/aas-lib": { + "version": "2.0.0", + "peerDependencies": { + "@angular/animations": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "rxjs": "~7.8.1", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + } + }, + "projects/aas-portal": { + "version": "2.0.0", + "license": "Apache-2.0", + "dependencies": { + "@angular/animations": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "rxjs": "~7.8.1", + "tslib": "^2.6.1", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^16.1.8", + "@angular-eslint/builder": "16.1.0", + "@angular-eslint/eslint-plugin": "16.1.0", + "@angular-eslint/eslint-plugin-template": "16.1.0", + "@angular-eslint/schematics": "16.1.0", + "@angular-eslint/template-parser": "16.1.0", + "@angular/cli": "^16.1.8", + "@angular/compiler-cli": "^16.1.8", + "@ngrx/eslint-plugin": "^16.1.0", + "@types/bootstrap": "^5.2.6", + "@types/jasmine": "^4.3.5", + "@types/jquery": "^3.5.16", + "@types/lodash-es": "^4.17.8", + "@types/uuid": "^8.3.4", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "eslint": "^8.46.0", + "jasmine-core": "^5.1.0", + "jest": "^29.6.2", + "karma": "^6.4.2", + "karma-chrome-launcher": "^3.2.0", + "karma-coverage": "^2.2.1", + "karma-jasmine": "^5.1.0", + "karma-jasmine-html-reporter": "^2.1.0", + "karma-junit-reporter": "^2.0.1", + "ng-packagr": "^16.1.0", + "rimraf": "^5.0.1", + "ts-node": "^10.9.1", + "typescript": "5.0.*" + } + }, + "projects/aas-server": { + "version": "2.0.0", + "license": "Apache 2.0", + "dependencies": { + "@xmldom/xmldom": "^0.8.10", + "bcryptjs": "^2.4.3", + "common": "2.0.0", + "cors": "^2.8.5", + "express": "^4.18.2", + "form-data": "^4.0.0", + "jimp": "^0.22.10", + "jsonwebtoken": "^9.0.1", + "jszip": "^3.10.1", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "mongoose": "^7.4.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "node-opcua": "^2.108.0", + "node-opcua-client-crawler": "^2.108.0", + "nodemailer": "^6.9.4", + "owncloud-sdk": "^3.1.0-alpha.7", + "reflect-metadata": "^0.1.13", + "rxjs": "~7.8.1", + "swagger-ui-express": "^5.0.0", + "tslib": "^2.6.1", + "tsoa": "^5.1.1", + "tsyringe": "^4.8.0", + "winston": "^3.10.0", + "winston-daily-rotate-file": "^4.7.1", + "ws": "^8.13.0", + "xpath": "^0.0.33" + }, + "devDependencies": { + "@jest/globals": "^29.6.2", + "@types/bcryptjs": "^2.4.2", + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/jquery": "^3.5.16", + "@types/jsonwebtoken": "^9.0.2", + "@types/lodash-es": "^4.17.8", + "@types/morgan": "^1.9.4", + "@types/multer": "^1.4.7", + "@types/node": "^18.16.0", + "@types/nodemailer": "^6.4.9", + "@types/supertest": "^2.0.12", + "@types/swagger-ui-express": "^4.1.3", + "@types/ws": "^8.5.5", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "babel-plugin-transform-import-meta": "^2.2.1", + "esbuild": "^0.18.19", + "eslint": "^8.46.0", + "jest": "^29.6.2", + "ng-packagr": "^16.1.0", + "rimraf": "^5.0.1", + "supertest": "^6.3.3", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "5.0.*" + } + }, + "projects/aas-server/node_modules/@types/node": { + "version": "18.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz", + "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==", + "dev": true + }, + "projects/common": { + "version": "2.0.0", + "license": "Apache-2.0", + "peerDependencies": { + "lodash-es": "^4.17.21" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@angular-devkit/architect": { + "version": "0.1602.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.0.tgz", + "integrity": "sha512-ZRmUTBeD+uGr605eOHnsovEn6f1mOBI+kxP64DRvagNweX5TN04s3iyQ8jmLSAHQD9ush31LFxv3dVNxv3ceXQ==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.0", + "rxjs": "7.8.1" + } + }, + "@angular-devkit/build-angular": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-16.2.0.tgz", + "integrity": "sha512-miylwjOqvlKmYrzS84bjRaJrecZxOXH9xsPVvQE8VBe8UKePJjRAL6yyOqXUOGtzlch2YmT98RAnuni7y0FEAw==", + "dev": true, + "requires": { + "@ampproject/remapping": "2.2.1", + "@angular-devkit/architect": "0.1602.0", + "@angular-devkit/build-webpack": "0.1602.0", + "@angular-devkit/core": "16.2.0", + "@babel/core": "7.22.9", + "@babel/generator": "7.22.9", + "@babel/helper-annotate-as-pure": "7.22.5", + "@babel/helper-split-export-declaration": "7.22.6", + "@babel/plugin-proposal-async-generator-functions": "7.20.7", + "@babel/plugin-transform-async-to-generator": "7.22.5", + "@babel/plugin-transform-runtime": "7.22.9", + "@babel/preset-env": "7.22.9", + "@babel/runtime": "7.22.6", + "@babel/template": "7.22.5", + "@discoveryjs/json-ext": "0.5.7", + "@ngtools/webpack": "16.2.0", + "@vitejs/plugin-basic-ssl": "1.0.1", + "ansi-colors": "4.1.3", + "autoprefixer": "10.4.14", + "babel-loader": "9.1.3", + "babel-plugin-istanbul": "6.1.1", + "browserslist": "^4.21.5", + "chokidar": "3.5.3", + "copy-webpack-plugin": "11.0.0", + "critters": "0.0.20", + "css-loader": "6.8.1", + "esbuild": "0.18.17", + "esbuild-wasm": "0.18.17", + "fast-glob": "3.3.1", + "guess-parser": "0.4.22", + "https-proxy-agent": "5.0.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "karma-source-map-support": "1.4.0", + "less": "4.1.3", + "less-loader": "11.1.0", + "license-webpack-plugin": "4.0.2", + "loader-utils": "3.2.1", + "magic-string": "0.30.1", + "mini-css-extract-plugin": "2.7.6", + "mrmime": "1.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "parse5-html-rewriting-stream": "7.0.0", + "picomatch": "2.3.1", + "piscina": "4.0.0", + "postcss": "8.4.27", + "postcss-loader": "7.3.3", + "resolve-url-loader": "5.0.0", + "rxjs": "7.8.1", + "sass": "1.64.1", + "sass-loader": "13.3.2", + "semver": "7.5.4", + "source-map-loader": "4.0.1", + "source-map-support": "0.5.21", + "terser": "5.19.2", + "text-table": "0.2.0", + "tree-kill": "1.2.2", + "tslib": "2.6.1", + "vite": "4.4.7", + "webpack": "5.88.2", + "webpack-dev-middleware": "6.1.1", + "webpack-dev-server": "4.15.1", + "webpack-merge": "5.9.0", + "webpack-subresource-integrity": "5.1.0" + }, + "dependencies": { + "@babel/core": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@esbuild/android-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.17.tgz", + "integrity": "sha512-wHsmJG/dnL3OkpAcwbgoBTTMHVi4Uyou3F5mf58ZtmUyIKfcdA7TROav/6tCzET4A3QW2Q2FC+eFneMU+iyOxg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.17.tgz", + "integrity": "sha512-9np+YYdNDed5+Jgr1TdWBsozZ85U1Oa3xW0c7TWqH0y2aGghXtZsuT8nYRbzOMcl0bXZXjOGbksoTtVOlWrRZg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.17.tgz", + "integrity": "sha512-O+FeWB/+xya0aLg23hHEM2E3hbfwZzjqumKMSIqcHbNvDa+dza2D0yLuymRBQQnC34CWrsJUXyH2MG5VnLd6uw==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.17.tgz", + "integrity": "sha512-M9uJ9VSB1oli2BE/dJs3zVr9kcCBBsE883prage1NWz6pBS++1oNn/7soPNS3+1DGj0FrkSvnED4Bmlu1VAE9g==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.17.tgz", + "integrity": "sha512-XDre+J5YeIJDMfp3n0279DFNrGCXlxOuGsWIkRb1NThMZ0BsrWXoTg23Jer7fEXQ9Ye5QjrvXpxnhzl3bHtk0g==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.17.tgz", + "integrity": "sha512-cjTzGa3QlNfERa0+ptykyxs5A6FEUQQF0MuilYXYBGdBxD3vxJcKnzDlhDCa1VAJCmAxed6mYhA2KaJIbtiNuQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.17.tgz", + "integrity": "sha512-sOxEvR8d7V7Kw8QqzxWc7bFfnWnGdaFBut1dRUYtu+EIRXefBc/eIsiUiShnW0hM3FmQ5Zf27suDuHsKgZ5QrA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.17.tgz", + "integrity": "sha512-2d3Lw6wkwgSLC2fIvXKoMNGVaeY8qdN0IC3rfuVxJp89CRfA3e3VqWifGDfuakPmp90+ZirmTfye1n4ncjv2lg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.17.tgz", + "integrity": "sha512-c9w3tE7qA3CYWjT+M3BMbwMt+0JYOp3vCMKgVBrCl1nwjAlOMYzEo+gG7QaZ9AtqZFj5MbUc885wuBBmu6aADQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.17.tgz", + "integrity": "sha512-1DS9F966pn5pPnqXYz16dQqWIB0dmDfAQZd6jSSpiT9eX1NzKh07J6VKR3AoXXXEk6CqZMojiVDSZi1SlmKVdg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.17.tgz", + "integrity": "sha512-EvLsxCk6ZF0fpCB6w6eOI2Fc8KW5N6sHlIovNe8uOFObL2O+Mr0bflPHyHwLT6rwMg9r77WOAWb2FqCQrVnwFg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.17.tgz", + "integrity": "sha512-e0bIdHA5p6l+lwqTE36NAW5hHtw2tNRmHlGBygZC14QObsA3bD4C6sXLJjvnDIjSKhW1/0S3eDy+QmX/uZWEYQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.17.tgz", + "integrity": "sha512-BAAilJ0M5O2uMxHYGjFKn4nJKF6fNCdP1E0o5t5fvMYYzeIqy2JdAP88Az5LHt9qBoUa4tDaRpfWt21ep5/WqQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.17.tgz", + "integrity": "sha512-Wh/HW2MPnC3b8BqRSIme/9Zhab36PPH+3zam5pqGRH4pE+4xTrVLx2+XdGp6fVS3L2x+DrsIcsbMleex8fbE6g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.17.tgz", + "integrity": "sha512-j/34jAl3ul3PNcK3pfI0NSlBANduT2UO5kZ7FCaK33XFv3chDhICLY8wJJWIhiQ+YNdQ9dxqQctRg2bvrMlYgg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.17.tgz", + "integrity": "sha512-QM50vJ/y+8I60qEmFxMoxIx4de03pGo2HwxdBeFd4nMh364X6TIBZ6VQ5UQmPbQWUVWHWws5MmJXlHAXvJEmpQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.17.tgz", + "integrity": "sha512-/jGlhWR7Sj9JPZHzXyyMZ1RFMkNPjC6QIAan0sDOtIo2TYk3tZn5UDrkE0XgsTQCxWTTOcMPf9p6Rh2hXtl5TQ==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.17.tgz", + "integrity": "sha512-rSEeYaGgyGGf4qZM2NonMhMOP/5EHp4u9ehFiBrg7stH6BYEEjlkVREuDEcQ0LfIl53OXLxNbfuIj7mr5m29TA==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.17.tgz", + "integrity": "sha512-Y7ZBbkLqlSgn4+zot4KUNYst0bFoO68tRgI6mY2FIM+b7ZbyNVtNbDP5y8qlu4/knZZ73fgJDlXID+ohY5zt5g==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.17.tgz", + "integrity": "sha512-bwPmTJsEQcbZk26oYpc4c/8PvTY3J5/QK8jM19DVlEsAB41M39aWovWoHtNm78sd6ip6prilxeHosPADXtEJFw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.17.tgz", + "integrity": "sha512-H/XaPtPKli2MhW+3CQueo6Ni3Avggi6hP/YvgkEe1aSaxw+AeO8MFjq8DlgfTd9Iz4Yih3QCZI6YLMoyccnPRg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.17.tgz", + "integrity": "sha512-fGEb8f2BSA3CW7riJVurug65ACLuQAzKq0SSqkY2b2yHHH0MzDfbLyKIGzHwOI/gkHcxM/leuSW6D5w/LMNitA==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.17.tgz", + "integrity": "sha512-1GJtYnUxsJreHYA0Y+iQz2UEykonY66HNWOb0yXYZi9/kNrORUEHVg87eQsCtqh59PEJ5YVZJO98JHznMJSWjg==", + "dev": true, + "optional": true, + "requires": { + "@esbuild/android-arm": "0.18.17", + "@esbuild/android-arm64": "0.18.17", + "@esbuild/android-x64": "0.18.17", + "@esbuild/darwin-arm64": "0.18.17", + "@esbuild/darwin-x64": "0.18.17", + "@esbuild/freebsd-arm64": "0.18.17", + "@esbuild/freebsd-x64": "0.18.17", + "@esbuild/linux-arm": "0.18.17", + "@esbuild/linux-arm64": "0.18.17", + "@esbuild/linux-ia32": "0.18.17", + "@esbuild/linux-loong64": "0.18.17", + "@esbuild/linux-mips64el": "0.18.17", + "@esbuild/linux-ppc64": "0.18.17", + "@esbuild/linux-riscv64": "0.18.17", + "@esbuild/linux-s390x": "0.18.17", + "@esbuild/linux-x64": "0.18.17", + "@esbuild/netbsd-x64": "0.18.17", + "@esbuild/openbsd-x64": "0.18.17", + "@esbuild/sunos-x64": "0.18.17", + "@esbuild/win32-arm64": "0.18.17", + "@esbuild/win32-ia32": "0.18.17", + "@esbuild/win32-x64": "0.18.17" + } + } + } + }, + "@angular-devkit/build-webpack": { + "version": "0.1602.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.1602.0.tgz", + "integrity": "sha512-KdSr6iAcO30i/LIGL8mYi+d1buVXuDCp2dptzEJ4vxReOMFJca90KLwb+tVHEqqnDb0WkNfWm8Ii2QYh2FrNyA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1602.0", + "rxjs": "7.8.1" + } + }, + "@angular-devkit/core": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.0.tgz", + "integrity": "sha512-l1k6Rqm3YM16BEn3CWyQKrk9xfu+2ux7Bw3oS+h1TO4/RoxO2PgHj8LLRh/WNrYVarhaqO7QZ5ePBkXNMkzJ1g==", + "dev": true, + "requires": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.0", + "rxjs": "7.8.1", + "source-map": "0.7.4" + } + }, + "@angular-devkit/schematics": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.0.tgz", + "integrity": "sha512-QMDJXPE0+YQJ9Ap3MMzb0v7rx6ZbBEokmHgpdIjN3eILYmbAdsSGE8HTV8NjS9nKmcyE9OGzFCMb7PFrDTlTAw==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.0", + "jsonc-parser": "3.2.0", + "magic-string": "0.30.1", + "ora": "5.4.1", + "rxjs": "7.8.1" + } + }, + "@angular-eslint/builder": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.0.tgz", + "integrity": "sha512-KIkE2SI1twFKoCiF/k2VR3ojOcc7TD1xPyY4kbUrx/Gxp+XEzar7O29I/ztzL4eHPBM+Uh3/NwS/jvjjBxjgAg==", + "dev": true, + "requires": { + "@nx/devkit": "16.5.1", + "nx": "16.5.1" + } + }, + "@angular-eslint/bundled-angular-compiler": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/bundled-angular-compiler/-/bundled-angular-compiler-16.1.0.tgz", + "integrity": "sha512-5EFAWXuFJADr3imo/ZYshY8s0K7U7wyysnE2LXnpT9PAi5rmkzt70UNZNRuamCbXr4tdIiu+fXWOj7tUuJKnnw==", + "dev": true + }, + "@angular-eslint/eslint-plugin": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin/-/eslint-plugin-16.1.0.tgz", + "integrity": "sha512-BFzzJJlgQgWc8avdSBkaDWAzNSUqcwWy0L1iZSBdXGoIOxj72kLbwe99emb8M+rUfCveljQkeM2pcYu8XLbJIA==", + "dev": true, + "requires": { + "@angular-eslint/utils": "16.1.0", + "@typescript-eslint/utils": "5.62.0" + } + }, + "@angular-eslint/eslint-plugin-template": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/eslint-plugin-template/-/eslint-plugin-template-16.1.0.tgz", + "integrity": "sha512-wQHWR5vqWGgO7mqoG5ixXeplIlz/OmxBJE9QMLPTZE8GdaTx8+F/5J37OWh84zCpD3mOa/FHYZxBDm2MfUmA1Q==", + "dev": true, + "requires": { + "@angular-eslint/bundled-angular-compiler": "16.1.0", + "@angular-eslint/utils": "16.1.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "aria-query": "5.3.0", + "axobject-query": "3.1.1" + } + }, + "@angular-eslint/schematics": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/schematics/-/schematics-16.1.0.tgz", + "integrity": "sha512-L1tmP3R2krHyveaRXAvn/SeDoBFNpS1VtPPrzZm1NYr1qPcAxf3NtG2nnoyVFu6WZGt59ZGHNQ/dZxnXvm0UGg==", + "dev": true, + "requires": { + "@angular-eslint/eslint-plugin": "16.1.0", + "@angular-eslint/eslint-plugin-template": "16.1.0", + "@nx/devkit": "16.5.1", + "ignore": "5.2.4", + "nx": "16.5.1", + "strip-json-comments": "3.1.1", + "tmp": "0.2.1" + } + }, + "@angular-eslint/template-parser": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/template-parser/-/template-parser-16.1.0.tgz", + "integrity": "sha512-DOQtzVehtbO7+BQ+FMOXRsxGRjHb3ve6M+S4qASKTiI+twtONjRODcHezD3N4PDkjpKPbOnk7YnFsHur5csUNw==", + "dev": true, + "requires": { + "@angular-eslint/bundled-angular-compiler": "16.1.0", + "eslint-scope": "^7.0.0" + } + }, + "@angular-eslint/utils": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@angular-eslint/utils/-/utils-16.1.0.tgz", + "integrity": "sha512-u5XscYUq1F/7RuwyVIV2a280QL27lyQz434VYR+Np/oO21NGj5jxoRKb55xhXT9EFVs5Sy4JYeEUp6S75J/cUw==", + "dev": true, + "requires": { + "@angular-eslint/bundled-angular-compiler": "16.1.0", + "@typescript-eslint/utils": "5.62.0" + } + }, + "@angular/animations": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-16.2.1.tgz", + "integrity": "sha512-XVabK9fRKJaYPhW5wn8ySL4KL45N5Np+xOssWhLPDRDBdZjl62MExfpvMkamdkos6E1n1IGsy9wSemjnR4WKhg==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/cli": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.0.tgz", + "integrity": "sha512-xT8vJOyw6Rc2364XDW2jHagLgKu7342ktd/lt+c0u6R+AB2XVFMePR7VceLohX9N/vRUsbQ0nVSZr+ru/hA+HA==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.1602.0", + "@angular-devkit/core": "16.2.0", + "@angular-devkit/schematics": "16.2.0", + "@schematics/angular": "16.2.0", + "@yarnpkg/lockfile": "1.1.0", + "ansi-colors": "4.1.3", + "ini": "4.1.1", + "inquirer": "8.2.4", + "jsonc-parser": "3.2.0", + "npm-package-arg": "10.1.0", + "npm-pick-manifest": "8.0.1", + "open": "8.4.2", + "ora": "5.4.1", + "pacote": "15.2.0", + "resolve": "1.22.2", + "semver": "7.5.4", + "symbol-observable": "4.0.0", + "yargs": "17.7.2" + } + }, + "@angular/common": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-16.2.1.tgz", + "integrity": "sha512-druackA5JQpvfS8cD8DFtPRXGRKbhx3mQ778t1n6x3fXpIdGaAX+nSAgAKhIoF7fxWmu0KuHGzb+3BFlZRyTXw==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/compiler": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-16.2.1.tgz", + "integrity": "sha512-dPauu+ESn79d66U9nBvnunNuBk/UMqnm7iL9Q31J8OKYN/4vrKbsO57pmULOft/GRAYsE3FdLBH0NkocFZKIMQ==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/compiler-cli": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-16.2.1.tgz", + "integrity": "sha512-A5SyNZTZnXSCL5JVXHKbYj9p2dRYoeFnb6hGQFt2AuCcpUjVIIdwHtre3YzkKe5sFwepPctdoRe2fRXlTfTRjA==", + "requires": { + "@babel/core": "7.22.5", + "@jridgewell/sourcemap-codec": "^1.4.14", + "chokidar": "^3.0.0", + "convert-source-map": "^1.5.1", + "reflect-metadata": "^0.1.2", + "semver": "^7.0.0", + "tslib": "^2.3.0", + "yargs": "^17.2.1" + }, + "dependencies": { + "@babel/core": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + } + } + }, + "@angular/core": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-16.2.1.tgz", + "integrity": "sha512-Y+0jssQnJPovxMv9cDKYlp6BBHeFBLOHd/+FPv5IIGD1c7NwBP/TImJxCaIV78a57xnO8L0SFacDg/kULzvKrg==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/forms": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-16.2.1.tgz", + "integrity": "sha512-cCygiLfBAsVHdtKmNptlk2IgXu0wjRc8kSiiSnJkfK6U/NiNg8ADMiN7iYgKW2TD1ZRw+7dYZV856lxEy2n0+A==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/localize": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/localize/-/localize-16.2.1.tgz", + "integrity": "sha512-IMlDEuDNYtVTZ135ATm+YAksdCaFjkOsrtTPu3aIg08Dsyqw7awZ1lEmmmSpiflOqEfPjgHScLWhUMhER70aUg==", + "requires": { + "@babel/core": "7.22.5", + "fast-glob": "3.3.0", + "yargs": "^17.2.1" + }, + "dependencies": { + "@babel/core": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.5.tgz", + "integrity": "sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helpers": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + } + }, + "fast-glob": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@angular/platform-browser": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-16.2.1.tgz", + "integrity": "sha512-SH8zRiRAcw0B5/tVlEc5U/lN5F8g+JizSuu7BQvpCAQEDkM6IjF9LP36Bjav7JuadItbWLfT6peWYa1sJvax2w==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/platform-browser-dynamic": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-16.2.1.tgz", + "integrity": "sha512-dKMCSrbD/joOMXM1mhDOKNDZ1BxwO9r9uu5ZxY0L/fWm/ousgMucNikLr38vBudgWM8CN6BuabzkxWKcqi3k4g==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@angular/router": { + "version": "16.2.1", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-16.2.1.tgz", + "integrity": "sha512-C0WfcktsC25G37unxdH/5I7PbkVBSEB1o+0DJK9/HG97r1yzEkptF6fbRIzDBTS7dX0NfWN/PTAKF0ep7YlHvA==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@assemblyscript/loader": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@assemblyscript/loader/-/loader-0.10.1.tgz", + "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==", + "dev": true + }, + "@babel/code-frame": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.10.tgz", + "integrity": "sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==", + "requires": { + "@babel/highlight": "^7.22.10", + "chalk": "^2.4.2" + } + }, + "@babel/compat-data": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==" + }, + "@babel/core": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz", + "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==", + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-compilation-targets": "^7.22.10", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.10", + "@babel/parser": "^7.22.10", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.1" + }, + "dependencies": { + "@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "requires": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", + "requires": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", + "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz", + "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==", + "dev": true, + "requires": { + "@babel/types": "^7.22.10" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz", + "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==", + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz", + "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz", + "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.2.tgz", + "integrity": "sha512-k0qnnOqHn5dK9pZpfD5XXZ9SojAITdCKRn2Lp6rnDGzIbaP0rHyMPk/4wsSxVBVz4RfN0q6VpXWP2pDGIoQ7hw==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" + }, + "@babel/helper-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "requires": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz", + "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", + "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz", + "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-wrap-function": "^7.22.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.9.tgz", + "integrity": "sha512-LJIKvvpgPOPUThdYqcX6IXRuIcTkcAub0IaDRGCZH0p5GPUp7PhRU9QVgFcDDd51BaPkk77ZjqFwh6DZTAEmGg==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-member-expression-to-functions": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", + "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "dev": true, + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "requires": { + "@babel/types": "^7.22.5" + } + }, + "@babel/helper-string-parser": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" + }, + "@babel/helper-validator-option": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==" + }, + "@babel/helper-wrap-function": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz", + "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.10" + } + }, + "@babel/helpers": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz", + "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==", + "requires": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.10", + "@babel/types": "^7.22.10" + } + }, + "@babel/highlight": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.10.tgz", + "integrity": "sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ==", + "requires": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz", + "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz", + "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.5" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "requires": {} + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", + "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-attributes": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz", + "integrity": "sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", + "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-async-generator-functions": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.10.tgz", + "integrity": "sha512-eueE8lvKVzq5wIObKK/7dvoeKJ+xc6TvRn6aysIjS6pSCeLy7S/eVi7pEQknZqyqvzaNKdDtem8nUNTBgDVR2g==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz", + "integrity": "sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-remap-async-to-generator": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", + "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz", + "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz", + "integrity": "sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-class-static-block": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz", + "integrity": "sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz", + "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-optimise-call-expression": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", + "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/template": "^7.22.5" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz", + "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz", + "integrity": "sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz", + "integrity": "sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-dynamic-import": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz", + "integrity": "sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz", + "integrity": "sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-export-namespace-from": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz", + "integrity": "sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz", + "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", + "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-json-strings": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz", + "integrity": "sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", + "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-logical-assignment-operators": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz", + "integrity": "sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", + "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz", + "integrity": "sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz", + "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz", + "integrity": "sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz", + "integrity": "sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", + "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz", + "integrity": "sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz", + "integrity": "sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-transform-numeric-separator": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz", + "integrity": "sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-transform-object-rest-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz", + "integrity": "sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.5", + "@babel/helper-compilation-targets": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.22.5" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", + "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-replace-supers": "^7.22.5" + } + }, + "@babel/plugin-transform-optional-catch-binding": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz", + "integrity": "sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-transform-optional-chaining": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.10.tgz", + "integrity": "sha512-MMkQqZAZ+MGj+jGTG3OTuhKeBpNcO+0oCEbrGNEaOmiEn+1MzRyQlYsruGiU8RTK3zV6XwrVJTmwiDOyYK6J9g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz", + "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-methods": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz", + "integrity": "sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-private-property-in-object": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz", + "integrity": "sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-create-class-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", + "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", + "integrity": "sha512-F28b1mDt8KcT5bUyJc/U9nwzw6cV+UmTeRlXYIl2TNqMMJif0Jeey9/RQ3C4NOd2zp0/TRsDns9ttj2L523rsw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "regenerator-transform": "^0.15.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz", + "integrity": "sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.9.tgz", + "integrity": "sha512-9KjBH61AGJetCPYp/IEyLEp47SyybZb0nDRpBvmtEkm+rUIwxdlKpyNHI1TmsGkeuLclJdleQHRZ8XLBnnh8CQ==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", + "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", + "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz", + "integrity": "sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", + "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz", + "integrity": "sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.10.tgz", + "integrity": "sha512-lRfaRKGZCBqDlRU3UIFovdp9c9mEvlylmpod0/OatICsSfuQ9YFthRo1tpTkGsklEefZdqlEFdY4A2dwTb6ohg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-property-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz", + "integrity": "sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz", + "integrity": "sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/plugin-transform-unicode-sets-regex": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz", + "integrity": "sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + } + }, + "@babel/preset-env": { + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.9.tgz", + "integrity": "sha512-wNi5H/Emkhll/bqPjsjQorSykrlfY5OWakd6AulLvMEytpKasMVUpVy8RL4qBIBs5Ac6/5i0/Rv0b/Fg6Eag/g==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.5", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.22.5", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.22.5", + "@babel/plugin-transform-async-generator-functions": "^7.22.7", + "@babel/plugin-transform-async-to-generator": "^7.22.5", + "@babel/plugin-transform-block-scoped-functions": "^7.22.5", + "@babel/plugin-transform-block-scoping": "^7.22.5", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-class-static-block": "^7.22.5", + "@babel/plugin-transform-classes": "^7.22.6", + "@babel/plugin-transform-computed-properties": "^7.22.5", + "@babel/plugin-transform-destructuring": "^7.22.5", + "@babel/plugin-transform-dotall-regex": "^7.22.5", + "@babel/plugin-transform-duplicate-keys": "^7.22.5", + "@babel/plugin-transform-dynamic-import": "^7.22.5", + "@babel/plugin-transform-exponentiation-operator": "^7.22.5", + "@babel/plugin-transform-export-namespace-from": "^7.22.5", + "@babel/plugin-transform-for-of": "^7.22.5", + "@babel/plugin-transform-function-name": "^7.22.5", + "@babel/plugin-transform-json-strings": "^7.22.5", + "@babel/plugin-transform-literals": "^7.22.5", + "@babel/plugin-transform-logical-assignment-operators": "^7.22.5", + "@babel/plugin-transform-member-expression-literals": "^7.22.5", + "@babel/plugin-transform-modules-amd": "^7.22.5", + "@babel/plugin-transform-modules-commonjs": "^7.22.5", + "@babel/plugin-transform-modules-systemjs": "^7.22.5", + "@babel/plugin-transform-modules-umd": "^7.22.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", + "@babel/plugin-transform-new-target": "^7.22.5", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.5", + "@babel/plugin-transform-numeric-separator": "^7.22.5", + "@babel/plugin-transform-object-rest-spread": "^7.22.5", + "@babel/plugin-transform-object-super": "^7.22.5", + "@babel/plugin-transform-optional-catch-binding": "^7.22.5", + "@babel/plugin-transform-optional-chaining": "^7.22.6", + "@babel/plugin-transform-parameters": "^7.22.5", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.5", + "@babel/plugin-transform-property-literals": "^7.22.5", + "@babel/plugin-transform-regenerator": "^7.22.5", + "@babel/plugin-transform-reserved-words": "^7.22.5", + "@babel/plugin-transform-shorthand-properties": "^7.22.5", + "@babel/plugin-transform-spread": "^7.22.5", + "@babel/plugin-transform-sticky-regex": "^7.22.5", + "@babel/plugin-transform-template-literals": "^7.22.5", + "@babel/plugin-transform-typeof-symbol": "^7.22.5", + "@babel/plugin-transform-unicode-escapes": "^7.22.5", + "@babel/plugin-transform-unicode-property-regex": "^7.22.5", + "@babel/plugin-transform-unicode-regex": "^7.22.5", + "@babel/plugin-transform-unicode-sets-regex": "^7.22.5", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.4", + "babel-plugin-polyfill-corejs3": "^0.8.2", + "babel-plugin-polyfill-regenerator": "^0.5.1", + "core-js-compat": "^3.31.0", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, + "@babel/runtime": { + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "@babel/template": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", + "requires": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + } + }, + "@babel/traverse": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz", + "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==", + "requires": { + "@babel/code-frame": "^7.22.10", + "@babel/generator": "^7.22.10", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.10", + "@babel/types": "^7.22.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/generator": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz", + "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==", + "requires": { + "@babel/types": "^7.22.10", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + } + } + } + }, + "@babel/types": { + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", + "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", + "requires": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==" + }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "dependencies": { + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + } + } + }, + "@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, + "@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true + }, + "@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "dev": true, + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jest/console": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.2.tgz", + "integrity": "sha512-0N0yZof5hi44HAR2pPS+ikJ3nzKNoZdVu8FffRf3wy47I7Dm7etk/3KetMdRUqzVd16V4O2m2ISpNTbnIuqy1w==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/core": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.2.tgz", + "integrity": "sha512-Oj+5B+sDMiMWLhPFF+4/DvHOf+U10rgvCLGPHP8Xlsy/7QxS51aU/eBngudHlJXnaWD5EohAgJ4js+T6pa+zOg==", + "dev": true, + "requires": { + "@jest/console": "^29.6.2", + "@jest/reporters": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.6.2", + "jest-resolve-dependencies": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "jest-watcher": "^29.6.2", + "micromatch": "^4.0.4", + "pretty-format": "^29.6.2", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/environment": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.2.tgz", + "integrity": "sha512-AEcW43C7huGd/vogTddNNTDRpO6vQ2zaQNrttvWV18ArBx9Z56h7BIsXkNFJVOO4/kblWEQz30ckw0+L3izc+Q==", + "dev": true, + "requires": { + "@jest/fake-timers": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "jest-mock": "^29.6.2" + } + }, + "@jest/expect": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-m6DrEJxVKjkELTVAztTLyS/7C92Y2b0VYqmDROYKLLALHn8T/04yPs70NADUYPrV3ruI+H3J0iUIuhkjp7vkfg==", + "dev": true, + "requires": { + "expect": "^29.6.2", + "jest-snapshot": "^29.6.2" + } + }, + "@jest/expect-utils": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.2.tgz", + "integrity": "sha512-6zIhM8go3RV2IG4aIZaZbxwpOzz3ZiM23oxAlkquOIole+G6TrbeXnykxWYlqF7kz2HlBjdKtca20x9atkEQYg==", + "dev": true, + "requires": { + "jest-get-type": "^29.4.3" + } + }, + "@jest/fake-timers": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.2.tgz", + "integrity": "sha512-euZDmIlWjm1Z0lJ1D0f7a0/y5Kh/koLFMUBE5SUYWrmy8oNhJpbTBDAP6CxKnadcMLDoDf4waRYCe35cH6G6PA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" + } + }, + "@jest/globals": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.2.tgz", + "integrity": "sha512-cjuJmNDjs6aMijCmSa1g2TNG4Lby/AeU7/02VtpW+SLcZXzOLK2GpN2nLqcFjmhy3B3AoPeQVx7BnyOf681bAw==", + "dev": true, + "requires": { + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.2" + } + }, + "@jest/reporters": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.2.tgz", + "integrity": "sha512-sWtijrvIav8LgfJZlrGCdN0nP2EWbakglJY49J1Y5QihcQLfy7ovyxxjJBRXMNltgt4uPtEcFmIMbVshEDfFWw==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/schemas": { + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.27.8" + } + }, + "@jest/source-map": { + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + } + }, + "@jest/test-result": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.2.tgz", + "integrity": "sha512-3VKFXzcV42EYhMCsJQURptSqnyjqCGbtLuX5Xxb6Pm6gUf1wIRIl+mandIRGJyWKgNKYF9cnstti6Ls5ekduqw==", + "dev": true, + "requires": { + "@jest/console": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.2.tgz", + "integrity": "sha512-GVYi6PfPwVejO7slw6IDO0qKVum5jtrJ3KoLGbgBWyr2qr4GaxFV6su+ZAjdTX75Sr1DkMFRk09r2ZVa+wtCGw==", + "dev": true, + "requires": { + "@jest/test-result": "^29.6.2", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "slash": "^3.0.0" + } + }, + "@jest/transform": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz", + "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.6.2", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jest/types": { + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@jimp/bmp": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.22.10.tgz", + "integrity": "sha512-1UXRl1Nw1KptZ1r0ANqtXOst9vGH51dq7keVKQzyyTO2lz4dOaezS9StuSTNh+RmiHg/SVPaFRpPfB0S/ln4Kg==", + "requires": { + "@jimp/utils": "^0.22.10", + "bmp-js": "^0.1.0" + } + }, + "@jimp/core": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.22.10.tgz", + "integrity": "sha512-ZKyrehVy6wu1PnBXIUpn/fXmyMRQiVSbvHDubgXz4bfTOao3GiOurKHjByutQIgozuAN6ZHWiSge1dKA+dex3w==", + "requires": { + "@jimp/utils": "^0.22.10", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "exif-parser": "^0.1.12", + "file-type": "^16.5.4", + "isomorphic-fetch": "^3.0.0", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.6.0" + } + }, + "@jimp/custom": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.22.10.tgz", + "integrity": "sha512-sPZkUYe1hu0iIgNisjizxPJqq2vaaKvkCkPoXq2U6UV3ZA1si/WVdrg25da3IcGIEV+83AoHgM8TvqlLgrCJsg==", + "requires": { + "@jimp/core": "^0.22.10" + } + }, + "@jimp/gif": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.22.10.tgz", + "integrity": "sha512-yEX2dSpamvkSx1PPDWGnKeWDrBz0vrCKjVG/cn4Zr68MRRT75tbZIeOrBa+RiUpY3ho5ix7d36LkYvt3qfUIhQ==", + "requires": { + "@jimp/utils": "^0.22.10", + "gifwrap": "^0.10.1", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.22.10.tgz", + "integrity": "sha512-6bu98pAcVN4DY2oiDLC4TOgieX/lZrLd1tombWZOFCN5PBmqaHQxm7IUmT+Wj4faEvh8QSHgVLSA+2JQQRJWVA==", + "requires": { + "@jimp/utils": "^0.22.10", + "jpeg-js": "^0.4.4" + } + }, + "@jimp/plugin-blit": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.22.10.tgz", + "integrity": "sha512-6EI8Sl+mxYHEIy6Yteh6eknD+EZguKpNdr3sCKxNezmLR0+vK99vHcllo6uGSjXXiwtwS67Xqxn8SsoatL+UJQ==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-blur": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.22.10.tgz", + "integrity": "sha512-4XRTWuPVdMXJeclJMisXPGizeHtTryVaVV5HnuQXpKqIZtzXReCCpNGH8q/i0kBQOQMXhGWS3mpqOEwtpPePKw==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-circle": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-0.22.10.tgz", + "integrity": "sha512-mhcwTO1ywRxiCgtLGge6tDDIDPlX6qkI3CY+BjgGG/XhVHccCddXgOGLdlf+5OuKIEF2Nqs0V01LQEQIJFTmEw==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-color": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.22.10.tgz", + "integrity": "sha512-e4t3L7Kedd96E0x1XjsTM6NcgulKUU66HdFTao7Tc9FYJRFSlttARZ/C6LEryGDm/i69R6bJEpo7BkNz0YL55Q==", + "requires": { + "@jimp/utils": "^0.22.10", + "tinycolor2": "^1.6.0" + } + }, + "@jimp/plugin-contain": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.22.10.tgz", + "integrity": "sha512-eP8KrzctuEoqibQAxi9WhbnoRosydhiwg+IYya3dKuKDBTrD9UHt+ERlPQ/lTNWHzV/l4S1ntV3r9s9saJgsXA==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-cover": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.22.10.tgz", + "integrity": "sha512-kJCwL5T1igfa0InCfkE7bBeqg26m46aoRt10ug+rvm11P6RrvRMGrgINFyIKB+mnB7CiyBN/MOula1CvLhSInQ==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-crop": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.22.10.tgz", + "integrity": "sha512-BOZ+YGaZlhU7c5ye65RxikicXH0Ki0It6/XHISvipR5WZrfjLjL2Ke20G+AGnwBQc76gKenVcMXVUCnEjtZV+Q==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-displace": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.22.10.tgz", + "integrity": "sha512-llNiWWMTKISDXt5+cXI0GaFmZWAjlT+4fFLYf4eXquuL/9wZoQsEBhv2GdGd48mkiS8jZq1Nnb2Q4ehEPTvrzw==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-dither": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.22.10.tgz", + "integrity": "sha512-05WLmeV5M+P/0FS+bWf13hMew2X0oa8w9AtmevL2UyA/5GqiyvP2Xm5WfGQ8oFiiMvpnL6RFomJQOZtWca0C2w==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-fisheye": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.10.tgz", + "integrity": "sha512-InjiXvc7Gkzrx8VWtU97kDqV7ENnhHGPULymJWeZaF2aicud9Fpk4iCtd/DcZIrk7Cbe60A8RwNXN00HXIbSCg==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-flip": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.22.10.tgz", + "integrity": "sha512-42GkGtTHWnhnwTMPVK/kXObZbkYIpQWfuIfy5EMEMk6zRj05zpv4vsjkKWfuemweZINwfvD7wDJF7FVFNNcZZg==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-gaussian": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.10.tgz", + "integrity": "sha512-ykrG/6lTp9Q5YA8jS5XzwMHtRxb9HOFMgtmnrUZ8kU+BK8REecfy9Ic5BUEOjCYvS1a/xLsnrZQU07iiYxBxFg==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-invert": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.22.10.tgz", + "integrity": "sha512-d8j9BlUJYs/c994t4azUWSWmQq4LLPG4ecm8m6SSNqap+S/HlVQGqjYhJEBbY9EXkOTYB9vBL9bqwSM1Rr6paA==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-mask": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.22.10.tgz", + "integrity": "sha512-yRBs1230XZkz24uFTdTcSlZ0HXZpIWzM3iFQN56MzZ7USgdVZjPPDCQ8I9RpqfZ36nDflQkUO0wV7ucsi4ogow==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-normalize": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.22.10.tgz", + "integrity": "sha512-Wk9GX6eJMchX/ZAazVa70Fagu+OXMvHiPY+HrcEwcclL+p1wo8xAHEsf9iKno7Ja4EU9lLhbBRY5hYJyiKMEkg==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-print": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.22.10.tgz", + "integrity": "sha512-1U3VloIR+beE1kWPdGEJMiE2h1Do29iv3w8sBbvPyRP4qXxRFcDpmCGtctsrKmb1krlBFlj8ubyAY90xL+5n9w==", + "requires": { + "@jimp/utils": "^0.22.10", + "load-bmfont": "^1.4.1" + } + }, + "@jimp/plugin-resize": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.22.10.tgz", + "integrity": "sha512-ixomxVcnAONXDgaq0opvAx4UAOiEhOA/tipuhFFOvPKFd4yf1BAnEviB5maB0SBHHkJXPUSzDp/73xVTMGSe7g==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-rotate": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.22.10.tgz", + "integrity": "sha512-eeFX8dnRyf3LAdsdXWKWuN18hLRg8zy1cP0cP9rHzQVWRK7ck/QsLxK1vHq7MADGwQalNaNTJ9SQxH6c8mz6jw==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-scale": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.22.10.tgz", + "integrity": "sha512-TG/H0oUN69C9ArBCZg4PmuoixFVKIiru8282KzSB/Tp1I0xwX0XLTv3dJ5pobPlIgPcB+TmD4xAIdkCT4rtWxg==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-shadow": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-shadow/-/plugin-shadow-0.22.10.tgz", + "integrity": "sha512-TN9xm6fI7XfxbMUQqFPZjv59Xdpf0tSiAQdINB4g6pJMWiVANR/74OtDONoy3KKpenu5Y38s+FkrtID/KcQAhw==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugin-threshold": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-0.22.10.tgz", + "integrity": "sha512-DA2lSnU0TgIRbAgmXaxroYw3Ad6J2DOFEoJp0NleSm2h3GWbZEE5yW9U2B6hD3iqn4AenG4E2b2WzHXZyzSutw==", + "requires": { + "@jimp/utils": "^0.22.10" + } + }, + "@jimp/plugins": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.22.10.tgz", + "integrity": "sha512-KDMZyM6pmvS8freB+UBLko1TO/k4D7URS/nphCozuH+P7i3UMe7NdckXKJ8u+WD6sqN0YFYvBehpkpnUiw/91w==", + "requires": { + "@jimp/plugin-blit": "^0.22.10", + "@jimp/plugin-blur": "^0.22.10", + "@jimp/plugin-circle": "^0.22.10", + "@jimp/plugin-color": "^0.22.10", + "@jimp/plugin-contain": "^0.22.10", + "@jimp/plugin-cover": "^0.22.10", + "@jimp/plugin-crop": "^0.22.10", + "@jimp/plugin-displace": "^0.22.10", + "@jimp/plugin-dither": "^0.22.10", + "@jimp/plugin-fisheye": "^0.22.10", + "@jimp/plugin-flip": "^0.22.10", + "@jimp/plugin-gaussian": "^0.22.10", + "@jimp/plugin-invert": "^0.22.10", + "@jimp/plugin-mask": "^0.22.10", + "@jimp/plugin-normalize": "^0.22.10", + "@jimp/plugin-print": "^0.22.10", + "@jimp/plugin-resize": "^0.22.10", + "@jimp/plugin-rotate": "^0.22.10", + "@jimp/plugin-scale": "^0.22.10", + "@jimp/plugin-shadow": "^0.22.10", + "@jimp/plugin-threshold": "^0.22.10", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.22.10.tgz", + "integrity": "sha512-RYinU7tZToeeR2g2qAMn42AU+8OUHjXPKZZ9RkmoL4bguA1xyZWaSdr22/FBkmnHhOERRlr02KPDN1OTOYHLDQ==", + "requires": { + "@jimp/utils": "^0.22.10", + "pngjs": "^6.0.0" + } + }, + "@jimp/tiff": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.22.10.tgz", + "integrity": "sha512-OaivlSYzpNTHyH/h7pEtl3A7F7TbsgytZs52GLX/xITW92ffgDgT6PkldIrMrET6ERh/hdijNQiew7IoEEr2og==", + "requires": { + "utif2": "^4.0.1" + } + }, + "@jimp/types": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.22.10.tgz", + "integrity": "sha512-u/r+XYzbCx4zZukDmxx8S0er3Yq3iDPI6+31WKX0N18i2qPPJYcn8qwIFurfupRumGvJ8SlGLCgt/T+Y8zzUIw==", + "requires": { + "@jimp/bmp": "^0.22.10", + "@jimp/gif": "^0.22.10", + "@jimp/jpeg": "^0.22.10", + "@jimp/png": "^0.22.10", + "@jimp/tiff": "^0.22.10", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.22.10.tgz", + "integrity": "sha512-ztlOK9Mm2iLG2AMoabzM4i3WZ/FtshcgsJCbZCRUs/DKoeS2tySRJTnQZ1b7Roq0M4Ce+FUAxnCAcBV0q7PH9w==", + "requires": { + "regenerator-runtime": "^0.13.3" + } + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.5.tgz", + "integrity": "sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, + "@leichtgewicht/ip-codec": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", + "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" + }, + "@ng-bootstrap/ng-bootstrap": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/@ng-bootstrap/ng-bootstrap/-/ng-bootstrap-15.1.1.tgz", + "integrity": "sha512-nZlIMMggtI3IHkGs0XPrUIUdpeEzQvfGV9M4I9IvCqiS2n4RwWoUvWK1ICo4csZqFNBDlCQx956gO6ZZUSL2mw==", + "requires": { + "tslib": "^2.3.0" + } + }, + "@ngrx/effects": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/effects/-/effects-16.2.0.tgz", + "integrity": "sha512-zZfq47LNoiRK+uS66Xm36mN07zm11AER1D9lTalX/G6jrV0bywgnAaukNNav9E33ZRrPEnCD8uu9BXZoboEYgA==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngrx/eslint-plugin": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/eslint-plugin/-/eslint-plugin-16.2.0.tgz", + "integrity": "sha512-BeCBRLQge0OIUTS1bCNfXB0WjAdXvHl8RgdrkQ4n4gsvvfzO8zetNmQREcHJsvpyMz3YjJuiOueuaiBRdbZfMA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^5.4.0", + "eslint-etc": "^5.1.0", + "semver": "^7.3.5", + "strip-json-comments": "3.1.1" + } + }, + "@ngrx/store": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngrx/store/-/store-16.2.0.tgz", + "integrity": "sha512-C7oIUC87xXV+1dTGUwYG/L4p0IZdYv/Ou1nTL/LffyAHllmmygTA5gzLB87abLOhucAxlFIQMQ8t/GSxdk/+QA==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@ngtools/webpack": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-16.2.0.tgz", + "integrity": "sha512-c9jv4r7GnLTpnPOeF+a9yAm/3/2wwl9lMBU32i9hlY+q/Hqde4PiL95bUOLnRRL1I64DV7BFTlSZqSPgDpFXZQ==", + "dev": true, + "requires": {} + }, + "@ngx-translate/core": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/core/-/core-15.0.0.tgz", + "integrity": "sha512-Am5uiuR0bOOxyoercDnAA3rJVizo4RRqJHo8N3RqJ+XfzVP/I845yEnMADykOHvM6HkVm4SZSnJBOiz0Anx5BA==", + "requires": {} + }, + "@ngx-translate/http-loader": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ngx-translate/http-loader/-/http-loader-8.0.0.tgz", + "integrity": "sha512-SFMsdUcmHF5OdZkL1CHEoSAwbP5EbAOPTLLboOCRRoOg21P4GJx+51jxGdJeGve6LSKLf4Pay7BkTwmE6vxYlg==", + "requires": {} + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@npmcli/fs": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.0.tgz", + "integrity": "sha512-7kZUAaLscfgbwBQRbvdMYaZOWyMEcPTH/tJjnyAWJ/dvvs9Ef+CERx/qJb9GExJpl1qipaDGn7KqHnFGGixd0w==", + "dev": true, + "requires": { + "semver": "^7.3.5" + } + }, + "@npmcli/git": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", + "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", + "dev": true, + "requires": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@npmcli/installed-package-contents": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.0.2.tgz", + "integrity": "sha512-xACzLPhnfD51GKvTOOuNX2/V4G4mz9/1I2MfDoye9kBM3RYe5g2YbscsaGoTlaWqkxeiapBWyseULVKpSVHtKQ==", + "dev": true, + "requires": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "@npmcli/node-gyp": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", + "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", + "dev": true + }, + "@npmcli/promise-spawn": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", + "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", + "dev": true, + "requires": { + "which": "^3.0.0" + }, + "dependencies": { + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@npmcli/run-script": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", + "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", + "dev": true, + "requires": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + }, + "dependencies": { + "which": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", + "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "@nrwl/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-NB+DE/+AFJ7lKH/WBFyatJEhcZGj25F24ncDkwjZ6MzEiSOGOJS0LaV/R+VUsmS5EHTPXYOpn3zHWWAcJhyOmA==", + "dev": true, + "requires": { + "@nx/devkit": "16.5.1" + } + }, + "@nrwl/tao": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-16.5.1.tgz", + "integrity": "sha512-x+gi/fKdM6uQNIti9exFlm3V5LBP3Y8vOEziO42HdOigyrXa0S0HD2WMpccmp6PclYKhwEDUjKJ39xh5sdh4Ig==", + "dev": true, + "requires": { + "nx": "16.5.1" + } + }, + "@nx/devkit": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-16.5.1.tgz", + "integrity": "sha512-T1acZrVVmJw/sJ4PIGidCBYBiBqlg/jT9e8nIGXLSDS20xcLvfo4zBQf8UZLrmHglnwwpDpOWuVJCp2rYA5aDg==", + "dev": true, + "requires": { + "@nrwl/devkit": "16.5.1", + "ejs": "^3.1.7", + "ignore": "^5.0.4", + "semver": "7.5.3", + "tmp": "~0.2.1", + "tslib": "^2.3.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "@nx/nx-darwin-arm64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-16.5.1.tgz", + "integrity": "sha512-q98TFI4B/9N9PmKUr1jcbtD4yAFs1HfYd9jUXXTQOlfO9SbDjnrYJgZ4Fp9rMNfrBhgIQ4x1qx0AukZccKmH9Q==", + "dev": true, + "optional": true + }, + "@nx/nx-darwin-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-16.5.1.tgz", + "integrity": "sha512-j9HmL1l8k7EVJ3eOM5y8COF93gqrydpxCDoz23ZEtsY+JHY77VAiRQsmqBgEx9GGA2dXi9VEdS67B0+1vKariw==", + "dev": true, + "optional": true + }, + "@nx/nx-freebsd-x64": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-16.5.1.tgz", + "integrity": "sha512-CXSPT01aVS869tvCCF2tZ7LnCa8l41wJ3mTVtWBkjmRde68E5Up093hklRMyXb3kfiDYlfIKWGwrV4r0eH6x1A==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm-gnueabihf": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-16.5.1.tgz", + "integrity": "sha512-BhrumqJSZCWFfLFUKl4CAUwR0Y0G2H5EfFVGKivVecEQbb+INAek1aa6c89evg2/OvetQYsJ+51QknskwqvLsA==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-16.5.1.tgz", + "integrity": "sha512-x7MsSG0W+X43WVv7JhiSq2eKvH2suNKdlUHEG09Yt0vm3z0bhtym1UCMUg3IUAK7jy9hhLeDaFVFkC6zo+H/XQ==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-arm64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-16.5.1.tgz", + "integrity": "sha512-J+/v/mFjOm74I0PNtH5Ka+fDd+/dWbKhpcZ2R1/6b9agzZk+Ff/SrwJcSYFXXWKbPX+uQ4RcJoytT06Zs3s0ow==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-x64-gnu": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-16.5.1.tgz", + "integrity": "sha512-igooWJ5YxQ94Zft7IqgL+Lw0qHaY15Btw4gfK756g/YTYLZEt4tTvR1y6RnK/wdpE3sa68bFTLVBNCGTyiTiDQ==", + "dev": true, + "optional": true + }, + "@nx/nx-linux-x64-musl": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-16.5.1.tgz", + "integrity": "sha512-zF/exnPqFYbrLAduGhTmZ7zNEyADid2bzNQiIjJkh8Y6NpDwrQIwVIyvIxqynsjMrIs51kBH+8TUjKjj2Jgf5A==", + "dev": true, + "optional": true + }, + "@nx/nx-win32-arm64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-16.5.1.tgz", + "integrity": "sha512-qtqiLS9Y9TYyAbbpq58kRoOroko4ZXg5oWVqIWFHoxc5bGPweQSJCROEqd1AOl2ZDC6BxfuVHfhDDop1kK05WA==", + "dev": true, + "optional": true + }, + "@nx/nx-win32-x64-msvc": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-16.5.1.tgz", + "integrity": "sha512-kUJBLakK7iyA9WfsGGQBVennA4jwf5XIgm0lu35oMOphtZIluvzItMt0EYBmylEROpmpEIhHq0P6J9FA+WH0Rg==", + "dev": true, + "optional": true + }, + "@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "dev": true, + "peer": true + }, + "@octokit/core": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.0.0.tgz", + "integrity": "sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==", + "dev": true, + "peer": true, + "requires": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.0.0", + "@octokit/request": "^8.0.2", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.0.tgz", + "integrity": "sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==", + "dev": true, + "peer": true, + "requires": { + "@octokit/types": "^11.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.0.1.tgz", + "integrity": "sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==", + "dev": true, + "peer": true, + "requires": { + "@octokit/request": "^8.0.1", + "@octokit/types": "^11.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==", + "dev": true, + "peer": true + }, + "@octokit/plugin-paginate-rest": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-8.0.0.tgz", + "integrity": "sha512-2xZ+baZWUg+qudVXnnvXz7qfrTmDeYPCzangBVq/1gXxii/OiS//4shJp9dnCCvj1x+JAm9ji1Egwm1BA47lPQ==", + "dev": true, + "peer": true, + "requires": { + "@octokit/types": "^11.0.0" + } + }, + "@octokit/plugin-retry": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-6.0.0.tgz", + "integrity": "sha512-a1/A4A+PB1QoAHQfLJxGHhLfSAT03bR1jJz3GgQJZvty2ozawFWs93MiBQXO7SL2YbO7CIq0Goj4qLOBj8JeMQ==", + "dev": true, + "peer": true, + "requires": { + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.0.0", + "bottleneck": "^2.15.3" + } + }, + "@octokit/plugin-throttling": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-7.0.0.tgz", + "integrity": "sha512-KL2k/d0uANc8XqP5S64YcNFCudR3F5AaKO39XWdUtlJIjT9Ni79ekWJ6Kj5xvAw87udkOMEPcVf9xEge2+ahew==", + "dev": true, + "peer": true, + "requires": { + "@octokit/types": "^11.0.0", + "bottleneck": "^2.15.3" + } + }, + "@octokit/request": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.1.1.tgz", + "integrity": "sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==", + "dev": true, + "peer": true, + "requires": { + "@octokit/endpoint": "^9.0.0", + "@octokit/request-error": "^5.0.0", + "@octokit/types": "^11.1.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.0.0.tgz", + "integrity": "sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==", + "dev": true, + "peer": true, + "requires": { + "@octokit/types": "^11.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/types": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-11.1.0.tgz", + "integrity": "sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==", + "dev": true, + "peer": true, + "requires": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "@parcel/watcher": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.0.4.tgz", + "integrity": "sha512-cTDi+FUDBIUOBKEtj+nhiJ71AZVlkAsQFuGQTun5tV9mwQBQgZvhCzG+URPQc8myeN32yRVZEfVAPCs1RW+Jvg==", + "dev": true, + "requires": { + "node-addon-api": "^3.2.1", + "node-gyp-build": "^4.3.0" + } + }, + "@peculiar/asn1-cms": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.3.6.tgz", + "integrity": "sha512-Kr0XsyjuElTc4NijuPYyd6YkTlbz0KCuoWnNkfPFhXjHTzbUIh/s15ixjxLj8XDrXsI1aPQp3D64uHbrs3Kuyg==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-csr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.3.6.tgz", + "integrity": "sha512-gCTEB/PvUxapmxo4SzGZT1JtEdevRnphRGZZmc9oJE7+pLuj2Px0Q6x+w8VvObfozA3pyPRTq+Wkocnu64+oLw==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-ecc": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.6.tgz", + "integrity": "sha512-Hu1xzMJQWv8/GvzOiinaE6XiD1/kEhq2C/V89UEoWeZ2fLUcGNIvMxOr/pMyL0OmpRWj/mhCTXOZp4PP+a0aTg==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pfx": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.3.6.tgz", + "integrity": "sha512-bScrrpQ59mppcoZLkDEW/Wruu+daSWQxpR2vqGjg69+v7VoQ1Le/Elm10ObfNShV2eNNridNQcOQvsHMLvUOCg==", + "requires": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-rsa": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pkcs8": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.3.6.tgz", + "integrity": "sha512-poqgdjsHNiyR0gnxP8l5VjRInSgpQvOM3zLULF/ZQW67uUsEiuPfplvaNJUlNqNOCd2szGo9jKW9+JmVVpWojA==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-pkcs9": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.3.6.tgz", + "integrity": "sha512-uaxSBF60glccuu5BEZvoPsaJzebVYcQRjXx2wXsGe7Grz/BXtq5RQAJ/3i9fEXawFK/zIbvbXBBpy07cnvrqhA==", + "requires": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-pfx": "^2.3.6", + "@peculiar/asn1-pkcs8": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "@peculiar/asn1-x509-attr": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-rsa": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.6.tgz", + "integrity": "sha512-DswjJyAXZnvESuImGNTvbNKvh1XApBVqU+r3UmrFFTAI23gv62byl0f5OFKWTNhCf66WQrd3sklpsCZc/4+jwA==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-schema": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", + "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "requires": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-x509": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.6.tgz", + "integrity": "sha512-dRwX31R1lcbIdzbztiMvLNTDoGptxdV7HocNx87LfKU0fEWh7fTWJjx4oV+glETSy6heF/hJHB2J4RGB3vVSYg==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "asn1js": "^3.0.5", + "ipaddr.js": "^2.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "@peculiar/asn1-x509-attr": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.3.6.tgz", + "integrity": "sha512-x5Kax8xp3fz+JSc+4Sq0/SUXIdbJeOePibYqvjHMGkP6AoeCOVcP+gg7rZRRGkTlDSyQnAoUTgTEsfAfFEd1/g==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "asn1js": "^3.0.5", + "tslib": "^2.4.0" + } + }, + "@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@peculiar/webcrypto": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", + "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.5.0", + "webcrypto-core": "^1.7.7" + } + }, + "@peculiar/x509": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.9.4.tgz", + "integrity": "sha512-Gcic9DV965oR2qr1uoir+mM6RQnxKQZpkz1bD4kiYSZtMBF2qWVfsCOA6748+87L85xoRrQrb58/vULG1/8vXg==", + "requires": { + "@peculiar/asn1-cms": "^2.3.6", + "@peculiar/asn1-csr": "^2.3.6", + "@peculiar/asn1-ecc": "^2.3.6", + "@peculiar/asn1-pkcs9": "^2.3.6", + "@peculiar/asn1-rsa": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-x509": "^2.3.6", + "pvtsutils": "^1.3.3", + "reflect-metadata": "^0.1.13", + "tslib": "^2.6.1", + "tsyringe": "^4.8.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "dev": true, + "peer": true + }, + "@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "4.2.10" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "peer": true + } + } + }, + "@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "dev": true, + "peer": true, + "requires": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + } + }, + "@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==" + }, + "@rollup/plugin-json": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.0.0.tgz", + "integrity": "sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1" + } + }, + "@rollup/plugin-node-resolve": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz", + "integrity": "sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-builtin-module": "^3.2.1", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + } + }, + "@rollup/pluginutils": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.3.tgz", + "integrity": "sha512-hfllNN4a80rwNQ9QCxhxuHCGHMAvabXqxNdaChUSSadMre7t4iEUI6fFAhBOn/eIYTgYVhBv7vCLsAJ4u3lf3g==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^2.3.1" + } + }, + "@schematics/angular": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.0.tgz", + "integrity": "sha512-Ib0/ZCkjWt7a5p3209JVwEWwf41v03K3ylvlxLIEo1ZGijAZAlrBj4GrA5YQ+TmPm2hRyt+owss7x91/x+i0Gw==", + "dev": true, + "requires": { + "@angular-devkit/core": "16.2.0", + "@angular-devkit/schematics": "16.2.0", + "jsonc-parser": "3.2.0" + } + }, + "@semantic-release/commit-analyzer": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/commit-analyzer/-/commit-analyzer-10.0.1.tgz", + "integrity": "sha512-9ejHzTAijYs9z246sY/dKBatmOPcd0GQ7lH4MgLCkv1q4GCiDZRkjHJkaQZXZVaK7mJybS+sH3Ng6G8i3pYMGQ==", + "dev": true, + "peer": true, + "requires": { + "conventional-changelog-angular": "^6.0.0", + "conventional-commits-filter": "^3.0.0", + "conventional-commits-parser": "^4.0.0", + "debug": "^4.0.0", + "import-from": "^4.0.0", + "lodash-es": "^4.17.21", + "micromatch": "^4.0.2" + } + }, + "@semantic-release/error": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-3.0.0.tgz", + "integrity": "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==", + "dev": true + }, + "@semantic-release/git": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@semantic-release/git/-/git-10.0.1.tgz", + "integrity": "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==", + "dev": true, + "requires": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + } + }, + "@semantic-release/github": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-9.0.4.tgz", + "integrity": "sha512-kQCGFAsBErvCR6hzNuzu63cj4erQN2krm9zQlg8vl4j5X0mL0d/Ras0wmL5Gkr1TuSS2lweME7M4J5zvtDDDSA==", + "dev": true, + "peer": true, + "requires": { + "@octokit/core": "^5.0.0", + "@octokit/plugin-paginate-rest": "^8.0.0", + "@octokit/plugin-retry": "^6.0.0", + "@octokit/plugin-throttling": "^7.0.0", + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^4.0.1", + "debug": "^4.3.4", + "dir-glob": "^3.0.1", + "globby": "^13.1.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "issue-parser": "^6.0.0", + "lodash-es": "^4.17.21", + "mime": "^3.0.0", + "p-filter": "^3.0.0", + "url-join": "^5.0.0" + }, + "dependencies": { + "@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "peer": true + }, + "agent-base": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", + "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "dev": true, + "peer": true, + "requires": { + "debug": "^4.3.4" + } + }, + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "peer": true, + "requires": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "http-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", + "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "dev": true, + "peer": true, + "requires": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + } + }, + "https-proxy-agent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.1.tgz", + "integrity": "sha512-Eun8zV0kcYS1g19r78osiQLEFIRspRUDd9tIfBCTBPBeMieF/EsJNL8VI3xOIdYRDEkjQnqOYPsZ2DsWsVsFwQ==", + "dev": true, + "peer": true, + "requires": { + "agent-base": "^7.0.2", + "debug": "4" + } + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true + }, + "mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "peer": true + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true, + "peer": true + }, + "url-join": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", + "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "dev": true, + "peer": true + } + } + }, + "@semantic-release/gitlab": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/@semantic-release/gitlab/-/gitlab-12.0.5.tgz", + "integrity": "sha512-7iLeD5J0BF34jBUKTYbJT+Z+J9j55PXeR78wKWq9Lqbc8Y566D0g8BNVl9HUVSv6eipELdkqS+zMyTDGqiUL1w==", + "dev": true, + "requires": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^4.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "escape-string-regexp": "^5.0.0", + "form-data": "^4.0.0", + "fs-extra": "^11.0.0", + "globby": "^11.0.0", + "got": "^13.0.0", + "hpagent": "^1.0.0", + "lodash-es": "^4.17.21", + "parse-url": "^8.0.0", + "url-join": "^4.0.0" + }, + "dependencies": { + "@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true + }, + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true + } + } + }, + "@semantic-release/npm": { + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/npm/-/npm-10.0.4.tgz", + "integrity": "sha512-6R3timIQ7VoL2QWRkc9DG8v74RQtRp7UOe/2KbNaqwJ815qOibAv65bH3RtTEhs4axEaHoZf7HDgFs5opaZ9Jw==", + "dev": true, + "peer": true, + "requires": { + "@semantic-release/error": "^4.0.0", + "aggregate-error": "^4.0.1", + "execa": "^7.0.0", + "fs-extra": "^11.0.0", + "lodash-es": "^4.17.21", + "nerf-dart": "^1.0.0", + "normalize-url": "^8.0.0", + "npm": "^9.5.0", + "rc": "^1.2.8", + "read-pkg": "^8.0.0", + "registry-auth-token": "^5.0.0", + "semver": "^7.1.2", + "tempy": "^3.0.0" + }, + "dependencies": { + "@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "peer": true + }, + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "peer": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "peer": true + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "peer": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "peer": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "peer": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "peer": true + } + } + }, + "@semantic-release/release-notes-generator": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-11.0.4.tgz", + "integrity": "sha512-j0Znnwq9IdWTCGzqSlkLv4MpALTsVDZxcVESzJCNN8pK2BYQlYaKsdZ1Ea/+7RlppI3vjhEi33ZKmjSGY1FLKw==", + "dev": true, + "peer": true, + "requires": { + "conventional-changelog-angular": "^6.0.0", + "conventional-changelog-writer": "^6.0.0", + "conventional-commits-filter": "^3.0.0", + "conventional-commits-parser": "^4.0.0", + "debug": "^4.0.0", + "get-stream": "^7.0.0", + "import-from": "^4.0.0", + "into-stream": "^7.0.0", + "lodash-es": "^4.17.21", + "read-pkg-up": "^10.0.0" + }, + "dependencies": { + "get-stream": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-7.0.1.tgz", + "integrity": "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==", + "dev": true, + "peer": true + } + } + }, + "@sigstore/bundle": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", + "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", + "dev": true, + "requires": { + "@sigstore/protobuf-specs": "^0.2.0" + } + }, + "@sigstore/protobuf-specs": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", + "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", + "dev": true + }, + "@sigstore/sign": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", + "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", + "dev": true, + "requires": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "make-fetch-happen": "^11.0.1" + } + }, + "@sigstore/tuf": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", + "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", + "dev": true, + "requires": { + "@sigstore/protobuf-specs": "^0.2.0", + "tuf-js": "^1.1.7" + } + }, + "@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "dev": true + }, + "@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^3.0.0" + } + }, + "@socket.io/component-emitter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", + "dev": true + }, + "@ster5/global-mutex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@ster5/global-mutex/-/global-mutex-2.0.0.tgz", + "integrity": "sha512-nlp5BM4E7ybkGt6ouZsohSnliWtXgRoUWHMl8uzi64gKwZSONsssEstfBGnQ0OpdQlE0HBP0qq9RDxP0JTW57w==", + "requires": { + "@types/proper-lockfile": "^4.1.2", + "proper-lockfile": "^4.1.2" + } + }, + "@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "requires": { + "defer-to-connect": "^2.0.1" + } + }, + "@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==" + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true + }, + "@tsoa/cli": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@tsoa/cli/-/cli-5.1.1.tgz", + "integrity": "sha512-krvp6Qr2yPUfj6bJRs0vwQhLANeINzyusNnzgSoerDfBBBnjZ+VhvR4rWguAcLc1kgP/kFAJz5kIp4iqLFmILQ==", + "requires": { + "@tsoa/runtime": "^5.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.1.0", + "glob": "^8.0.3", + "handlebars": "^4.7.7", + "merge": "^2.1.1", + "minimatch": "^5.1.0", + "typescript": "^4.9.5", + "validator": "^13.7.0", + "yamljs": "^0.3.0", + "yargs": "^17.5.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" + } + } + }, + "@tsoa/runtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@tsoa/runtime/-/runtime-5.0.0.tgz", + "integrity": "sha512-DY0x7ZhNRF9FcwCZXQQbQhVj3bfZe0LScNyqp0c8PhDTj0gRMjY4ESVpihopRzhQtamReJoDRg3FhEu4BlSVtA==", + "requires": { + "@types/multer": "^1.4.7", + "promise.any": "^2.0.5", + "reflect-metadata": "^0.1.13", + "validator": "^13.7.0" + } + }, + "@tufjs/canonical-json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", + "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", + "dev": true + }, + "@tufjs/models": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", + "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", + "dev": true, + "requires": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@types/async": { + "version": "3.2.20", + "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.20.tgz", + "integrity": "sha512-6jSBQQugzyX1aWto0CbvOnmxrU9tMoXfA9gc4IrLEtvr3dTwSg5GLGoWiZnGLI6UG/kqpB3JOQKQrqnhUWGKQA==" + }, + "@types/babel__core": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", + "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", + "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/bcryptjs": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/bcryptjs/-/bcryptjs-2.4.2.tgz", + "integrity": "sha512-LiMQ6EOPob/4yUL66SZzu6Yh77cbzJFYll+ZfaPiPPFswtIlA/Fs1MzdKYA7JApHU49zQTbJGX3PDmCpIdDBRQ==", + "dev": true + }, + "@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "@types/bonjour": { + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.10.tgz", + "integrity": "sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/bootstrap": { + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.6.tgz", + "integrity": "sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==", + "dev": true, + "requires": { + "@popperjs/core": "^2.9.2" + } + }, + "@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "dev": true + }, + "@types/cookiejar": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/cookiejar/-/cookiejar-2.1.2.tgz", + "integrity": "sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog==", + "dev": true + }, + "@types/cors": { + "version": "2.8.13", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", + "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/dns-packet": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@types/dns-packet/-/dns-packet-5.2.4.tgz", + "integrity": "sha512-OAruArypdNxR/tzbmrtoyEuXeNTLaZCpO19BXaNC10T5ACIbvjmvhmV2RDEy2eLc3w8IjK7SY3cvUCcAW+sfoQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/eslint": { + "version": "8.44.2", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", + "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "dev": true, + "requires": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "@types/eslint-scope": { + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", + "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "dev": true, + "requires": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, + "@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "requires": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "@types/graceful-fs": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/http-cache-semantics": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", + "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", + "dev": true + }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, + "@types/http-proxy": { + "version": "1.17.11", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.11.tgz", + "integrity": "sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", + "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/jasmine": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-4.3.5.tgz", + "integrity": "sha512-9YHUdvuNDDRJYXZwHqSsO72Ok0vmqoJbNn73ttyITQp/VA60SarnZ+MPLD37rJAhVoKp+9BWOvJP5tHIRfZylQ==", + "dev": true + }, + "@types/jquery": { + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.16.tgz", + "integrity": "sha512-bsI7y4ZgeMkmpG9OM710RRzDFp+w4P1RGiIt30C1mSBT+ExCleeh4HObwgArnDFELmRrOpXgSYN9VF1hj+f1lw==", + "dev": true, + "requires": { + "@types/sizzle": "*" + } + }, + "@types/json-schema": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "dev": true + }, + "@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/jsrsasign": { + "version": "10.5.8", + "resolved": "https://registry.npmjs.org/@types/jsrsasign/-/jsrsasign-10.5.8.tgz", + "integrity": "sha512-1oZ3TbarAhKtKUpyrCIqXpbx3ZAfoSulleJs6/UzzyYty0ut+kjRX7zHLAaHwVIuw8CBjIymwW4J2LK944HoHQ==" + }, + "@types/lodash": { + "version": "4.14.197", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", + "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==" + }, + "@types/lodash-es": { + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.8.tgz", + "integrity": "sha512-euY3XQcZmIzSy7YH5+Unb3b2X12Wtk54YWINBvvGQ5SmMvwb11JQskGsfkH/5HXK77Kr8GF0wkVDIxzAisWtog==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, + "@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true, + "peer": true + }, + "@types/mkdirp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.2.tgz", + "integrity": "sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/morgan": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.4.tgz", + "integrity": "sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/multer": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.7.tgz", + "integrity": "sha512-/SNsDidUFCvqqcWDwxv2feww/yqhNeTRL5CVoL3jU4Goc4kKEL10T7Eye65ZqPNi4HRx8sAEX59pV1aEH7drNA==", + "requires": { + "@types/express": "*" + } + }, + "@types/multicast-dns": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@types/multicast-dns/-/multicast-dns-7.2.1.tgz", + "integrity": "sha512-A2PmB8MRcNVEkw6wzGT5rtBHqyHOVjiRMkJH+zpJKXipSi+GGkHg6JjNFApDiYK9WefJqkVG0taln1VMl4TGfw==", + "requires": { + "@types/dns-packet": "*", + "@types/node": "*" + } + }, + "@types/node": { + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", + "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==" + }, + "@types/nodemailer": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.9.tgz", + "integrity": "sha512-XYG8Gv+sHjaOtUpiuytahMy2mM3rectgroNbs6R3djZEKmPNiIJwe9KqOJBGzKKnNZNKvnuvmugBgpq3w/S0ig==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true, + "peer": true + }, + "@types/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-kd4LMvcnpYkspDcp7rmXKedn8iJSCoa331zRRamUp5oanKt/CefbEGPQP7G89enz7sKD4bvsr8mHSsC8j5WOvA==", + "requires": { + "@types/retry": "*" + } + }, + "@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + }, + "@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + }, + "@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true + }, + "@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==" + }, + "@types/semver": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==" + }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "@types/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==", + "dev": true, + "requires": { + "@types/express": "*" + } + }, + "@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "requires": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "@types/sizzle": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz", + "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==", + "dev": true + }, + "@types/sockjs": { + "version": "0.3.33", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", + "integrity": "sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/stack-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", + "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", + "dev": true + }, + "@types/superagent": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", + "dev": true, + "requires": { + "@types/cookiejar": "*", + "@types/node": "*" + } + }, + "@types/supertest": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/supertest/-/supertest-2.0.12.tgz", + "integrity": "sha512-X3HPWTwXRerBZS7Mo1k6vMVR1Z6zmJcDVn5O/31whe0tnjE4te6ZJSJGq1RiqHPjzPdMTfjCFogDJmwng9xHaQ==", + "dev": true, + "requires": { + "@types/superagent": "*" + } + }, + "@types/swagger-ui-express": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz", + "integrity": "sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "@types/triple-beam": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.2.tgz", + "integrity": "sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g==" + }, + "@types/uuid": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", + "dev": true + }, + "@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/yargs": { + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.0.tgz", + "integrity": "sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.4.0", + "@typescript-eslint/type-utils": "6.4.0", + "@typescript-eslint/utils": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "dependencies": { + "@typescript-eslint/type-utils": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.0.tgz", + "integrity": "sha512-TvqrUFFyGY0cX3WgDHcdl2/mMCWCDv/0thTtx/ODMY1QhEiyFtv/OlLaNIiYLwRpAxAtOLOY9SUf1H3Q3dlwAg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "6.4.0", + "@typescript-eslint/utils": "6.4.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.0.tgz", + "integrity": "sha512-BvvwryBQpECPGo8PwF/y/q+yacg8Hn/2XS+DqL/oRsOPK+RPt29h5Ui5dqOKHDlbXrAeHUTnyG3wZA0KTDxRZw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.4.0", + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/typescript-estree": "6.4.0", + "semver": "^7.5.4" + } + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.62.0" + } + }, + "@typescript-eslint/parser": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.0.tgz", + "integrity": "sha512-I1Ah1irl033uxjxO9Xql7+biL3YD7w9IU8zF+xlzD/YxY6a4b7DYA08PXUUCbm2sEljwJF6ERFy2kTGAGcNilg==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "6.4.0", + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/typescript-estree": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.0.tgz", + "integrity": "sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "dependencies": { + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + } + } + }, + "@typescript-eslint/types": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.0.tgz", + "integrity": "sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.0.tgz", + "integrity": "sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.4.0", + "@typescript-eslint/visitor-keys": "6.4.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.0.tgz", + "integrity": "sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "6.4.0", + "eslint-visitor-keys": "^3.4.1" + } + }, + "@vitejs/plugin-basic-ssl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.0.1.tgz", + "integrity": "sha512-pcub+YbFtFhaGRTo1832FQHQSHvMrlb43974e2eS8EKleR3p1cDdkJFPci1UhwkEf1J9Bz+wKBSzqpKp7nNj2A==", + "dev": true, + "requires": {} + }, + "@webassemblyjs/ast": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", + "dev": true, + "requires": { + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", + "dev": true + }, + "@webassemblyjs/helper-numbers": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", + "dev": true, + "requires": { + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.11.6", + "@xtuc/long": "4.2.2" + } + }, + "@wessberg/ts-evaluator": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/@wessberg/ts-evaluator/-/ts-evaluator-0.0.27.tgz", + "integrity": "sha512-7gOpVm3yYojUp/Yn7F4ZybJRxyqfMNf0LXK5KJiawbPfL0XTsJV+0mgrEDjOIR6Bi0OYk2Cyg4tjFu1r8MCZaA==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "jsdom": "^16.4.0", + "object-path": "^0.11.5", + "tslib": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "@yarnpkg/parsers": { + "version": "3.0.0-rc.46", + "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", + "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", + "dev": true, + "requires": { + "js-yaml": "^3.10.0", + "tslib": "^2.4.0" + } + }, + "@zkochan/js-yaml": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@zkochan/js-yaml/-/js-yaml-0.0.6.tgz", + "integrity": "sha512-nzvgl3VfhcELQ8LyVrYOru+UtAy1nrygk2+AGbTm8a5YcO6o8lSjAT+pfg3vJWxIoZKOUhrK6UU7xW/+00kQrg==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + } + } + }, + "aas-lib": { + "version": "file:projects/aas-lib", + "requires": {} + }, + "aas-portal": { + "version": "file:projects/aas-portal", + "requires": { + "@angular-devkit/build-angular": "^16.1.8", + "@angular-eslint/builder": "16.1.0", + "@angular-eslint/eslint-plugin": "16.1.0", + "@angular-eslint/eslint-plugin-template": "16.1.0", + "@angular-eslint/schematics": "16.1.0", + "@angular-eslint/template-parser": "16.1.0", + "@angular/animations": "^16.1.8", + "@angular/cli": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/compiler-cli": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/eslint-plugin": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@types/bootstrap": "^5.2.6", + "@types/jasmine": "^4.3.5", + "@types/jquery": "^3.5.16", + "@types/lodash-es": "^4.17.8", + "@types/uuid": "^8.3.4", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "eslint": "^8.46.0", + "jasmine-core": "^5.1.0", + "jest": "^29.6.2", + "jwt-decode": "^3.1.2", + "karma": "^6.4.2", + "karma-chrome-launcher": "^3.2.0", + "karma-coverage": "^2.2.1", + "karma-jasmine": "^5.1.0", + "karma-jasmine-html-reporter": "^2.1.0", + "karma-junit-reporter": "^2.0.1", + "lodash-es": "^4.17.21", + "ng-packagr": "^16.1.0", + "rimraf": "^5.0.1", + "rxjs": "~7.8.1", + "ts-node": "^10.9.1", + "tslib": "^2.6.1", + "typescript": "5.0.*", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + } + }, + "aas-server": { + "version": "file:projects/aas-server", + "requires": { + "@jest/globals": "^29.6.2", + "@types/bcryptjs": "^2.4.2", + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/jquery": "^3.5.16", + "@types/jsonwebtoken": "^9.0.2", + "@types/lodash-es": "^4.17.8", + "@types/morgan": "^1.9.4", + "@types/multer": "^1.4.7", + "@types/node": "^18.16.0", + "@types/nodemailer": "^6.4.9", + "@types/supertest": "^2.0.12", + "@types/swagger-ui-express": "^4.1.3", + "@types/ws": "^8.5.5", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "@xmldom/xmldom": "^0.8.10", + "babel-plugin-transform-import-meta": "^2.2.1", + "bcryptjs": "^2.4.3", + "common": "2.0.0", + "cors": "^2.8.5", + "esbuild": "^0.18.19", + "eslint": "^8.46.0", + "express": "^4.18.2", + "form-data": "^4.0.0", + "jest": "^29.6.2", + "jimp": "^0.22.10", + "jsonwebtoken": "^9.0.1", + "jszip": "^3.10.1", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "mongoose": "^7.4.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "ng-packagr": "^16.1.0", + "node-opcua": "^2.108.0", + "node-opcua-client-crawler": "^2.108.0", + "nodemailer": "^6.9.4", + "owncloud-sdk": "^3.1.0-alpha.7", + "reflect-metadata": "^0.1.13", + "rimraf": "^5.0.1", + "rxjs": "~7.8.1", + "supertest": "^6.3.3", + "swagger-ui-express": "^5.0.0", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "tslib": "^2.6.1", + "tsoa": "^5.1.1", + "tsyringe": "^4.8.0", + "typescript": "5.0.*", + "winston": "^3.10.0", + "winston-daily-rotate-file": "^4.7.1", + "ws": "^8.13.0", + "xpath": "^0.0.33" + }, + "dependencies": { + "@types/node": { + "version": "18.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz", + "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==", + "dev": true + } + } + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "acorn": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "dev": true + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "dev": true, + "requires": {} + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "adjust-sourcemap-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz", + "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==", + "dev": true, + "requires": { + "loader-utils": "^2.0.0", + "regex-parser": "^2.2.11" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + } + } + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "dev": true, + "requires": { + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "requires": { + "ajv": "^8.0.0" + } + }, + "ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansicolors": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", + "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==", + "dev": true, + "peer": true + }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "argv-formatter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz", + "integrity": "sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==", + "dev": true, + "peer": true + }, + "aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "requires": { + "dequal": "^2.0.3" + } + }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "peer": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array.prototype.map": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", + "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + } + }, + "arraybuffer.prototype.slice": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", + "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "peer": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, + "asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "requires": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + } + }, + "assert": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.0.0.tgz", + "integrity": "sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A==", + "requires": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "autoprefixer": { + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", + "dev": true, + "requires": { + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "peer": true, + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "requires": { + "deep-equal": "^2.0.5" + } + }, + "babel-jest": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz", + "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==", + "dev": true, + "requires": { + "@jest/transform": "^29.6.2", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.5.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "dev": true, + "requires": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + } + }, + "babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.5.tgz", + "integrity": "sha512-19hwUH5FKl49JEsvyTcoHakh6BE0wgXLLptIyKZ3PijHc/Ci521wygORCUCCred+E/twuqRyAkE02BAWPmsHOg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.4.2", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.3.tgz", + "integrity": "sha512-z41XaniZL26WLrvjy7soabMXrfPWARN25PZoriDEiLMxAp50AUW3t35BGQUMg5xK3UrpVTtagIDklxYa+MhiNA==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.2", + "core-js-compat": "^3.31.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.2.tgz", + "integrity": "sha512-tAlOptU0Xj34V1Y2PNTL4Y0FOJMDB6bZmoW39FeCQIhigGLkqu3Fj6uiXpxIf6Ij274ENdYx64y6Au+ZKlb1IA==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.4.2" + } + }, + "babel-plugin-transform-import-meta": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-import-meta/-/babel-plugin-transform-import-meta-2.2.1.tgz", + "integrity": "sha512-AxNh27Pcg8Kt112RGa3Vod2QS2YXKKJ6+nSvRtv7qQTJAdx0MZa4UHZ4lnxHUWA2MNbLuZQv5FVab4P1CoLOWw==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "tslib": "^2.4.0" + } + }, + "babel-preset-current-node-syntax": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", + "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.8.3" + } + }, + "babel-preset-jest": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^29.5.0", + "babel-preset-current-node-syntax": "^1.0.0" + } + }, + "backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==", + "requires": { + "precond": "0.2" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", + "peer": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "dev": true + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==" + }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "dev": true, + "peer": true + }, + "better-assert": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", + "integrity": "sha512-bYeph2DFlpK1XmGs6fvlLRUN29QISM3GBuUwSFsMY2XRx4AvC0WNCS57j4c/xGrK2RS24C1w3YoBOsw9fT46tQ==", + "requires": { + "callsite": "1.0.0" + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==" + }, + "body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "bonjour-service": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.1.1.tgz", + "integrity": "sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==", + "dev": true, + "requires": { + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + } + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, + "bootstrap": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.1.tgz", + "integrity": "sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g==", + "requires": {} + }, + "bootstrap-icons": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.10.5.tgz", + "integrity": "sha512-oSX26F37V7QV7NCE53PPEL45d7EGXmBgHG3pDpZvcRaKVzWMqIRL9wcqJUyEha1esFtM3NJzvmxFXDxjJYD0jQ==" + }, + "bottleneck": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", + "dev": true, + "peer": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browserslist": { + "version": "4.21.10", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.10.tgz", + "integrity": "sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==", + "requires": { + "caniuse-lite": "^1.0.30001517", + "electron-to-chromium": "^1.4.477", + "node-releases": "^2.0.13", + "update-browserslist-db": "^1.0.11" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "requires": { + "node-int64": "^0.4.0" + } + }, + "bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==" + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==" + }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, + "builtins": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz", + "integrity": "sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==", + "dev": true, + "requires": { + "semver": "^7.0.0" + } + }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "requires": { + "streamsearch": "^1.1.0" + } + }, + "byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==" + }, + "byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz", + "integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==", + "peer": true + }, + "bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" + }, + "cacache": { + "version": "17.1.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", + "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", + "dev": true, + "requires": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^7.0.3", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "dev": true + }, + "cacheable-request": { + "version": "10.2.13", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.13.tgz", + "integrity": "sha512-3SD4rrMu1msNGEtNSt8Od6enwdo//U9s4ykmXfA2TD58kcLkCobtCDiby7kNyj7a/Q7lz/mAesAFI54rTdnvBA==", + "dev": true, + "requires": { + "@types/http-cache-semantics": "^4.0.1", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsite": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", + "integrity": "sha512-0vdNRFXn5q+dtOqjfFtmtlI9N2eVZ7LMyEV2iKC5mEEFvSg/69Ml6b/WU2qF8W1nLRa0wiSrDT3Y5jOHZCwKPQ==" + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "peer": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "dependencies": { + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "peer": true + } + } + }, + "caniuse-lite": { + "version": "1.0.30001521", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001521.tgz", + "integrity": "sha512-fnx1grfpEOvDGH+V17eccmNjucGUnCbP6KL+l5KqBIerp26WK/+RQ7CIDE37KGJjaPyqWXXlFUyKiWmvdNNKmQ==" + }, + "cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "dev": true, + "peer": true, + "requires": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } + } + }, + "char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "peer": true + }, + "chart.js": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz", + "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==", + "requires": { + "@kurkle/color": "^0.3.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "ci-info": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true + }, + "cjs-module-lexer": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "dev": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true + }, + "cli-table": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz", + "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==", + "requires": { + "colors": "1.0.3" + } + }, + "cli-table3": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", + "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "dev": true, + "peer": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true + }, + "clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "dependencies": { + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + } + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true + }, + "collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true + }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==" + }, + "colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "requires": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", + "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "dev": true + }, + "common": { + "version": "file:projects/common", + "requires": {} + }, + "common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, + "compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "peer": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dev": true, + "peer": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "peer": true + } + } + }, + "connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "requires": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true + } + } + }, + "connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, + "content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "requires": { + "safe-buffer": "5.2.1" + } + }, + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" + }, + "conventional-changelog-angular": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", + "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "dev": true, + "peer": true, + "requires": { + "compare-func": "^2.0.0" + } + }, + "conventional-changelog-writer": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-6.0.1.tgz", + "integrity": "sha512-359t9aHorPw+U+nHzUXHS5ZnPBOizRxfQsWT5ZDHBfvfxQOAik+yfuhKXG66CN5LEWPpMNnIMHUTCKeYNprvHQ==", + "dev": true, + "peer": true, + "requires": { + "conventional-commits-filter": "^3.0.0", + "dateformat": "^3.0.3", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "meow": "^8.1.2", + "semver": "^7.0.0", + "split": "^1.0.1" + } + }, + "conventional-commits-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-3.0.0.tgz", + "integrity": "sha512-1ymej8b5LouPx9Ox0Dw/qAO2dVdfpRFq28e5Y0jJEU8ZrLdy0vOSkkIInwmxErFGhg6SALro60ZrwYFVTUDo4Q==", + "dev": true, + "peer": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.1" + } + }, + "conventional-commits-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", + "dev": true, + "peer": true, + "requires": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" + } + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" + }, + "cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true + }, + "copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "requires": { + "is-what": "^3.14.1" + } + }, + "copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "dev": true, + "requires": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "dependencies": { + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "dev": true, + "requires": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + } + }, + "slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "dev": true + } + } + }, + "core-js-compat": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.0.tgz", + "integrity": "sha512-7a9a3D1k4UCVKnLhrgALyFcP7YCsLOQIxPd0dKjf/6GuPcgyiGP70ewWdCGrSK7evyhymi0qO4EqCmSJofDeYw==", + "dev": true, + "requires": { + "browserslist": "^4.21.9" + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, + "cosmiconfig": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", + "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "dev": true, + "requires": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "dependencies": { + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + } + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "critters": { + "version": "0.0.20", + "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.20.tgz", + "integrity": "sha512-CImNRorKOl5d8TWcnAz5n5izQ6HFsvz29k327/ELy6UFcmbiZNOsinaKvzv16WZR0P6etfSWYzE47C4/56B3Uw==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "css-select": "^5.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.2", + "htmlparser2": "^8.0.2", + "postcss": "^8.4.23", + "pretty-bytes": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "peer": true, + "requires": { + "node-fetch": "^2.6.12" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "peer": true + }, + "crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "dev": true, + "peer": true, + "requires": { + "type-fest": "^1.0.1" + }, + "dependencies": { + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "peer": true + } + } + }, + "css-loader": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", + "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.3", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + } + }, + "css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + } + }, + "css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssom": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", + "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "cuint": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==", + "dev": true + }, + "custom-event": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", + "integrity": "sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg==", + "dev": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "data-urls": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", + "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", + "dev": true, + "requires": { + "abab": "^2.0.3", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.0.0" + } + }, + "date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "peer": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "peer": true + }, + "decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "peer": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "peer": true + } + } + }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true + }, + "decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "requires": { + "mimic-response": "^3.1.0" + }, + "dependencies": { + "mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true + } + } + }, + "dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "requires": {} + }, + "deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "peer": true + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, + "default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, + "defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true + }, + "define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true + }, + "define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "dependency-graph": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", + "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", + "dev": true + }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "dev": true, + "peer": true + }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, + "dequeue": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/dequeue/-/dequeue-1.0.5.tgz", + "integrity": "sha512-2FIVJZTaWhUj0Y2uKmDAasTP6ZwFWRjkRc01MYN5jFm96iIzkYyNzGADfJ13C5W7CTN7XO9mBYDcVB68eNybBA==" + }, + "destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "di": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/di/-/di-0.0.1.tgz", + "integrity": "sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==" + }, + "dns-packet": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", + "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", + "requires": { + "@leichtgewicht/ip-codec": "^2.0.1" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dom-serialize": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/dom-serialize/-/dom-serialize-2.2.1.tgz", + "integrity": "sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ==", + "dev": true, + "requires": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + } + }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==" + }, + "domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true + }, + "domexception": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", + "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", + "dev": true, + "requires": { + "webidl-conversions": "^5.0.0" + }, + "dependencies": { + "webidl-conversions": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", + "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", + "dev": true + } + } + }, + "domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0" + } + }, + "domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "requires": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "peer": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotenv": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", + "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", + "dev": true + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", + "dev": true, + "peer": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "ejs": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.4.494", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.494.tgz", + "integrity": "sha512-KF7wtsFFDu4ws1ZsSOt4pdmO1yWVNWCFtijVYZPUeW4SV7/hy/AESjLn/+qIWgq7mHscNOKAwN5AIM1+YAy+Ww==" + }, + "emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "engine.io": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.2.tgz", + "integrity": "sha512-IXsMcGpw/xRfjra46sVZVHiSWo/nJ/3g1337q9KNXtS6YRzbW5yIzTCb9DjhrBe7r3GZQR0I4+nq+4ODk5g/cA==", + "dev": true, + "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.11.0" + }, + "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true + }, + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "requires": {} + } + } + }, + "engine.io-parser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.1.tgz", + "integrity": "sha512-9JktcM3u18nU9N2Lz3bWeBgxVgOKpw7yhRaoxQA3FUDZzzw+9WlA6p4G4u0RixNkg14fH7EfEc/RhpurtiROTQ==", + "dev": true + }, + "enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + } + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "ent": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ent/-/ent-2.2.0.tgz", + "integrity": "sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==", + "dev": true + }, + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true + }, + "env-ci": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-9.1.1.tgz", + "integrity": "sha512-Im2yEWeF4b2RAMAaWvGioXk6m0UNaIjD8hj28j2ij5ldnIFrDQT0+pzDvpbRkcjurhXhf/AsBKv8P2rtmGi9Aw==", + "dev": true, + "peer": true, + "requires": { + "execa": "^7.0.0", + "java-properties": "^1.0.2" + }, + "dependencies": { + "execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "peer": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "peer": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "peer": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "peer": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "peer": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "peer": true + } + } + }, + "env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "optional": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", + "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.1", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.1", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "safe-array-concat": "^1.0.0", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.10" + } + }, + "es-aggregate-error": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.9.tgz", + "integrity": "sha512-fvnX40sb538wdU6r4s35cq4EY6Lr09Upj40BEVem4LEsuW8XgQep9yD5Q1U2KftokNp1rWODFJ2qwZSsAjFpbg==", + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "function-bind": "^1.1.1", + "functions-have-names": "^1.2.3", + "get-intrinsic": "^1.1.3", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + } + }, + "es-module-lexer": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.3.0.tgz", + "integrity": "sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==", + "dev": true + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==" + }, + "esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "esbuild-wasm": { + "version": "0.18.17", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.18.17.tgz", + "integrity": "sha512-9OHGcuRzy+I8ziF9FzjfKLWAPbvi0e/metACVg9k6bK+SI4FFxeV6PcZsz8RIVaMD4YNehw+qj6UMR3+qj/EuQ==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true + }, + "escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "eslint": { + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", + "@humanwhocodes/config-array": "^0.11.10", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "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.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-etc": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-etc/-/eslint-etc-5.2.1.tgz", + "integrity": "sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "tsutils": "^3.17.1", + "tsutils-etc": "^1.4.1" + } + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + }, + "eventemitter-asyncresource": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz", + "integrity": "sha512-39F7TBIV0G7gTelxwbEqnwhp90eqCPON1k0NwNfwhgKn4Co4ybUbj2pECcXT0B3ztRKZ7Pw1JujUUgmQJHcVAQ==", + "dev": true + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true + }, + "expect": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.2.tgz", + "integrity": "sha512-iAErsLxJ8C+S02QbLAwgSGSezLQK+XXRDt8IuFXFpwCNw2ECmzZSmjKcCaFVp5VRMk+WAvz6h6jokzEzBFZEuA==", + "dev": true, + "requires": { + "@jest/expect-utils": "^29.6.2", + "@types/node": "*", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2" + } + }, + "exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "dev": true + }, + "express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "requires": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + } + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true + }, + "fast-xml-parser": { + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz", + "integrity": "sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==", + "peer": true, + "requires": { + "strnum": "^1.0.4" + } + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "requires": { + "reusify": "^1.0.4" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "requires": { + "bser": "2.1.1" + } + }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "requires": { + "pend": "~1.2.0" + } + }, + "fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + } + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-stream-rotator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/file-stream-rotator/-/file-stream-rotator-0.6.1.tgz", + "integrity": "sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==", + "requires": { + "moment": "^2.29.1" + } + }, + "file-type": { + "version": "16.5.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz", + "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==", + "requires": { + "readable-web-to-node-stream": "^3.0.0", + "strtok3": "^6.2.4", + "token-types": "^4.1.1" + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "dev": true, + "requires": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "find-versions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz", + "integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==", + "dev": true, + "peer": true, + "requires": { + "semver-regex": "^4.0.5" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, + "follow-redirects": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true + }, + "formidable": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.2.tgz", + "integrity": "sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==", + "dev": true, + "requires": { + "dezalgo": "^1.0.4", + "hexoid": "^1.0.0", + "once": "^1.4.0", + "qs": "^6.11.0" + } + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, + "fs-extra": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs-minipass": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", + "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", + "dev": true, + "requires": { + "minipass": "^7.0.3" + } + }, + "fs-monkey": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.4.tgz", + "integrity": "sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + } + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "requires": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, + "git-log-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", + "integrity": "sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==", + "dev": true, + "peer": true, + "requires": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "~0.6.6" + }, + "dependencies": { + "split2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-1.0.0.tgz", + "integrity": "sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==", + "dev": true, + "peer": true, + "requires": { + "through2": "~2.0.0" + } + } + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "requires": { + "define-properties": "^1.1.3" + } + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "got": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", + "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", + "dev": true, + "requires": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "guess-parser": { + "version": "0.4.22", + "resolved": "https://registry.npmjs.org/guess-parser/-/guess-parser-0.4.22.tgz", + "integrity": "sha512-KcUWZ5ACGaBM69SbqwVIuWGoSAgD+9iJnchR9j/IarVI1jHVeXv+bUXBIMeqVMSKt3zrn0Dgf9UpcOEpPBLbSg==", + "dev": true, + "requires": { + "@wessberg/ts-evaluator": "0.0.27" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "peer": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "hdr-histogram-js": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hdr-histogram-js/-/hdr-histogram-js-2.0.3.tgz", + "integrity": "sha512-Hkn78wwzWHNCp2uarhzQ2SGFLU3JY8SBDDd3TAABK4fc30wm+MuPOrg5QVFVfkKOQd6Bfz3ukJEI+q9sXEkK1g==", + "dev": true, + "requires": { + "@assemblyscript/loader": "^0.10.1", + "base64-js": "^1.2.0", + "pako": "^1.0.3" + } + }, + "hdr-histogram-percentiles-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz", + "integrity": "sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==", + "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "peer": true + }, + "hexoid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", + "integrity": "sha512-QFLV0taWQOZtvIRIAdBChesmogZrtuXvVWsFHZTk2SU+anspqZ2vMnoLg7IE1+Uk16N19APic1BuF8bC8c2m5g==", + "dev": true + }, + "hexy": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.3.5.tgz", + "integrity": "sha512-UCP7TIZPXz5kxYJnNOym+9xaenxCLor/JyhKieo8y8/bJWunGh9xbhy3YrgYJUQ87WwfXGm05X330DszOfINZw==" + }, + "hook-std": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz", + "integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==", + "dev": true, + "peer": true + }, + "hosted-git-info": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz", + "integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==", + "dev": true, + "requires": { + "lru-cache": "^7.5.1" + }, + "dependencies": { + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + } + } + }, + "hot-patcher": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-0.5.0.tgz", + "integrity": "sha512-2Uu2W0s8+dnqXzdlg0MRsRzPoDCs1wVjOGSyMRRaMzLDX4bgHw6xDYKccsWafXPPxQpkQfEjgW6+17pwcg60bw==", + "peer": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "dev": true + }, + "html-encoding-sniffer": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", + "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", + "dev": true, + "requires": { + "whatwg-encoding": "^1.0.5" + } + }, + "html-entities": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.4.0.tgz", + "integrity": "sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==", + "dev": true + }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "dev": true, + "requires": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true + }, + "http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "requires": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + } + }, + "http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + } + }, + "http-proxy-middleware": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz", + "integrity": "sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==", + "dev": true, + "requires": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true + } + } + }, + "http2-wrapper": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", + "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "dev": true, + "requires": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "humanize": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz", + "integrity": "sha512-bvZZ7vXpr1RKoImjuQ45hJb5OvE2oJafHysiD/AL3nkqTZH2hFCjQ3YZfCd63FefDitbJze/ispUPP0gfDsT2Q==" + }, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "ignore-walk": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.3.tgz", + "integrity": "sha512-C7FfFoTA+bI10qfeydT8aZbvr91vAEU+2W5BZUlzPec47oNb07SsOfwYrtxuvOYdUApPP/Qlh4DtAO51Ekk2QA==", + "dev": true, + "requires": { + "minimatch": "^9.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "requires": { + "@types/node": "16.9.1" + }, + "dependencies": { + "@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==" + } + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "optional": true + }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "immutable": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz", + "integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "import-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", + "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", + "dev": true, + "peer": true + }, + "import-local": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "dependencies": { + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true + }, + "injection-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/injection-js/-/injection-js-2.4.0.tgz", + "integrity": "sha512-6jiJt0tCAo9zjHbcwLiPL+IuNe9SQ6a9g0PEzafThW3fOQi0mrmiJGBJvDD6tmhPh8cQHIQtCOrJuBfQME4kPA==", + "dev": true, + "requires": { + "tslib": "^2.0.0" + } + }, + "inquirer": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.4.tgz", + "integrity": "sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "requires": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "into-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-7.0.0.tgz", + "integrity": "sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==", + "dev": true, + "peer": true, + "requires": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + } + }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "ipaddr.js": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.1.0.tgz", + "integrity": "sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==" + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "peer": true + }, + "is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "requires": { + "builtin-modules": "^3.3.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-core-module": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", + "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" + }, + "is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "peer": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "peer": true + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "dev": true, + "peer": true + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "peer": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "requires": { + "which-typed-array": "^1.1.11" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true + }, + "isomorphic-fetch": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", + "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", + "requires": { + "node-fetch": "^2.6.1", + "whatwg-fetch": "^3.4.1" + } + }, + "issue-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/issue-parser/-/issue-parser-6.0.0.tgz", + "integrity": "sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==", + "dev": true, + "peer": true, + "requires": { + "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": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==" + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, + "jackspeak": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.0.tgz", + "integrity": "sha512-uKmsITSsF4rUWQHzqaRUuyAir3fZfW3f202Ee34lz/gZCi970CPZwyQXLGNgWJvvZbvFyzeyGq0+4fcG/mBKZg==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "jake": { + "version": "10.8.7", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", + "integrity": "sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jasmine-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-5.1.0.tgz", + "integrity": "sha512-bFMMwpKuTZXCuGd51yClFobw5SOtad1kmdWnYO8dNwYV8i01Xj0C2+nyQpSKl1EKxiPfyd1ZgBl/rsusL3aS6w==", + "dev": true + }, + "java-properties": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", + "integrity": "sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==", + "dev": true, + "peer": true + }, + "jest": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.2.tgz", + "integrity": "sha512-8eQg2mqFbaP7CwfsTpCxQ+sHzw1WuNWL5UUvjnWP4hx2riGz9fPSzYOaU5q8/GqWn1TfgZIVTqYJygbGbWAANg==", + "dev": true, + "requires": { + "@jest/core": "^29.6.2", + "@jest/types": "^29.6.1", + "import-local": "^3.0.2", + "jest-cli": "^29.6.2" + } + }, + "jest-changed-files": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", + "dev": true, + "requires": { + "execa": "^5.0.0", + "p-limit": "^3.1.0" + } + }, + "jest-circus": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.2.tgz", + "integrity": "sha512-G9mN+KOYIUe2sB9kpJkO9Bk18J4dTDArNFPwoZ7WKHKel55eKIS/u2bLthxgojwlf9NLCVQfgzM/WsOVvoC6Fw==", + "dev": true, + "requires": { + "@jest/environment": "^29.6.2", + "@jest/expect": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.6.2", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "p-limit": "^3.1.0", + "pretty-format": "^29.6.2", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-cli": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.2.tgz", + "integrity": "sha512-TT6O247v6dCEX2UGHGyflMpxhnrL0DNqP2fRTKYm3nJJpCTfXX3GCMQPGFjXDoj0i5/Blp3jriKXFgdfmbYB6Q==", + "dev": true, + "requires": { + "@jest/core": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/types": "^29.6.1", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "import-local": "^3.0.2", + "jest-config": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "prompts": "^2.0.1", + "yargs": "^17.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-config": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.2.tgz", + "integrity": "sha512-VxwFOC8gkiJbuodG9CPtMRjBUNZEHxwfQXmIudSTzFWxaci3Qub1ddTRbFNQlD/zUeaifLndh/eDccFX4wCMQw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.6.2", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.2", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.6.2", + "jest-environment-node": "^29.6.2", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.6.2", + "jest-runner": "^29.6.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.6.2", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-diff": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.2.tgz", + "integrity": "sha512-t+ST7CB9GX5F2xKwhwCf0TAR17uNDiaPTZnVymP9lw0lssa9vG+AFyDZoeIHStU3WowFFwT+ky+er0WVl2yGhA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.6.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-docblock": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", + "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", + "dev": true, + "requires": { + "detect-newline": "^3.0.0" + } + }, + "jest-each": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.2.tgz", + "integrity": "sha512-MsrsqA0Ia99cIpABBc3izS1ZYoYfhIy0NNWqPSE0YXbQjwchyt6B1HD2khzyPe1WiJA7hbxXy77ZoUQxn8UlSw==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "chalk": "^4.0.0", + "jest-get-type": "^29.4.3", + "jest-util": "^29.6.2", + "pretty-format": "^29.6.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-environment-node": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.2.tgz", + "integrity": "sha512-YGdFeZ3T9a+/612c5mTQIllvWkddPbYcN2v95ZH24oWMbGA4GGS2XdIF92QMhUhvrjjuQWYgUGW2zawOyH63MQ==", + "dev": true, + "requires": { + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "jest-mock": "^29.6.2", + "jest-util": "^29.6.2" + } + }, + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + }, + "jest-haste-map": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz", + "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.3.2", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.6.2", + "jest-worker": "^29.6.2", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + } + }, + "jest-leak-detector": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.2.tgz", + "integrity": "sha512-aNqYhfp5uYEO3tdWMb2bfWv6f0b4I0LOxVRpnRLAeque2uqOVVMLh6khnTcE2qJ5wAKop0HcreM1btoysD6bPQ==", + "dev": true, + "requires": { + "jest-get-type": "^29.4.3", + "pretty-format": "^29.6.2" + } + }, + "jest-matcher-utils": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.2.tgz", + "integrity": "sha512-4LiAk3hSSobtomeIAzFTe+N8kL6z0JtF3n6I4fg29iIW7tt99R7ZcIFW34QkX+DuVrf+CUe6wuVOpm7ZKFJzZQ==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^29.6.2", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.6.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-message-util": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.2.tgz", + "integrity": "sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.1", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.6.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-mock": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.2.tgz", + "integrity": "sha512-hoSv3lb3byzdKfwqCuT6uTscan471GUECqgNYykg6ob0yiAw3zYc7OrPnI9Qv8Wwoa4lC7AZ9hyS4AiIx5U2zg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "@types/node": "*", + "jest-util": "^29.6.2" + } + }, + "jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "requires": {} + }, + "jest-regex-util": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", + "dev": true + }, + "jest-resolve": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.2.tgz", + "integrity": "sha512-G/iQUvZWI5e3SMFssc4ug4dH0aZiZpsDq9o1PtXTV1210Ztyb2+w+ZgQkB3iOiC5SmAEzJBOHWz6Hvrd+QnNPw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.6.2", + "jest-validate": "^29.6.2", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-resolve-dependencies": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.2.tgz", + "integrity": "sha512-LGqjDWxg2fuQQm7ypDxduLu/m4+4Lb4gczc13v51VMZbVP5tSBILqVx8qfWcsdP8f0G7aIqByIALDB0R93yL+w==", + "dev": true, + "requires": { + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.6.2" + } + }, + "jest-runner": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.2.tgz", + "integrity": "sha512-wXOT/a0EspYgfMiYHxwGLPCZfC0c38MivAlb2lMEAlwHINKemrttu1uSbcGbfDV31sFaPWnWJPmb2qXM8pqZ4w==", + "dev": true, + "requires": { + "@jest/console": "^29.6.2", + "@jest/environment": "^29.6.2", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.6.2", + "jest-haste-map": "^29.6.2", + "jest-leak-detector": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-resolve": "^29.6.2", + "jest-runtime": "^29.6.2", + "jest-util": "^29.6.2", + "jest-watcher": "^29.6.2", + "jest-worker": "^29.6.2", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-runtime": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.2.tgz", + "integrity": "sha512-2X9dqK768KufGJyIeLmIzToDmsN0m7Iek8QNxRSI/2+iPFYHF0jTwlO3ftn7gdKd98G/VQw9XJCk77rbTGZnJg==", + "dev": true, + "requires": { + "@jest/environment": "^29.6.2", + "@jest/fake-timers": "^29.6.2", + "@jest/globals": "^29.6.2", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-mock": "^29.6.2", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.6.2", + "jest-snapshot": "^29.6.2", + "jest-util": "^29.6.2", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-snapshot": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.2.tgz", + "integrity": "sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==", + "dev": true, + "requires": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.6.2", + "@jest/transform": "^29.6.2", + "@jest/types": "^29.6.1", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.6.2", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.6.2", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.6.2", + "jest-message-util": "^29.6.2", + "jest-util": "^29.6.2", + "natural-compare": "^1.4.0", + "pretty-format": "^29.6.2", + "semver": "^7.5.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-util": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz", + "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-validate": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.2.tgz", + "integrity": "sha512-vGz0yMN5fUFRRbpJDPwxMpgSXW1LDKROHfBopAvDcmD6s+B/s8WJrwi+4bfH4SdInBA5C3P3BI19dBtKzx1Arg==", + "dev": true, + "requires": { + "@jest/types": "^29.6.1", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.4.3", + "leven": "^3.1.0", + "pretty-format": "^29.6.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-watcher": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.2.tgz", + "integrity": "sha512-GZitlqkMkhkefjfN/p3SJjrDaxPflqxEAv3/ik10OirZqJGYH5rPiIsgVcfof0Tdqg3shQGdEIxDBx+B4tuLzA==", + "dev": true, + "requires": { + "@jest/test-result": "^29.6.2", + "@jest/types": "^29.6.1", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.6.2", + "string-length": "^4.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-worker": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz", + "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==", + "dev": true, + "requires": { + "@types/node": "*", + "jest-util": "^29.6.2", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jimp": { + "version": "0.22.10", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.22.10.tgz", + "integrity": "sha512-lCaHIJAgTOsplyJzC1w/laxSxrbSsEBw4byKwXgUdMmh+ayPsnidTblenQm+IvhIs44Gcuvlb6pd2LQ0wcKaKg==", + "requires": { + "@jimp/custom": "^0.22.10", + "@jimp/plugins": "^0.22.10", + "@jimp/types": "^0.22.10", + "regenerator-runtime": "^0.13.3" + } + }, + "jiti": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz", + "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==", + "dev": true + }, + "jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + }, + "jsdom": { + "version": "16.7.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", + "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", + "dev": true, + "requires": { + "abab": "^2.0.5", + "acorn": "^8.2.4", + "acorn-globals": "^6.0.0", + "cssom": "^0.4.4", + "cssstyle": "^2.3.0", + "data-urls": "^2.0.0", + "decimal.js": "^10.2.1", + "domexception": "^2.0.1", + "escodegen": "^2.0.0", + "form-data": "^3.0.0", + "html-encoding-sniffer": "^2.0.1", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "6.0.1", + "saxes": "^5.0.1", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^2.0.0", + "webidl-conversions": "^6.1.0", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^8.5.0", + "ws": "^7.4.6", + "xml-name-validator": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "requires": {} + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true, + "peer": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "dev": true, + "peer": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "peer": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "requires": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + } + }, + "jsrsasign": { + "version": "10.8.6", + "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-10.8.6.tgz", + "integrity": "sha512-bQmbVtsfbgaKBTWCKiDCPlUPbdlRIK/FzSwT3BzIgZl/cU6TqXu6pZJsCI/dJVrZ9Gir5GC4woqw9shH/v7MBw==" + }, + "jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "requires": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, + "kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" + }, + "karma": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/karma/-/karma-6.4.2.tgz", + "integrity": "sha512-C6SU/53LB31BEgRg+omznBEMY4SjHU3ricV6zBcAe1EeILKkeScr+fZXtaI5WyDbkVowJxxAI6h73NcFPmXolQ==", + "dev": true, + "requires": { + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", + "source-map": "^0.6.1", + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, + "karma-chrome-launcher": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz", + "integrity": "sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q==", + "dev": true, + "requires": { + "which": "^1.2.1" + }, + "dependencies": { + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "karma-coverage": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/karma-coverage/-/karma-coverage-2.2.1.tgz", + "integrity": "sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-instrument": "^5.1.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.0.5", + "minimatch": "^3.0.4" + } + }, + "karma-jasmine": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine/-/karma-jasmine-5.1.0.tgz", + "integrity": "sha512-i/zQLFrfEpRyQoJF9fsCdTMOF5c2dK7C7OmsuKg2D0YSsuZSfQDiLuaiktbuio6F2wiCsZSnSnieIQ0ant/uzQ==", + "dev": true, + "requires": { + "jasmine-core": "^4.1.0" + }, + "dependencies": { + "jasmine-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.0.tgz", + "integrity": "sha512-O236+gd0ZXS8YAjFx8xKaJ94/erqUliEkJTDedyE7iHvv4ZVqi+q+8acJxu05/WJDKm512EUNn809In37nWlAQ==", + "dev": true + } + } + }, + "karma-jasmine-html-reporter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-html-reporter/-/karma-jasmine-html-reporter-2.1.0.tgz", + "integrity": "sha512-sPQE1+nlsn6Hwb5t+HHwyy0A1FNCVKuL1192b+XNauMYWThz2kweiBVW1DqloRpVvZIJkIoHVB7XRpK78n1xbQ==", + "dev": true, + "requires": {} + }, + "karma-junit-reporter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/karma-junit-reporter/-/karma-junit-reporter-2.0.1.tgz", + "integrity": "sha512-VtcGfE0JE4OE1wn0LK8xxDKaTP7slN8DO3I+4xg6gAi1IoAHAXOJ1V9G/y45Xg6sxdxPOR3THCFtDlAfBo9Afw==", + "dev": true, + "requires": { + "path-is-absolute": "^1.0.0", + "xmlbuilder": "12.0.0" + } + }, + "karma-source-map-support": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/karma-source-map-support/-/karma-source-map-support-1.4.0.tgz", + "integrity": "sha512-RsBECncGO17KAoJCYXjv+ckIz+Ii9NCi+9enk+rq6XC81ezYkb4/RHE6CTXdA7IOJqoF3wcaLfVG0CPmE5ca6A==", + "dev": true, + "requires": { + "source-map-support": "^0.5.5" + } + }, + "keyv": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", + "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "dev": true + }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "launch-editor": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.6.0.tgz", + "integrity": "sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==", + "dev": true, + "requires": { + "picocolors": "^1.0.0", + "shell-quote": "^1.7.3" + } + }, + "layerr": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/layerr/-/layerr-0.1.2.tgz", + "integrity": "sha512-ob5kTd9H3S4GOG2nVXyQhOu9O8nBgP555XxWPkJI0tR0JeRilfyTp8WtPdIJHLXBmHMSdEq5+KMxiYABeScsIQ==", + "peer": true + }, + "less": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/less/-/less-4.1.3.tgz", + "integrity": "sha512-w16Xk/Ta9Hhyei0Gpz9m7VS8F28nieJaL/VyShID7cYvP6IL5oHeL6p4TXSDJqZE/lNv0oJ2pGVjJsRkfwm5FA==", + "dev": true, + "requires": { + "copy-anything": "^2.0.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "parse-node-version": "^1.0.1", + "source-map": "~0.6.0", + "tslib": "^2.3.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "optional": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "optional": true + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "optional": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "less-loader": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.0.tgz", + "integrity": "sha512-C+uDBV7kS7W5fJlUjq5mPBeBVhYpTIm5gB09APT9o3n/ILeaXVsiSFTbZpTJCJwQ/Crczfn3DmfQFwxYusWFug==", + "dev": true, + "requires": { + "klona": "^2.0.4" + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "license-webpack-plugin": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-4.0.2.tgz", + "integrity": "sha512-771TFWFD70G1wLTC4oU2Cw4qvtmNrIw+wRvBtn+okgHl7slJVi7zfNcdmqDL72BojM30VNJ2UHylr1o77U37Jw==", + "dev": true, + "requires": { + "webpack-sources": "^3.0.0" + } + }, + "lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "requires": { + "immediate": "~3.0.5" + } + }, + "lines-and-columns": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.3.tgz", + "integrity": "sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w==", + "dev": true + }, + "load-bmfont": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.1.tgz", + "integrity": "sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA==", + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + } + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "dev": true, + "peer": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "dev": true, + "peer": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "peer": true + } + } + }, + "loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true + }, + "loader-utils": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.2.1.tgz", + "integrity": "sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, + "lodash.capitalize": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz", + "integrity": "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==", + "dev": true, + "peer": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "dev": true, + "peer": true + }, + "lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "dev": true, + "peer": true + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "peer": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true, + "peer": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.uniqby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz", + "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", + "dev": true, + "peer": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dev": true, + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + } + }, + "logform": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.5.1.tgz", + "integrity": "sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==", + "requires": { + "@colors/colors": "1.5.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + } + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "requires": { + "yallist": "^3.0.2" + } + }, + "ltx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ltx/-/ltx-3.0.0.tgz", + "integrity": "sha512-bu3/4/ApUmMqVNuIkHaRhqVtEi6didYcBDIF56xhPRCzVpdztCipZ62CUuaxMlMBUzaVL93+4LZRqe02fuAG6A==" + }, + "magic-string": { + "version": "0.30.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.1.tgz", + "integrity": "sha512-mbVKXPmS0z0G4XqFDCTllmDQ6coZzn94aMlb0o/A4HEHJCKcanlDZwYJgwnkmgD3jyWhUgj9VsPrfd972yPffA==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "make-fetch-happen": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", + "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "dependencies": { + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + } + } + }, + "makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "requires": { + "tmpl": "1.0.5" + } + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "peer": true + }, + "marked": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.2.tgz", + "integrity": "sha512-ahRPGXJpjMjwSOlBoTMZAK7ATXkli5qCPxZ21TG44rx1KEo44bii4ekgTDQPNRQ4Kh7JMb9Ub1PVk1NxRSsorg==", + "dev": true, + "peer": true + }, + "marked-terminal": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-5.2.0.tgz", + "integrity": "sha512-Piv6yNwAQXGFjZSaiNljyNFw7jKDdGrw70FSbtxEyldLsyeuV5ZHm/1wW++kWbrOF1VPnUgYOhB2oLL0ZpnekA==", + "dev": true, + "peer": true, + "requires": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "dependencies": { + "ansi-escapes": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", + "dev": true, + "peer": true, + "requires": { + "type-fest": "^3.0.0" + } + }, + "chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "peer": true + }, + "type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "peer": true + } + } + }, + "md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "peer": true, + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + }, + "memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "requires": { + "fs-monkey": "^1.0.4" + } + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "peer": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "dependencies": { + "hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "peer": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "peer": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "peer": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "peer": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "peer": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "peer": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "peer": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "peer": true + } + } + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "peer": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "peer": true + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "peer": true + } + } + }, + "merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==" + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "requires": { + "dom-walk": "^0.1.0" + } + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "peer": true + }, + "mini-css-extract-plugin": { + "version": "2.7.6", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz", + "integrity": "sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==", + "dev": true, + "requires": { + "schema-utils": "^4.0.0" + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "peer": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "minipass": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", + "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "dev": true + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-fetch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.4.tgz", + "integrity": "sha512-jHAqnA728uUpIaFm7NWsCnqKT6UqZz7GcI/bDpPATuwYyKwJwW0remxSCxUlKiEty+eopHGa3oc8WxgQ1FFJqg==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^7.0.3", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.1.tgz", + "integrity": "sha512-ODqY18UZt/I8k+b7rl2AENgbWE8IDYam+undIJONvigAz8KR5GWblsFTEfQs0WODsjbSXWlm+JHEv8Gr6Tfdbg==", + "dev": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "requires": { + "minimist": "^1.2.6" + } + }, + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "peer": true + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, + "mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "requires": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "saslprep": "^1.0.3", + "socks": "^2.7.1" + } + }, + "mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + }, + "dependencies": { + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + } + } + }, + "mongoose": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.3.tgz", + "integrity": "sha512-eok0lW6mZJHK2vVSWyJb9tUfPMUuRF3h7YC4pU2K2/YSZBlNDUwvKsHgftMOANbokP2Ry+4ylvzAdW4KjkRFjw==", + "requires": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "requires": { + "ee-first": "1.1.1" + } + } + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + } + }, + "mrmime": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-1.0.1.tgz", + "integrity": "sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + } + }, + "multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "requires": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + } + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "needle": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.2.0.tgz", + "integrity": "sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==", + "dev": true, + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "optional": true, + "requires": { + "ms": "^2.1.1" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "nerf-dart": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nerf-dart/-/nerf-dart-1.0.0.tgz", + "integrity": "sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==", + "dev": true, + "peer": true + }, + "nested-property": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz", + "integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==", + "peer": true + }, + "ng-packagr": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/ng-packagr/-/ng-packagr-16.2.0.tgz", + "integrity": "sha512-3u2FVSpKDa0EJRSGOAhYIZwjtnG7SVFBnUf5fk/VfDOxVV4kFRea6DEK7f/mb1D4WV/yqSZB9JmvBZp0uuIGeA==", + "dev": true, + "requires": { + "@rollup/plugin-json": "^6.0.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "ajv": "^8.11.0", + "ansi-colors": "^4.1.3", + "autoprefixer": "^10.4.12", + "browserslist": "^4.21.4", + "cacache": "^17.0.0", + "chokidar": "^3.5.3", + "commander": "^11.0.0", + "convert-source-map": "^2.0.0", + "dependency-graph": "^0.11.0", + "esbuild": "^0.19.0", + "esbuild-wasm": "^0.19.0", + "fast-glob": "^3.2.12", + "find-cache-dir": "^3.3.2", + "injection-js": "^2.4.0", + "jsonc-parser": "^3.2.0", + "less": "^4.1.3", + "ora": "^5.1.0", + "piscina": "^4.0.0", + "postcss": "^8.4.16", + "postcss-url": "^10.1.3", + "rollup": "^3.0.0", + "rxjs": "^7.5.6", + "sass": "^1.55.0" + }, + "dependencies": { + "@esbuild/android-arm": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.2.tgz", + "integrity": "sha512-tM8yLeYVe7pRyAu9VMi/Q7aunpLwD139EY1S99xbQkT4/q2qa6eA4ige/WJQYdJ8GBL1K33pPFhPfPdJ/WzT8Q==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.2.tgz", + "integrity": "sha512-lsB65vAbe90I/Qe10OjkmrdxSX4UJDjosDgb8sZUKcg3oefEuW2OT2Vozz8ef7wrJbMcmhvCC+hciF8jY/uAkw==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.2.tgz", + "integrity": "sha512-qK/TpmHt2M/Hg82WXHRc/W/2SGo/l1thtDHZWqFq7oi24AjZ4O/CpPSu6ZuYKFkEgmZlFoa7CooAyYmuvnaG8w==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.2.tgz", + "integrity": "sha512-Ora8JokrvrzEPEpZO18ZYXkH4asCdc1DLdcVy8TGf5eWtPO1Ie4WroEJzwI52ZGtpODy3+m0a2yEX9l+KUn0tA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.2.tgz", + "integrity": "sha512-tP+B5UuIbbFMj2hQaUr6EALlHOIOmlLM2FK7jeFBobPy2ERdohI4Ka6ZFjZ1ZYsrHE/hZimGuU90jusRE0pwDw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.2.tgz", + "integrity": "sha512-YbPY2kc0acfzL1VPVK6EnAlig4f+l8xmq36OZkU0jzBVHcOTyQDhnKQaLzZudNJQyymd9OqQezeaBgkTGdTGeQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.2.tgz", + "integrity": "sha512-nSO5uZT2clM6hosjWHAsS15hLrwCvIWx+b2e3lZ3MwbYSaXwvfO528OF+dLjas1g3bZonciivI8qKR/Hm7IWGw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.2.tgz", + "integrity": "sha512-Odalh8hICg7SOD7XCj0YLpYCEc+6mkoq63UnExDCiRA2wXEmGlK5JVrW50vZR9Qz4qkvqnHcpH+OFEggO3PgTg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.2.tgz", + "integrity": "sha512-ig2P7GeG//zWlU0AggA3pV1h5gdix0MA3wgB+NsnBXViwiGgY77fuN9Wr5uoCrs2YzaYfogXgsWZbm+HGr09xg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.2.tgz", + "integrity": "sha512-mLfp0ziRPOLSTek0Gd9T5B8AtzKAkoZE70fneiiyPlSnUKKI4lp+mGEnQXcQEHLJAcIYDPSyBvsUbKUG2ri/XQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.2.tgz", + "integrity": "sha512-hn28+JNDTxxCpnYjdDYVMNTR3SKavyLlCHHkufHV91fkewpIyQchS1d8wSbmXhs1fiYDpNww8KTFlJ1dHsxeSw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.2.tgz", + "integrity": "sha512-KbXaC0Sejt7vD2fEgPoIKb6nxkfYW9OmFUK9XQE4//PvGIxNIfPk1NmlHmMg6f25x57rpmEFrn1OotASYIAaTg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.2.tgz", + "integrity": "sha512-dJ0kE8KTqbiHtA3Fc/zn7lCd7pqVr4JcT0JqOnbj4LLzYnp+7h8Qi4yjfq42ZlHfhOCM42rBh0EwHYLL6LEzcw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.2.tgz", + "integrity": "sha512-7Z/jKNFufZ/bbu4INqqCN6DDlrmOTmdw6D0gH+6Y7auok2r02Ur661qPuXidPOJ+FSgbEeQnnAGgsVynfLuOEw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.2.tgz", + "integrity": "sha512-U+RinR6aXXABFCcAY4gSlv4CL1oOVvSSCdseQmGO66H+XyuQGZIUdhG56SZaDJQcLmrSfRmx5XZOWyCJPRqS7g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.2.tgz", + "integrity": "sha512-oxzHTEv6VPm3XXNaHPyUTTte+3wGv7qVQtqaZCrgstI16gCuhNOtBXLEBkBREP57YTd68P0VgDgG73jSD8bwXQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.2.tgz", + "integrity": "sha512-WNa5zZk1XpTTwMDompZmvQLHszDDDN7lYjEHCUmAGB83Bgs20EMs7ICD+oKeT6xt4phV4NDdSi/8OfjPbSbZfQ==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.2.tgz", + "integrity": "sha512-S6kI1aT3S++Dedb7vxIuUOb3oAxqxk2Rh5rOXOTYnzN8JzW1VzBd+IqPiSpgitu45042SYD3HCoEyhLKQcDFDw==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.2.tgz", + "integrity": "sha512-VXSSMsmb+Z8LbsQGcBMiM+fYObDNRm8p7tkUDMPG/g4fhFX5DEFmjxIEa3N8Zr96SjsJ1woAhF0DUnS3MF3ARw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.2.tgz", + "integrity": "sha512-5NayUlSAyb5PQYFAU9x3bHdsqB88RC3aM9lKDAz4X1mo/EchMIT1Q+pSeBXNgkfNmRecLXA0O8xP+x8V+g/LKg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.2.tgz", + "integrity": "sha512-47gL/ek1v36iN0wL9L4Q2MFdujR0poLZMJwhO2/N3gA89jgHp4MR8DKCmwYtGNksbfJb9JoTtbkoe6sDhg2QTA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.2.tgz", + "integrity": "sha512-tcuhV7ncXBqbt/Ybf0IyrMcwVOAPDckMK9rXNHtF17UTK18OKLpg08glminN06pt2WCoALhXdLfSPbVvK/6fxw==", + "dev": true, + "optional": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "esbuild": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.2.tgz", + "integrity": "sha512-G6hPax8UbFakEj3hWO0Vs52LQ8k3lnBhxZWomUJDxfz3rZTLqF5k/FCzuNdLx2RbpBiQQF9H9onlDDH1lZsnjg==", + "dev": true, + "optional": true, + "requires": { + "@esbuild/android-arm": "0.19.2", + "@esbuild/android-arm64": "0.19.2", + "@esbuild/android-x64": "0.19.2", + "@esbuild/darwin-arm64": "0.19.2", + "@esbuild/darwin-x64": "0.19.2", + "@esbuild/freebsd-arm64": "0.19.2", + "@esbuild/freebsd-x64": "0.19.2", + "@esbuild/linux-arm": "0.19.2", + "@esbuild/linux-arm64": "0.19.2", + "@esbuild/linux-ia32": "0.19.2", + "@esbuild/linux-loong64": "0.19.2", + "@esbuild/linux-mips64el": "0.19.2", + "@esbuild/linux-ppc64": "0.19.2", + "@esbuild/linux-riscv64": "0.19.2", + "@esbuild/linux-s390x": "0.19.2", + "@esbuild/linux-x64": "0.19.2", + "@esbuild/netbsd-x64": "0.19.2", + "@esbuild/openbsd-x64": "0.19.2", + "@esbuild/sunos-x64": "0.19.2", + "@esbuild/win32-arm64": "0.19.2", + "@esbuild/win32-ia32": "0.19.2", + "@esbuild/win32-x64": "0.19.2" + } + }, + "esbuild-wasm": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/esbuild-wasm/-/esbuild-wasm-0.19.2.tgz", + "integrity": "sha512-ak2XIIJKby+Uo3Iqh8wtw4pn2uZcnfLgtcmBHIgkShpun5ZIJsFigWXp7uLt7gXk3QAOCMmv0TSsIxD5qdn+Vw==", + "dev": true + }, + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "nice-napi": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", + "integrity": "sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==", + "dev": true, + "optional": true, + "requires": { + "node-addon-api": "^3.0.0", + "node-gyp-build": "^4.2.2" + } + }, + "node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==", + "dev": true + }, + "node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "peer": true, + "requires": { + "lodash": "^4.17.21" + } + }, + "node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, + "node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "dev": true + }, + "node-gyp": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.0.tgz", + "integrity": "sha512-dMXsYP6gc9rRbejLXmTbVRYjAHw7ppswsKyMxuxJxxOHzluIO1rGp9TOQgjFJ+2MCqcOcQTOPB/8Xwhr+7s4Eg==", + "dev": true, + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "node-gyp-build": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", + "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "dev": true + }, + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true + }, + "node-opcua": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua/-/node-opcua-2.109.0.tgz", + "integrity": "sha512-9E8u5O6ZNMxLLGxvK7CqgwUEa/6+bb2tyJF2KdCietHz4H6njLgrw2zNQH1KVwM20+NZMCeDoo3Al73sbGSMQQ==", + "requires": { + "@types/semver": "^7.5.0", + "chalk": "4.1.2", + "node-opcua-address-space": "2.109.0", + "node-opcua-address-space-for-conformance-testing": "2.109.0", + "node-opcua-aggregates": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-client": "2.109.0", + "node-opcua-client-crawler": "2.109.0", + "node-opcua-client-proxy": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-nodesets": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-packet-analyzer": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-server-discovery": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-filter": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-node-management": "2.109.0", + "node-opcua-service-query": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-register-node": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-service-session": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-transport": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "node-opcua-vendor-diagnostic": "2.109.0", + "semver": "^7.5.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-address-space": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-address-space/-/node-opcua-address-space-2.109.0.tgz", + "integrity": "sha512-JVNcUL9NErjCux2GIOVjhI8Vav7Mo0CwiQimxxdTidXs7LB6bkhapd3O9hZ9FEAHyCgwquFEmSa3KSfHKu3M/Q==", + "requires": { + "@types/lodash": "4.14.197", + "@types/semver": "^7.5.0", + "async": "^3.2.4", + "chalk": "4.1.2", + "dequeue": "^1.0.5", + "lodash": "4.17.21", + "node-opcua-address-space-base": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-client-dynamic-extension-object": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-nodeset-ua": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "node-opcua-xml2json": "2.109.0", + "semver": "^7.5.4", + "set-prototype-of": "^1.0.0", + "thenify": "^3.3.1", + "xml-writer": "^1.7.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-address-space-base": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-address-space-base/-/node-opcua-address-space-base-2.109.0.tgz", + "integrity": "sha512-NYZxc1v3NrQiA1k58xPEeiDMRHbkBTr4R87MTqypm2YAfWGx/SphtAslXlgdLu3YksvQDqFefj85/z7qNtOXug==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-address-space-for-conformance-testing": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-address-space-for-conformance-testing/-/node-opcua-address-space-for-conformance-testing-2.109.0.tgz", + "integrity": "sha512-9lIvbdrbxTotmaLwRxu562JLm8qDN1eJhZmLQComWR3Bx8dlz+5IL+WAyA94h7AhRdOah8Aorol08nnkGpIIHw==", + "requires": { + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-aggregates": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-aggregates/-/node-opcua-aggregates-2.109.0.tgz", + "integrity": "sha512-DU4ik5t+0NSOqRlFQ5gDcAEddxPrk88E9ezPgOLRle9PYdiX+h3rij4/h2T5+4AyZVNQiSUoHUWOfuszSt5ABQ==", + "requires": { + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-assert": { + "version": "2.105.0", + "resolved": "https://registry.npmjs.org/node-opcua-assert/-/node-opcua-assert-2.105.0.tgz", + "integrity": "sha512-q4VVsbfeXdXarTRga8d100NxkALvhEeAeN/YMBUsOkDIHh/VjrozknSSUT1c0h406QRZdmcoz7MnHCLG0+Rwxw==", + "requires": { + "chalk": "4.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-basic-types": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-basic-types/-/node-opcua-basic-types-2.109.0.tgz", + "integrity": "sha512-jSTIHx9yW4OodTL3KEDIDVnmX79omkmYSlafJQIXoJsdgP7sg6xEqC5n6eWjqfFJi0CC4FF8mojBlhkoyLX1Ng==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-guid": "2.98.1", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0" + } + }, + "node-opcua-binary-stream": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-binary-stream/-/node-opcua-binary-stream-2.109.0.tgz", + "integrity": "sha512-XuJ/YlXm2uzPPE0SCEVfzfiZ5NAOZYrjqSJVS6Ge+bBvXV4ecKz5PyLokQ8F8g7GS3Z8Zb4LOKOYa+ei2Mn2Qw==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-buffer-utils": "2.109.0" + } + }, + "node-opcua-buffer-utils": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-buffer-utils/-/node-opcua-buffer-utils-2.109.0.tgz", + "integrity": "sha512-wi52xeXIX8X8nrar43uvnRS5JJwHPGS8AW/CQWZ7+nS57suQO2hGosLrRL/wpiVEvFZl1LLOrfJIcX3Y54qj8A==" + }, + "node-opcua-certificate-manager": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-certificate-manager/-/node-opcua-certificate-manager-2.109.0.tgz", + "integrity": "sha512-5l2eE7zNlPCWlIPesHM5wmxMO/EGP8mwBmi6YZmOBHC4yV1acT2j2spL6+ij99vp92Y8byYu6IAzx5N98O5/8Q==", + "requires": { + "@types/mkdirp": "1.0.2", + "env-paths": "2.2.1", + "mkdirp": "1.0.4", + "node-opcua-assert": "2.105.0", + "node-opcua-crypto": "4.1.0", + "node-opcua-debug": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-pki": "4.3.0", + "node-opcua-status-code": "2.109.0", + "thenify": "^3.3.1" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + } + } + }, + "node-opcua-chunkmanager": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-chunkmanager/-/node-opcua-chunkmanager-2.109.0.tgz", + "integrity": "sha512-bwY+BVJHAgU13X3dWsfFGSnv2XZm1EyZIY/XeKlhXGV58eURv9lBNe7y7Orp3RJh4zSO0LxA1rwATc5eT7aqZQ==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-packet-assembler": "2.109.0" + } + }, + "node-opcua-client": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client/-/node-opcua-client-2.109.0.tgz", + "integrity": "sha512-DPXhu2VCIVcoHUMY6qrFeULj5IIeK035dlrj3gZyNMhm90A37FU5WaH67GLbmEdbvHRcEL5aN+ITstxJr54sVg==", + "requires": { + "@ster5/global-mutex": "^2.0.0", + "@types/async": "^3.2.20", + "async": "^3.2.4", + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-client-dynamic-extension-object": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-pki": "4.3.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-filter": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-query": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-register-node": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-service-session": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-client-crawler": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client-crawler/-/node-opcua-client-crawler-2.109.0.tgz", + "integrity": "sha512-hpZdcOPLlQoA1pYNQctp8i8OD7tL0WehlbFMrBLCEEeByVZHgLmgFdq88k4U/jjGvAIW8x/dV4A3xw5gvQP1iA==", + "requires": { + "async": "^3.2.4", + "chalk": "4.1.2", + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-client": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "thenify": "^3.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-client-dynamic-extension-object": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client-dynamic-extension-object/-/node-opcua-client-dynamic-extension-object-2.109.0.tgz", + "integrity": "sha512-Wc2dwmQnjzqcYla5+tlkdzQKZAguEtqVOaR4dH+XRjr5+ismJjs/O8bIvJbl5rT3SFmQVPXQgMYDLpq1nWg3UA==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-client-proxy": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-client-proxy/-/node-opcua-client-proxy-2.109.0.tgz", + "integrity": "sha512-gr75WZojmylSjcW9PFhvSB0gZ6BrvKBcuQMwEEhlhs3JeALsJ+YQxG5FxxvJ5TkCNSHxe6XpjTFop8+RuhwyAA==", + "requires": { + "async": "^3.2.4", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-pseudo-session": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node-opcua-common": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-common/-/node-opcua-common-2.109.0.tgz", + "integrity": "sha512-N/Dgh21qT/kwcceJfrlQ46eJllQCNghIwCUneJyLzDH0UfwjW/JP2JRAdHIl0Sbb/l0tjx+FD+qERVA5v2lEbQ==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-crypto": "4.1.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-constants": { + "version": "2.98.1", + "resolved": "https://registry.npmjs.org/node-opcua-constants/-/node-opcua-constants-2.98.1.tgz", + "integrity": "sha512-7RDmofF6vajYmmsbm/t0obqZlL0K7KKgYe4V+QT8qSGdNFrmDANHiAUhgPljur8e8taaDUXFcaOhS4fYjMN1WQ==" + }, + "node-opcua-crypto": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/node-opcua-crypto/-/node-opcua-crypto-4.1.0.tgz", + "integrity": "sha512-2MOWvkArDaJj5iJ5QeVmFME32BuAYcx06RF/h6J23QrqhU9L5j+0OCx8ksC+OfGw4LHt8o8gkcZ+opSrBfoUWQ==", + "requires": { + "@peculiar/webcrypto": "^1.4.3", + "@peculiar/x509": "^1.9.3", + "@types/jsrsasign": "^10.5.8", + "assert": "^2.0.0", + "better-assert": "^1.0.2", + "chalk": "^4.1.2", + "hexy": "0.3.5", + "jsrsasign": "^10.8.6", + "sshpk": "^1.17.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-data-access": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-data-access/-/node-opcua-data-access-2.109.0.tgz", + "integrity": "sha512-v5n5bCj/yWhOjCvxoo1HfdOrCJ+Hmc8k6nVOBx3NIcn5DTAfNuFw7Aqk3vwEEFyJ3nDyoUasRr0zPo1HMp/E6w==", + "requires": { + "node-opcua-data-model": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-data-model": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-data-model/-/node-opcua-data-model-2.109.0.tgz", + "integrity": "sha512-SfeJwylz4fHjrhM9/iEsTiOZhxAPD3oxiyJ49DDE7WVddSzb6jfxevtoyPRDU2UqvqGCjwNkgglYF1RCvNs0Kg==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0" + } + }, + "node-opcua-data-value": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-data-value/-/node-opcua-data-value-2.109.0.tgz", + "integrity": "sha512-bxSGWj3qDjYVvxCtLVscjO2iLgWGu8wnlAP+9XoxKYouBNxQNwlby4yz99i6Trt4AYyIEMMJ2tKRF1Bqzt2+4A==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-date-time": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-date-time/-/node-opcua-date-time-2.109.0.tgz", + "integrity": "sha512-REua4ngOEiwOVlePAhCiNLgDchiGFdRWuP381uuunl4dQhj+6HsAVibvMttEBTytrpZ7VyP/hZJYxcTPgazz1Q==", + "requires": { + "long": "^4.0.0", + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node-opcua-debug": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-debug/-/node-opcua-debug-2.109.0.tgz", + "integrity": "sha512-VUnaE47oWsSDtrzUok4QQtGBaeSzEEKKUh1vLxpEuA05PiCQK6l9s18Pme7Ql0DzSgrpJ03QzplAh3UEyF5GVg==", + "requires": { + "chalk": "4.1.2", + "hexy": "0.3.5", + "node-opcua-assert": "2.105.0", + "node-opcua-buffer-utils": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-enum": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-enum/-/node-opcua-enum-2.109.0.tgz", + "integrity": "sha512-CN38NujK6Tt+EECNNPwBmCyrBNbiB7YkGYW6TEMV7TUBpEcBieYLb/NtS66V7kFcZDFRlXx4mmcraem0QELZ2A==" + }, + "node-opcua-extension-object": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-extension-object/-/node-opcua-extension-object-2.109.0.tgz", + "integrity": "sha512-z1BUljLKUSRwpxhEVTZhVEtz6zQCdbrkVzUqWInvx88zH2Gn6iJMLns6Vy2LUpphn1V4BRBGTyxCok8zpshCpA==", + "requires": { + "chalk": "4.1.2", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-factory": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-factory/-/node-opcua-factory-2.109.0.tgz", + "integrity": "sha512-S3MhKpQe2PVKOEgfrZ3OKQNgoFgu3HEzTTvXh5YoKb0c7BwddrYK4gONuyiOr7JAKZg2I17fHkkUTZrQSFBFbw==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-debug": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-guid": "2.98.1", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-utils": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-generator": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-generator/-/node-opcua-generator-2.109.0.tgz", + "integrity": "sha512-mLXf723UTukIGqOvfORwbIM000pnHcThe6N7CTMj7UB8pfVGLjygM/vzjsfrZNlXBZCCG2WQSgRrJG4VMqbxMw==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-schemas": "2.109.0", + "node-opcua-utils": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-guid": { + "version": "2.98.1", + "resolved": "https://registry.npmjs.org/node-opcua-guid/-/node-opcua-guid-2.98.1.tgz", + "integrity": "sha512-09hWgnEUhq6t0QPrCIklAa4/x2aNhp1te0l2IkFQdNkJ8iYEBEKk0lJG7+nA+fNyys0ccUohvHdvuFae2fSGTw==" + }, + "node-opcua-hostname": { + "version": "2.105.0", + "resolved": "https://registry.npmjs.org/node-opcua-hostname/-/node-opcua-hostname-2.105.0.tgz", + "integrity": "sha512-nb55yjaaRaxxyypcy3QQ1brml1eK1lBTECy6+36v9v/gs0Kuv9rtdQbu4sZ089qOeuvsWNCFHPDULlLyfDMgeQ==" + }, + "node-opcua-nodeid": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-nodeid/-/node-opcua-nodeid-2.109.0.tgz", + "integrity": "sha512-9I/JiYhaDlxJ1xr8083V13Qpu58WrEMTZtzmIPRlxb61KCYWvmHNIiCpo5hHkOvnn1bv4+oW4ICK96sqv16vbw==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-guid": "2.98.1" + } + }, + "node-opcua-nodeset-ua": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-nodeset-ua/-/node-opcua-nodeset-ua-2.109.0.tgz", + "integrity": "sha512-EMMAvEMPX5uUgN7dlCGtkYH0z4YzMPeTNY7G0WEdcKaDc5eK6TLBMeUnqtD/VM16hI4a1sYDq1wp6yqvZfwLdg==", + "requires": { + "node-opcua-address-space-base": "2.109.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-data-access": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-nodesets": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-nodesets/-/node-opcua-nodesets-2.109.0.tgz", + "integrity": "sha512-WwP5otCcU1HmEhAt8BuhzphiZ3EtkTk+S6C+xO9kYvON5GA9Ie/2Cwh6cyWXaSBi7Nb7EOWumlWokV8USZ5g/Q==" + }, + "node-opcua-numeric-range": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-numeric-range/-/node-opcua-numeric-range-2.109.0.tgz", + "integrity": "sha512-iwYvqZ3Hp7eCNdidTLd1y4faVBGV7takgG1mjHvTHojCHsxntjKUJ0AfwIMzKrw0YGzc400aVN5tPPOk3xW57w==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-status-code": "2.109.0" + } + }, + "node-opcua-object-registry": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-object-registry/-/node-opcua-object-registry-2.109.0.tgz", + "integrity": "sha512-4MiWKVtveaKYbwpYkjAXsGRvxbK8zSBTaPVQPvuG8ZO3FN0er/ZoJjXRkisCTmJIRkap/0YH8rMJH1Wx1X3vyQ==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-debug": "2.109.0" + } + }, + "node-opcua-packet-analyzer": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-packet-analyzer/-/node-opcua-packet-analyzer-2.109.0.tgz", + "integrity": "sha512-TB2qJlin7Bzdl1U0S1TbDIjUGR4o6KoPCA7ylkySvao/SdQLa4EzjYcIjl7qvheMeqgz8EEKGsBaKGPJsept8A==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-utils": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-packet-assembler": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-packet-assembler/-/node-opcua-packet-assembler-2.109.0.tgz", + "integrity": "sha512-1+JR5ssPMbI8/1m+7RufvdPBQzRhjj4fgLoEQzq0C4BgzpzEWCKrTmz2Pxbdm7d/CGYCt6G7ga8iTAKqNz50fw==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-debug": "2.109.0" + } + }, + "node-opcua-pki": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-opcua-pki/-/node-opcua-pki-4.3.0.tgz", + "integrity": "sha512-7GJ2fm9d9L8VSVtj4cW8tlehkcsB/HS1tje2qYcUUxlbF9AJfW4JCInjNBrXYaq7DGPlpF92GgbFDOVmp5D7WQ==", + "requires": { + "@ster5/global-mutex": "^2.0.0", + "async": "^3.2.4", + "byline": "^5.0.0", + "chalk": "4.1.2", + "chokidar": "^3.5.3", + "cli-table": "^0.3.11", + "minimist": "^1.2.8", + "node-opcua-crypto": "4.1.0", + "progress": "^2.0.3", + "rimraf": "3.0.2", + "thenify": "^3.3.1", + "wget-improved-2": "^3.3.0", + "yargs": "17.7.2", + "yauzl": "^2.10.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-pseudo-session": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-pseudo-session/-/node-opcua-pseudo-session-2.109.0.tgz", + "integrity": "sha512-YmMV53BfTT9wEP/stuZlE2SWx1bodybEnW2CC322JPvhRuwDjyO/TOTXgUO+4DPJnTp/hFfPR1Hj6lqbJeQaBw==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + } + }, + "node-opcua-schemas": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-schemas/-/node-opcua-schemas-2.109.0.tgz", + "integrity": "sha512-xQgOP10+X0xpcZkPqufUbIzrdTF5+Gl1QgmkwFeSvSGIhuxJY5cHSLLDvHg14nfaSraTeks+eMS6xum1WpkSsQ==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-variant": "2.109.0", + "node-opcua-xml2json": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-secure-channel": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-secure-channel/-/node-opcua-secure-channel-2.109.0.tgz", + "integrity": "sha512-silNrmvcOU+TTN6inrXdYPTQ4o0yqV8JcFMqxTiHkED/AL6b/2K9NxvYwlzAA2aSIIJQ8JTDxKJcaJcVQwPw0Q==", + "requires": { + "async": "^3.2.4", + "backoff": "^2.5.0", + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-chunkmanager": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-crypto": "4.1.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-packet-analyzer": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-transport": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-server": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-server/-/node-opcua-server-2.109.0.tgz", + "integrity": "sha512-ZKZDv1pt2l29m9XhhocmbXFxTi8HldhBmN9GUGJqK8wrK7J1CRqmNHbrXkw5tVD4sFT12OUGriTWgedSgVnW0A==", + "requires": { + "@ster5/global-mutex": "^2.0.0", + "async": "^3.2.4", + "chalk": "4.1.2", + "dequeue": "^1.0.5", + "lodash": "4.17.21", + "node-opcua-address-space": "2.109.0", + "node-opcua-address-space-base": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-client": "2.109.0", + "node-opcua-client-dynamic-extension-object": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-crypto": "4.1.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-date-time": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-nodesets": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-service-browse": "2.109.0", + "node-opcua-service-call": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-service-filter": "2.109.0", + "node-opcua-service-history": "2.109.0", + "node-opcua-service-node-management": "2.109.0", + "node-opcua-service-query": "2.109.0", + "node-opcua-service-read": "2.109.0", + "node-opcua-service-register-node": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-service-session": "2.109.0", + "node-opcua-service-subscription": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-service-write": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-utils": "2.109.0", + "node-opcua-variant": "2.109.0", + "thenify": "^3.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-server-discovery": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-server-discovery/-/node-opcua-server-discovery-2.109.0.tgz", + "integrity": "sha512-IRqI6eKABxP+t7Loi7qskE/baoryRuC8eduNtLaBNQyP5WlG/4vqv1MW8oNz3YNr15nwEve2AsD1qbRdBQKk+g==", + "requires": { + "chalk": "4.1.2", + "env-paths": "2.2.1", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-certificate-manager": "2.109.0", + "node-opcua-common": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-hostname": "2.105.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-secure-channel": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-service-discovery": "2.109.0", + "node-opcua-service-endpoints": "2.109.0", + "node-opcua-status-code": "2.109.0", + "sterfive-bonjour-service": "1.1.4", + "thenify": "^3.3.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-service-browse": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-browse/-/node-opcua-service-browse-2.109.0.tgz", + "integrity": "sha512-HgqnzfZOkBoJFpmGlI5bVk6U1lpKZl7GYNhp8U1+c8+nWvfqu2P9+1bA64oWQN3Gav9rKBL+6ZXWQYfsqM2Blw==", + "requires": { + "node-opcua-data-model": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-call": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-call/-/node-opcua-service-call-2.109.0.tgz", + "integrity": "sha512-Uqoi27BZ+Ia3d4PxLE9jnxjEGuTf2N6kreu1uZfwb3j/pzira0dxmudWrq3826XkxZ24+Marhrcc8O0hsw1Chw==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-service-discovery": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-discovery/-/node-opcua-service-discovery-2.109.0.tgz", + "integrity": "sha512-ELh7s1QP20A2FvexHlnk8r3CrDd7eBiSiuoOfQ34UP+41lW2Dt5++/BDfGLqTonG60Zkd2SRP5XYRml+qmmDfw==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-debug": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-types": "2.109.0", + "sterfive-bonjour-service": "1.1.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-service-endpoints": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-endpoints/-/node-opcua-service-endpoints-2.109.0.tgz", + "integrity": "sha512-rFdzGAOdXMWBRAgle4hyHnG5LgAHIdlixBJfpjPzaSNX9eveir9fduY8KPfsNAMMk39SWv4oNyl9QiyAXvA9Ew==", + "requires": { + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-filter": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-filter/-/node-opcua-service-filter-2.109.0.tgz", + "integrity": "sha512-YDBR+ArqKFCUYsplSDzw7+GalgKnyJMHLA3srCMSvex44bQdEZRJuZkI5siZLopL5Aaw/BwGdxQE+Li/8oH7Fg==", + "requires": { + "node-opcua-address-space-base": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-service-translate-browse-path": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-service-history": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-history/-/node-opcua-service-history-2.109.0.tgz", + "integrity": "sha512-VT8V8zJm4N/PmGU9wWXBJrdWuYsTmP2Pc4sM7HDC3aulMLxRcvPRQiP7nz51dVChVvekGW797aW0tSTXl/50rA==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-node-management": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-node-management/-/node-opcua-service-node-management-2.109.0.tgz", + "integrity": "sha512-SNQa9+kCOv6OEJvcKICbx7A4FdQKtkf26xL4zG3sIhvi0Gp5LUh9XsRus88Rs7/00R7nn43u8tDUIUhcqhdxrg==", + "requires": { + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-query": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-query/-/node-opcua-service-query-2.109.0.tgz", + "integrity": "sha512-KRygFtynmEFAuYA29GVN1dRVD4WF3FpM+6YBLnlsuaVCE68hYN5D9QruOPZmjJ7Yk0vfJVzqJVGReooaObpa5A==", + "requires": { + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-read": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-read/-/node-opcua-service-read-2.109.0.tgz", + "integrity": "sha512-exiJUI6uRQqaqNo29XqZUO2gp3SFa9wKRU/2ImENw7latqzdh8hwO/U8Sbg1YjrM7L6moVhdtXcjp4KzzCbhxA==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-service-secure-channel": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-register-node": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-register-node/-/node-opcua-service-register-node-2.109.0.tgz", + "integrity": "sha512-DezkWT8dTeYEGpjXWcKlyj8J7rkkJ3aovRTXdtTiUUP8IbR0tNUSz8+3ElcBwqjG7DsAFCnoL81HMxnv1YIfcg==", + "requires": { + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-secure-channel": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-secure-channel/-/node-opcua-service-secure-channel-2.109.0.tgz", + "integrity": "sha512-pUx1a3d/H2Hz2yNfi+Lq5BCVHjjJjOKMnV0/8Muzdq2uBGjJ6Z1WCMNw0d8DE4D6gdjMho5Ql9tsYPC2YQFy7w==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-session": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-session/-/node-opcua-service-session-2.109.0.tgz", + "integrity": "sha512-E+3YDVSnFjvjt66kADTPeLcqxdNc7ytqm+BJ9+Fy+ccOvCBkBW5BaMRkQTS/fCiJbQYSeLA4XkmfQcfbKWECpQ==", + "requires": { + "node-opcua-factory": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-subscription": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-subscription/-/node-opcua-service-subscription-2.109.0.tgz", + "integrity": "sha512-L4Q5dae4wH26fmZ4IJyxDGBTJEcnGVX8Y/leGdxBYRhbyYeWTs0VvBqLHcc/YKHMXQBv5l0+Sc8oA559cWqKkg==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-types": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-service-translate-browse-path": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-translate-browse-path/-/node-opcua-service-translate-browse-path-2.109.0.tgz", + "integrity": "sha512-/b4f5UEDaWTroe0MmiqG+0pF1E0ut5TLiW2jHye8m3u+zpzGC60Qh0cSbXQ1ShSv9E8Pw3Xa1DUqlgTHn/ovrQ==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-data-model": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-service-write": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-service-write/-/node-opcua-service-write-2.109.0.tgz", + "integrity": "sha512-oIJofZDUsJQQMhhkfxSbo1qZKD8GWMO0I65VgC4qZ6jFmKo2KfGAy4iWgHKHdoqTXfjHKSs63bWJIsgWVeNr8Q==", + "requires": { + "node-opcua-types": "2.109.0" + } + }, + "node-opcua-status-code": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-status-code/-/node-opcua-status-code-2.109.0.tgz", + "integrity": "sha512-j/017+dEy8o/UU3OzS6EDelr2nOPOCMOgJ/ghSADnl7y6qGRwQmpXHGQR2ayVFnDvgxUMFbOGVwCj0QchPt2vA==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-binary-stream": "2.109.0" + } + }, + "node-opcua-transport": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-transport/-/node-opcua-transport-2.109.0.tgz", + "integrity": "sha512-IVsSB/tjHhl7Gs6nrQgVUBoRQkuBz3Ubhre+ZAOFj4UhG3hxX7hakM4xOYv/cLHFTBX3uiENNvCxCwXgFF9nyw==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-buffer-utils": "2.109.0", + "node-opcua-chunkmanager": "2.109.0", + "node-opcua-debug": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-object-registry": "2.109.0", + "node-opcua-packet-assembler": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-utils": "2.109.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-types": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-types/-/node-opcua-types-2.109.0.tgz", + "integrity": "sha512-5fBzKM/pLx+gJTV5dTKnLVPsBhGl34h096lyzvuwFN0XAiaT/oM0GapEXL/it16yhWmMesDifaoEsPgBSl/yAQ==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-data-value": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-extension-object": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-generator": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-numeric-range": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-utils": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-utils/-/node-opcua-utils-2.109.0.tgz", + "integrity": "sha512-SB7jQAbWrfufQgkB0j0wUjcP9MhBQLGS0MtWXc7JK+7F8Wu4PLNJTz4S4Qidy6qpiPTokl92L1TRSuFhMlWObw==", + "requires": { + "chalk": "4.1.2", + "node-opcua-assert": "2.105.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "node-opcua-variant": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-variant/-/node-opcua-variant-2.109.0.tgz", + "integrity": "sha512-NmUbaWVyH9o7vD2o1xw4ManbU8/lCAThof5XDfQgkbw2FZ3tAu6+oo0psbvl7DHgOMJTY8a12gaDQ0Jwy1RnSQ==", + "requires": { + "node-opcua-assert": "2.105.0", + "node-opcua-basic-types": "2.109.0", + "node-opcua-binary-stream": "2.109.0", + "node-opcua-data-model": "2.109.0", + "node-opcua-enum": "2.109.0", + "node-opcua-factory": "2.109.0", + "node-opcua-nodeid": "2.109.0", + "node-opcua-utils": "2.109.0" + } + }, + "node-opcua-vendor-diagnostic": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-vendor-diagnostic/-/node-opcua-vendor-diagnostic-2.109.0.tgz", + "integrity": "sha512-z7OPToOF087syPkaYks63AqEvhpQTPzrL+fOTZHIkvY948kZKjt+VW5pJPmSl4KFCd5yYwSXC6CJS1kgErYvyg==", + "requires": { + "humanize": "0.0.9", + "node-opcua-address-space": "2.109.0", + "node-opcua-assert": "2.105.0", + "node-opcua-constants": "2.98.1", + "node-opcua-debug": "2.109.0", + "node-opcua-server": "2.109.0", + "node-opcua-status-code": "2.109.0", + "node-opcua-variant": "2.109.0" + } + }, + "node-opcua-xml2json": { + "version": "2.109.0", + "resolved": "https://registry.npmjs.org/node-opcua-xml2json/-/node-opcua-xml2json-2.109.0.tgz", + "integrity": "sha512-jIsV74uvYQODEJInwgHpgeZCr43bq8gUoooUawo0No/acb1lYAJQN33NEioNM3I0nO0ISZ/AMjAFTaohoqoQ5A==", + "requires": { + "ltx": "^3.0.0", + "node-opcua-assert": "2.105.0", + "node-opcua-utils": "2.109.0", + "thenify": "^3.3.1", + "xml-writer": "^1.7.0" + } + }, + "node-releases": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + }, + "nodemailer": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==" + }, + "nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "requires": { + "abbrev": "^1.0.0" + } + }, + "normalize-package-data": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", + "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", + "dev": true, + "requires": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, + "normalize-url": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.0.tgz", + "integrity": "sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==", + "dev": true + }, + "npm": { + "version": "9.8.1", + "resolved": "https://registry.npmjs.org/npm/-/npm-9.8.1.tgz", + "integrity": "sha512-AfDvThQzsIXhYgk9zhbk5R+lh811lKkLAeQMMhSypf1BM7zUafeIIBzMzespeuVEJ0+LvY36oRQYf7IKLzU3rw==", + "dev": true, + "peer": true, + "requires": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^6.3.0", + "@npmcli/config": "^6.2.1", + "@npmcli/fs": "^3.1.0", + "@npmcli/map-workspaces": "^3.0.4", + "@npmcli/package-json": "^4.0.1", + "@npmcli/promise-spawn": "^6.0.2", + "@npmcli/run-script": "^6.0.2", + "abbrev": "^2.0.0", + "archy": "~1.0.0", + "cacache": "^17.1.3", + "chalk": "^5.3.0", + "ci-info": "^3.8.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.3", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.16", + "fs-minipass": "^3.0.2", + "glob": "^10.2.7", + "graceful-fs": "^4.2.11", + "hosted-git-info": "^6.1.1", + "ini": "^4.1.1", + "init-package-json": "^5.0.0", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^3.0.0", + "libnpmaccess": "^7.0.2", + "libnpmdiff": "^5.0.19", + "libnpmexec": "^6.0.3", + "libnpmfund": "^4.0.19", + "libnpmhook": "^9.0.3", + "libnpmorg": "^5.0.4", + "libnpmpack": "^5.0.19", + "libnpmpublish": "^7.5.0", + "libnpmsearch": "^6.0.2", + "libnpmteam": "^5.0.3", + "libnpmversion": "^4.0.2", + "make-fetch-happen": "^11.1.1", + "minimatch": "^9.0.3", + "minipass": "^5.0.0", + "minipass-pipeline": "^1.2.4", + "ms": "^2.1.2", + "node-gyp": "^9.4.0", + "nopt": "^7.2.0", + "npm-audit-report": "^5.0.0", + "npm-install-checks": "^6.1.1", + "npm-package-arg": "^10.1.0", + "npm-pick-manifest": "^8.0.1", + "npm-profile": "^7.0.1", + "npm-registry-fetch": "^14.0.5", + "npm-user-validate": "^2.0.0", + "npmlog": "^7.0.1", + "p-map": "^4.0.0", + "pacote": "^15.2.0", + "parse-conflict-json": "^3.0.1", + "proc-log": "^3.0.0", + "qrcode-terminal": "^0.12.0", + "read": "^2.1.0", + "semver": "^7.5.4", + "sigstore": "^1.7.0", + "ssri": "^10.0.4", + "supports-color": "^9.4.0", + "tar": "^6.1.15", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^3.0.0", + "validate-npm-package-name": "^5.0.0", + "which": "^3.0.1", + "write-file-atomic": "^5.0.1" + }, + "dependencies": { + "@colors/colors": { + "version": "1.5.0", + "bundled": true, + "dev": true, + "optional": true, + "peer": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "emoji-regex": { + "version": "9.2.2", + "bundled": true, + "dev": true, + "peer": true + }, + "string-width": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "@isaacs/string-locale-compare": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "peer": true + }, + "@npmcli/arborist": { + "version": "6.3.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/fs": "^3.1.0", + "@npmcli/installed-package-contents": "^2.0.2", + "@npmcli/map-workspaces": "^3.0.2", + "@npmcli/metavuln-calculator": "^5.0.0", + "@npmcli/name-from-folder": "^2.0.0", + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/package-json": "^4.0.0", + "@npmcli/query": "^3.0.0", + "@npmcli/run-script": "^6.0.0", + "bin-links": "^4.0.1", + "cacache": "^17.0.4", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "json-stringify-nice": "^1.1.4", + "minimatch": "^9.0.0", + "nopt": "^7.0.0", + "npm-install-checks": "^6.0.0", + "npm-package-arg": "^10.1.0", + "npm-pick-manifest": "^8.0.1", + "npm-registry-fetch": "^14.0.3", + "npmlog": "^7.0.1", + "pacote": "^15.0.8", + "parse-conflict-json": "^3.0.0", + "proc-log": "^3.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.2", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^10.0.1", + "treeverse": "^3.0.0", + "walk-up-path": "^3.0.1" + } + }, + "@npmcli/config": { + "version": "6.2.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/map-workspaces": "^3.0.2", + "ci-info": "^3.8.0", + "ini": "^4.1.0", + "nopt": "^7.0.0", + "proc-log": "^3.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.5", + "walk-up-path": "^3.0.1" + } + }, + "@npmcli/disparity-colors": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.3.0" + } + }, + "@npmcli/fs": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "semver": "^7.3.5" + } + }, + "@npmcli/git": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/promise-spawn": "^6.0.0", + "lru-cache": "^7.4.4", + "npm-pick-manifest": "^8.0.0", + "proc-log": "^3.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^3.0.0" + } + }, + "@npmcli/installed-package-contents": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-bundled": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "@npmcli/map-workspaces": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/name-from-folder": "^2.0.0", + "glob": "^10.2.2", + "minimatch": "^9.0.0", + "read-package-json-fast": "^3.0.0" + } + }, + "@npmcli/metavuln-calculator": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "cacache": "^17.0.0", + "json-parse-even-better-errors": "^3.0.0", + "pacote": "^15.0.0", + "semver": "^7.3.5" + } + }, + "@npmcli/name-from-folder": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "@npmcli/node-gyp": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "@npmcli/package-json": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/git": "^4.1.0", + "glob": "^10.2.2", + "hosted-git-info": "^6.1.1", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "proc-log": "^3.0.0", + "semver": "^7.5.3" + } + }, + "@npmcli/promise-spawn": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "which": "^3.0.0" + } + }, + "@npmcli/query": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "@npmcli/run-script": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/node-gyp": "^3.0.0", + "@npmcli/promise-spawn": "^6.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^3.0.0", + "which": "^3.0.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "bundled": true, + "dev": true, + "optional": true, + "peer": true + }, + "@sigstore/protobuf-specs": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "peer": true + }, + "@sigstore/tuf": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@sigstore/protobuf-specs": "^0.1.0", + "tuf-js": "^1.1.7" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "@tufjs/canonical-json": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "@tufjs/models": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@tufjs/canonical-json": "1.0.0", + "minimatch": "^9.0.0" + } + }, + "abbrev": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "abort-controller": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "agent-base": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "debug": "4" + } + }, + "agentkeepalive": { + "version": "4.3.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + } + }, + "aggregate-error": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "ansi-styles": { + "version": "4.3.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "aproba": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "are-we-there-yet": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^4.1.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "peer": true + }, + "base64-js": { + "version": "1.5.1", + "bundled": true, + "dev": true, + "peer": true + }, + "bin-links": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "cmd-shim": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "read-cmd-shim": "^4.0.0", + "write-file-atomic": "^5.0.0" + } + }, + "binary-extensions": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "peer": true + }, + "brace-expansion": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "buffer": { + "version": "6.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "builtins": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "semver": "^7.0.0" + } + }, + "cacache": { + "version": "17.1.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + } + }, + "chalk": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "peer": true + }, + "chownr": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "ci-info": { + "version": "3.8.0", + "bundled": true, + "dev": true, + "peer": true + }, + "cidr-regex": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ip-regex": "^4.1.0" + } + }, + "clean-stack": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "peer": true + }, + "cli-columns": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + } + }, + "cli-table3": { + "version": "0.6.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@colors/colors": "1.5.0", + "string-width": "^4.2.0" + } + }, + "clone": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "peer": true + }, + "cmd-shim": { + "version": "6.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "color-convert": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "peer": true + }, + "color-support": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "peer": true + }, + "columnify": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + } + }, + "common-ancestor-path": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "peer": true + }, + "cross-spawn": { + "version": "7.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "cssesc": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "debug": { + "version": "4.3.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "peer": true + } + } + }, + "defaults": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "clone": "^1.0.2" + } + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "depd": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "diff": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "peer": true + }, + "eastasianwidth": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "peer": true + }, + "emoji-regex": { + "version": "8.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "encoding": { + "version": "0.1.13", + "bundled": true, + "dev": true, + "optional": true, + "peer": true, + "requires": { + "iconv-lite": "^0.6.2" + } + }, + "env-paths": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "peer": true + }, + "err-code": { + "version": "2.0.3", + "bundled": true, + "dev": true, + "peer": true + }, + "event-target-shim": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "events": { + "version": "3.3.0", + "bundled": true, + "dev": true, + "peer": true + }, + "exponential-backoff": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "peer": true + }, + "fastest-levenshtein": { + "version": "1.0.16", + "bundled": true, + "dev": true, + "peer": true + }, + "foreground-child": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "fs-minipass": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^5.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "function-bind": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "peer": true + }, + "gauge": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^4.0.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "glob": { + "version": "10.2.7", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", + "path-scurry": "^1.7.0" + } + }, + "graceful-fs": { + "version": "4.2.11", + "bundled": true, + "dev": true, + "peer": true + }, + "has": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "hosted-git-info": { + "version": "6.1.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "lru-cache": "^7.5.1" + } + }, + "http-cache-semantics": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "peer": true + }, + "http-proxy-agent": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "humanize-ms": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ms": "^2.0.0" + } + }, + "iconv-lite": { + "version": "0.6.3", + "bundled": true, + "dev": true, + "optional": true, + "peer": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ieee754": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "peer": true + }, + "ignore-walk": { + "version": "6.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minimatch": "^9.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "peer": true + }, + "indent-string": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "peer": true + }, + "ini": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "peer": true + }, + "init-package-json": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-package-arg": "^10.0.0", + "promzard": "^1.0.0", + "read": "^2.0.0", + "read-package-json": "^6.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^5.0.0" + } + }, + "ip": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "ip-regex": { + "version": "4.3.0", + "bundled": true, + "dev": true, + "peer": true + }, + "is-cidr": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "cidr-regex": "^3.1.1" + } + }, + "is-core-module": { + "version": "2.12.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "is-lambda": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "jackspeak": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "json-parse-even-better-errors": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "json-stringify-nice": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "peer": true + }, + "jsonparse": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "peer": true + }, + "just-diff": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "peer": true + }, + "just-diff-apply": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "peer": true + }, + "libnpmaccess": { + "version": "7.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-package-arg": "^10.1.0", + "npm-registry-fetch": "^14.0.3" + } + }, + "libnpmdiff": { + "version": "5.0.19", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/arborist": "^6.3.0", + "@npmcli/disparity-colors": "^3.0.0", + "@npmcli/installed-package-contents": "^2.0.2", + "binary-extensions": "^2.2.0", + "diff": "^5.1.0", + "minimatch": "^9.0.0", + "npm-package-arg": "^10.1.0", + "pacote": "^15.0.8", + "tar": "^6.1.13" + } + }, + "libnpmexec": { + "version": "6.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/arborist": "^6.3.0", + "@npmcli/run-script": "^6.0.0", + "ci-info": "^3.7.1", + "npm-package-arg": "^10.1.0", + "npmlog": "^7.0.1", + "pacote": "^15.0.8", + "proc-log": "^3.0.0", + "read": "^2.0.0", + "read-package-json-fast": "^3.0.2", + "semver": "^7.3.7", + "walk-up-path": "^3.0.1" + } + }, + "libnpmfund": { + "version": "4.0.19", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/arborist": "^6.3.0" + } + }, + "libnpmhook": { + "version": "9.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^14.0.3" + } + }, + "libnpmorg": { + "version": "5.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^14.0.3" + } + }, + "libnpmpack": { + "version": "5.0.19", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/arborist": "^6.3.0", + "@npmcli/run-script": "^6.0.0", + "npm-package-arg": "^10.1.0", + "pacote": "^15.0.8" + } + }, + "libnpmpublish": { + "version": "7.5.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ci-info": "^3.6.1", + "normalize-package-data": "^5.0.0", + "npm-package-arg": "^10.1.0", + "npm-registry-fetch": "^14.0.3", + "proc-log": "^3.0.0", + "semver": "^7.3.7", + "sigstore": "^1.4.0", + "ssri": "^10.0.1" + } + }, + "libnpmsearch": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-registry-fetch": "^14.0.3" + } + }, + "libnpmteam": { + "version": "5.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^14.0.3" + } + }, + "libnpmversion": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/git": "^4.0.1", + "@npmcli/run-script": "^6.0.0", + "json-parse-even-better-errors": "^3.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.7" + } + }, + "lru-cache": { + "version": "7.18.3", + "bundled": true, + "dev": true, + "peer": true + }, + "make-fetch-happen": { + "version": "11.1.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "minipass-collect": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-fetch": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^5.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "minipass-flush": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-json-stream": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minizlib": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "bundled": true, + "dev": true, + "peer": true + }, + "ms": { + "version": "2.1.3", + "bundled": true, + "dev": true, + "peer": true + }, + "mute-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "negotiator": { + "version": "0.6.3", + "bundled": true, + "dev": true, + "peer": true + }, + "node-gyp": { + "version": "9.4.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "peer": true + }, + "are-we-there-yet": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "gauge": { + "version": "4.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + } + }, + "glob": { + "version": "7.2.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "nopt": { + "version": "6.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "abbrev": "^1.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "readable-stream": { + "version": "3.6.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "signal-exit": { + "version": "3.0.7", + "bundled": true, + "dev": true, + "peer": true + }, + "which": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "nopt": { + "version": "7.2.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "abbrev": "^2.0.0" + } + }, + "normalize-package-data": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "hosted-git-info": "^6.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + } + }, + "npm-audit-report": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "npm-bundled": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-normalize-package-bin": "^3.0.0" + } + }, + "npm-install-checks": { + "version": "6.1.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "npm-package-arg": { + "version": "10.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + } + }, + "npm-packlist": { + "version": "7.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ignore-walk": "^6.0.0" + } + }, + "npm-pick-manifest": { + "version": "8.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + } + }, + "npm-profile": { + "version": "7.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0" + } + }, + "npm-registry-fetch": { + "version": "14.0.5", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + } + }, + "npm-user-validate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "npmlog": { + "version": "7.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "are-we-there-yet": "^4.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^5.0.0", + "set-blocking": "^2.0.0" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "wrappy": "1" + } + }, + "p-map": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "pacote": { + "version": "15.2.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + } + }, + "parse-conflict-json": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "json-parse-even-better-errors": "^3.0.0", + "just-diff": "^6.0.0", + "just-diff-apply": "^5.2.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "path-key": { + "version": "3.1.1", + "bundled": true, + "dev": true, + "peer": true + }, + "path-scurry": { + "version": "1.9.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "lru-cache": "^9.1.1", + "minipass": "^5.0.0 || ^6.0.2" + }, + "dependencies": { + "lru-cache": { + "version": "9.1.1", + "bundled": true, + "dev": true, + "peer": true + } + } + }, + "postcss-selector-parser": { + "version": "6.0.13", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "proc-log": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "process": { + "version": "0.11.10", + "bundled": true, + "dev": true, + "peer": true + }, + "promise-all-reject-late": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "promise-call-limit": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "peer": true + }, + "promise-inflight": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "promise-retry": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "promzard": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "read": "^2.0.0" + } + }, + "qrcode-terminal": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "peer": true + }, + "read": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "mute-stream": "~1.0.0" + } + }, + "read-cmd-shim": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "read-package-json": { + "version": "6.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "read-package-json-fast": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + } + }, + "readable-stream": { + "version": "4.4.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10" + } + }, + "retry": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "peer": true + }, + "rimraf": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "glob": { + "version": "7.2.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "safe-buffer": { + "version": "5.2.1", + "bundled": true, + "dev": true, + "peer": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true, + "peer": true + }, + "semver": { + "version": "7.5.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "shebang-command": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "signal-exit": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "peer": true + }, + "sigstore": { + "version": "1.7.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@sigstore/protobuf-specs": "^0.1.0", + "@sigstore/tuf": "^1.0.1", + "make-fetch-happen": "^11.0.1" + } + }, + "smart-buffer": { + "version": "4.2.0", + "bundled": true, + "dev": true, + "peer": true + }, + "socks": { + "version": "2.7.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "7.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "spdx-correct": { + "version": "3.2.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "bundled": true, + "dev": true, + "peer": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.13", + "bundled": true, + "dev": true, + "peer": true + }, + "ssri": { + "version": "10.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^5.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "9.4.0", + "bundled": true, + "dev": true, + "peer": true + }, + "tar": { + "version": "6.1.15", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "fs-minipass": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + } + } + }, + "text-table": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "peer": true + }, + "tiny-relative-date": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "peer": true + }, + "treeverse": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true + }, + "tuf-js": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + } + }, + "unique-filename": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "unique-slug": "^4.0.0" + } + }, + "unique-slug": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "peer": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "5.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "builtins": "^5.0.0" + } + }, + "walk-up-path": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "wcwidth": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "bundled": true, + "dev": true, + "peer": true + }, + "ansi-styles": { + "version": "6.2.1", + "bundled": true, + "dev": true, + "peer": true + }, + "emoji-regex": { + "version": "9.2.2", + "bundled": true, + "dev": true, + "peer": true + }, + "string-width": { + "version": "5.1.2", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "peer": true + }, + "write-file-atomic": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "peer": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + } + }, + "yallist": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "peer": true + } + } + }, + "npm-bundled": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.0.tgz", + "integrity": "sha512-Vq0eyEQy+elFpzsKjMss9kxqb9tG3YHg4dsyWuUENuzvSUWe1TCnW/vV9FkhvBk/brEDoDiVd+M1Btosa6ImdQ==", + "dev": true, + "requires": { + "npm-normalize-package-bin": "^3.0.0" + } + }, + "npm-install-checks": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.2.0.tgz", + "integrity": "sha512-744wat5wAAHsxa4590mWO0tJ8PKxR8ORZsH9wGpQc3nWTzozMAgBN/XyqYw7mg3yqLM8dLwEnwSfKMmXAjF69g==", + "dev": true, + "requires": { + "semver": "^7.1.1" + } + }, + "npm-normalize-package-bin": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", + "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", + "dev": true + }, + "npm-package-arg": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", + "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", + "dev": true, + "requires": { + "hosted-git-info": "^6.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + } + }, + "npm-packlist": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", + "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", + "dev": true, + "requires": { + "ignore-walk": "^6.0.0" + } + }, + "npm-pick-manifest": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.1.tgz", + "integrity": "sha512-mRtvlBjTsJvfCCdmPtiu2bdlx8d/KXtF7yNXNWe7G0Z36qWA9Ny5zXsI2PfBZEv7SXgoxTmNaTzGSbbzDZChoA==", + "dev": true, + "requires": { + "npm-install-checks": "^6.0.0", + "npm-normalize-package-bin": "^3.0.0", + "npm-package-arg": "^10.0.0", + "semver": "^7.3.5" + } + }, + "npm-registry-fetch": { + "version": "14.0.5", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", + "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", + "dev": true, + "requires": { + "make-fetch-happen": "^11.0.0", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^10.0.0", + "proc-log": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + } + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "dev": true, + "requires": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + } + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "nwsapi": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", + "integrity": "sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==", + "dev": true + }, + "nx": { + "version": "16.5.1", + "resolved": "https://registry.npmjs.org/nx/-/nx-16.5.1.tgz", + "integrity": "sha512-I3hJRE4hG7JWAtncWwDEO3GVeGPpN0TtM8xH5ArZXyDuVeTth/i3TtJzdDzqXO1HHtIoAQN0xeq4n9cLuMil5g==", + "dev": true, + "requires": { + "@nrwl/tao": "16.5.1", + "@nx/nx-darwin-arm64": "16.5.1", + "@nx/nx-darwin-x64": "16.5.1", + "@nx/nx-freebsd-x64": "16.5.1", + "@nx/nx-linux-arm-gnueabihf": "16.5.1", + "@nx/nx-linux-arm64-gnu": "16.5.1", + "@nx/nx-linux-arm64-musl": "16.5.1", + "@nx/nx-linux-x64-gnu": "16.5.1", + "@nx/nx-linux-x64-musl": "16.5.1", + "@nx/nx-win32-arm64-msvc": "16.5.1", + "@nx/nx-win32-x64-msvc": "16.5.1", + "@parcel/watcher": "2.0.4", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.0.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^7.0.2", + "dotenv": "~10.0.0", + "enquirer": "~2.3.6", + "fast-glob": "3.2.7", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "glob": "7.1.4", + "ignore": "^5.0.4", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "3.0.5", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "semver": "7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "v8-compile-cache": "2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "axios": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "dev": true, + "requires": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "minimatch": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.5.tgz", + "integrity": "sha512-tUpxzX0VAzJHjLu0xUfFv1gwVp9ba3IOuRAVH2EGuRW8a5emA2FlACLqiT/lDVtS1W+TGNwqz3sWaNyLgDJWuw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "semver": { + "version": "7.5.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.3.tgz", + "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" + }, + "object-hash": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", + "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" + }, + "object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object-path": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.8.tgz", + "integrity": "sha512-YJjNZrlXJFM42wTBn6zgOJVar9KFJvzx6sTWDte8sWZF//cnjl0BxHNpfZx+ZffXX63A9q0b1zsFiBX4g4X5KA==", + "dev": true + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, + "on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "requires": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "dev": true + }, + "owncloud-sdk": { + "version": "3.1.0-alpha.7", + "resolved": "https://registry.npmjs.org/owncloud-sdk/-/owncloud-sdk-3.1.0-alpha.7.tgz", + "integrity": "sha512-YNZrwY7yesiQBKu+4Z2JWR9r5LwtPHXuozlChOlOCMzw/FUI6e7koh9+WRrEwoRQZAnWVvtVCre+zUeJXXcqZw==", + "requires": {} + }, + "p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "dev": true + }, + "p-each-series": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", + "integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==", + "dev": true, + "peer": true + }, + "p-filter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-filter/-/p-filter-3.0.0.tgz", + "integrity": "sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg==", + "dev": true, + "peer": true, + "requires": { + "p-map": "^5.1.0" + }, + "dependencies": { + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true + }, + "p-map": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", + "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "dev": true, + "peer": true, + "requires": { + "aggregate-error": "^4.0.0" + } + } + } + }, + "p-is-promise": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", + "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==", + "dev": true, + "peer": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + }, + "dependencies": { + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + } + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "p-reduce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz", + "integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==", + "dev": true + }, + "p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "dev": true, + "requires": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "dependencies": { + "@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "dev": true + }, + "retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true + } + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pacote": { + "version": "15.2.0", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", + "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", + "dev": true, + "requires": { + "@npmcli/git": "^4.0.0", + "@npmcli/installed-package-contents": "^2.0.1", + "@npmcli/promise-spawn": "^6.0.1", + "@npmcli/run-script": "^6.0.0", + "cacache": "^17.0.0", + "fs-minipass": "^3.0.0", + "minipass": "^5.0.0", + "npm-package-arg": "^10.0.0", + "npm-packlist": "^7.0.0", + "npm-pick-manifest": "^8.0.0", + "npm-registry-fetch": "^14.0.0", + "proc-log": "^3.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^6.0.0", + "read-package-json-fast": "^3.0.0", + "sigstore": "^1.3.0", + "ssri": "^10.0.0", + "tar": "^6.1.11" + }, + "dependencies": { + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==" + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==" + }, + "parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "requires": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "parse-headers": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz", + "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==" + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "dependencies": { + "lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + } + } + }, + "parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true + }, + "parse-path": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-7.0.0.tgz", + "integrity": "sha512-Euf9GG8WT9CdqwuWJGdf3RkUcTBArppHABkO7Lm8IzRQp0e2r/kkFnmhu4TSK30Wcu5rVAZLmfPKSBBi9tWFog==", + "dev": true, + "requires": { + "protocols": "^2.0.0" + } + }, + "parse-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-8.1.0.tgz", + "integrity": "sha512-xDvOoLU5XRrcOZvnI6b8zA6n9O9ejNk/GExuz1yBuWUGn9KA97GI6HTs6u02wKara1CeVmZhH+0TZFdWScR89w==", + "dev": true, + "requires": { + "parse-path": "^7.0.0" + } + }, + "parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "dev": true + }, + "parse5-html-rewriting-stream": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-html-rewriting-stream/-/parse5-html-rewriting-stream-7.0.0.tgz", + "integrity": "sha512-mazCyGWkmCRWDI15Zp+UiCqMp/0dgEmkZRvhlsqqKYr4SsVm/TvnSpD9fCvqCA2zoWJcfRym846ejWBBHRiYEg==", + "dev": true, + "requires": { + "entities": "^4.3.0", + "parse5": "^7.0.0", + "parse5-sax-parser": "^7.0.0" + }, + "dependencies": { + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "requires": { + "entities": "^4.4.0" + } + } + } + }, + "parse5-sax-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-sax-parser/-/parse5-sax-parser-7.0.0.tgz", + "integrity": "sha512-5A+v2SNsq8T6/mG3ahcz8ZtQ0OUFTatxPbeidoMB7tkJSGDY3tdfl4MHovtLQHkEn5CGxijNWRQHhRQ6IRpXKg==", + "dev": true, + "requires": { + "parse5": "^7.0.0" + }, + "dependencies": { + "parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "dev": true, + "requires": { + "entities": "^4.4.0" + } + } + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-posix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", + "integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==", + "peer": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz", + "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==", + "dev": true + } + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "peek-readable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz", + "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "dev": true, + "peer": true + }, + "pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true + }, + "piscina": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.0.0.tgz", + "integrity": "sha512-641nAmJS4k4iqpNUqfggqUBUMmlw0ZoM5VZKdQkV2e970Inn3Tk9kroCc1wpsYLD07vCwpys5iY0d3xI/9WkTg==", + "dev": true, + "requires": { + "eventemitter-asyncresource": "^1.0.0", + "hdr-histogram-js": "^2.0.1", + "hdr-histogram-percentiles-obj": "^3.0.0", + "nice-napi": "^1.0.2" + } + }, + "pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA==", + "requires": { + "pngjs": "^3.0.0" + }, + "dependencies": { + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + } + } + }, + "pkg-conf": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-2.1.0.tgz", + "integrity": "sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==", + "dev": true, + "peer": true, + "requires": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "peer": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "peer": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "peer": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "peer": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "peer": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "peer": true + } + } + }, + "pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "dev": true, + "requires": { + "find-up": "^6.3.0" + }, + "dependencies": { + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true + } + } + }, + "pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==" + }, + "postcss": { + "version": "8.4.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", + "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "dev": true, + "requires": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-loader": { + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.3.tgz", + "integrity": "sha512-YgO/yhtevGO/vJePCQmTxiaEwER94LABZN0ZMT4A0vsak9TpO+RvKRs7EmJ8peIlB9xfXCsS7M8LjqncsUZ5HA==", + "dev": true, + "requires": { + "cosmiconfig": "^8.2.0", + "jiti": "^1.18.2", + "semver": "^7.3.8" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", + "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-url": { + "version": "10.1.3", + "resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-10.1.3.tgz", + "integrity": "sha512-FUzyxfI5l2tKmXdYc6VTu3TWZsInayEKPbiyW+P6vmmIrrb4I6CGX0BFoewgYHLK+oIL5FECEK02REYRpBvUCw==", + "dev": true, + "requires": { + "make-dir": "~3.1.0", + "mime": "~2.5.2", + "minimatch": "~3.0.4", + "xxhashjs": "~0.2.2" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, + "precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==" + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true + }, + "pretty-format": { + "version": "29.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.2.tgz", + "integrity": "sha512-1q0oC8eRveTg5nnBEWMXAU2qpv65Gnuf2eCQzSjxpWFkPaPARwqZZDGuNE0zPAZfTCHzIk3A8dIjwlQKKLphyg==", + "dev": true, + "requires": { + "@jest/schemas": "^29.6.0", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "proc-log": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", + "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + }, + "promise": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", + "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", + "peer": true, + "requires": { + "asap": "~2.0.6" + } + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } + }, + "promise.any": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/promise.any/-/promise.any-2.0.5.tgz", + "integrity": "sha512-aM+D4cv0Sjkc90Qhg19XH8Mo5aw28YWqPTFWFkaOpE80MuPbjH/brgI7NI4YGWbcS3suOa0xjJrYznet7lSHhw==", + "requires": { + "array.prototype.map": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-aggregate-error": "^1.0.9", + "get-intrinsic": "^1.1.3", + "iterate-value": "^1.0.2" + } + }, + "prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "requires": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + } + }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "dev": true, + "peer": true + }, + "protocols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/protocols/-/protocols-2.0.1.tgz", + "integrity": "sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==", + "dev": true + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "dependencies": { + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + } + } + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "optional": true + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + }, + "pure-rand": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "dev": true + }, + "pvtsutils": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.4.tgz", + "integrity": "sha512-Y2lmrVPui6d2U0n8lWRSTQ2Ri/0VDcA/BHAPS8/+5ElWp5drG4oPryLaqnehJT71Q2GgmGeB4mau+lSR1gCCmA==", + "requires": { + "tslib": "^2.6.1" + } + }, + "pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==" + }, + "qjobs": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/qjobs/-/qjobs-1.2.0.tgz", + "integrity": "sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg==", + "dev": true + }, + "qs": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "requires": { + "side-channel": "^1.0.4" + } + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "peer": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "peer": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "peer": true + } + } + }, + "react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "read-package-json": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", + "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", + "dev": true, + "requires": { + "glob": "^10.2.2", + "json-parse-even-better-errors": "^3.0.0", + "normalize-package-data": "^5.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "read-package-json-fast": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", + "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", + "dev": true, + "requires": { + "json-parse-even-better-errors": "^3.0.0", + "npm-normalize-package-bin": "^3.0.0" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true + } + } + }, + "read-pkg": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-8.0.0.tgz", + "integrity": "sha512-Ajb9oSjxXBw0YyOiwtQ2dKbAA/vMnUPnY63XcCk+mXo0BwIdQEMgZLZiMWGttQHcUhUgbK0mH85ethMPKXxziw==", + "dev": true, + "peer": true, + "requires": { + "@types/normalize-package-data": "^2.4.1", + "normalize-package-data": "^5.0.0", + "parse-json": "^7.0.0", + "type-fest": "^3.8.0" + }, + "dependencies": { + "json-parse-even-better-errors": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.0.tgz", + "integrity": "sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==", + "dev": true, + "peer": true + }, + "parse-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-7.0.0.tgz", + "integrity": "sha512-kP+TQYAzAiVnzOlWOe0diD6L35s9bJh0SCn95PIbZFKrOYuIRQsQkeWEYxzVDuHTt9V9YqvYCJ2Qo4z9wdfZPw==", + "dev": true, + "peer": true, + "requires": { + "@babel/code-frame": "^7.21.4", + "error-ex": "^1.3.2", + "json-parse-even-better-errors": "^3.0.0", + "lines-and-columns": "^2.0.3", + "type-fest": "^3.8.0" + } + }, + "type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "peer": true + } + } + }, + "read-pkg-up": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-10.0.0.tgz", + "integrity": "sha512-jgmKiS//w2Zs+YbX039CorlkOp8FIVbSAN8r8GJHDsGlmNPXo+VeHkqAwCiQVTTx5/LwLZTcEw59z3DvcLbr0g==", + "dev": true, + "peer": true, + "requires": { + "find-up": "^6.3.0", + "read-pkg": "^8.0.0", + "type-fest": "^3.12.0" + }, + "dependencies": { + "find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "dev": true, + "peer": true, + "requires": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + } + }, + "locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "dev": true, + "peer": true, + "requires": { + "p-locate": "^6.0.0" + } + }, + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "peer": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "dev": true, + "peer": true, + "requires": { + "p-limit": "^4.0.0" + } + }, + "path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "dev": true, + "peer": true + }, + "type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "peer": true + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "peer": true + } + } + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "readable-web-to-node-stream": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz", + "integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==", + "requires": { + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "peer": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "redeyed": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", + "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "dev": true, + "peer": true, + "requires": { + "esprima": "~4.0.0" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", + "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-parser": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", + "integrity": "sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + } + }, + "regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "dev": true, + "requires": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + } + }, + "registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "dev": true, + "peer": true, + "requires": { + "@pnpm/npm-conf": "^2.1.0" + } + }, + "regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" + }, + "resolve": { + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", + "dev": true, + "requires": { + "is-core-module": "^2.11.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-url-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", + "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^8.2.14", + "source-map": "0.6.1" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true + }, + "responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "dev": true, + "requires": { + "lowercase-keys": "^3.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==" + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", + "dev": true + }, + "rimraf": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", + "dev": true, + "requires": { + "glob": "^10.2.5" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.3.tgz", + "integrity": "sha512-92vPiMb/iqpmEgsOoIDvTjc50wf9CCCvMzsi6W0JLPeUKE8TWP1a73PgqSrqy7iAZxaSD1YdzU7QZR5LF51MJw==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "rollup": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", + "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "requires": { + "tslib": "^2.1.0" + } + }, + "safe-array-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", + "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "sass": { + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.64.1.tgz", + "integrity": "sha512-16rRACSOFEE8VN7SCgBu1MpYCyN7urj9At898tyzdXFhC+a+yOX5dXwAR7L8/IdPJ1NB8OYoXmD55DM30B2kEQ==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sass-loader": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.2.tgz", + "integrity": "sha512-CQbKl57kdEv+KDLquhC+gE3pXt74LEAzm+tzywcA0/aHZuub8wTErbjAoNI57rPUWRYRNC5WUnNl8eGJNbDdwg==", + "dev": true, + "requires": { + "neo-async": "^2.6.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "saxes": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", + "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "schema-utils": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", + "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true + }, + "selfsigned": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.1.1.tgz", + "integrity": "sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==", + "dev": true, + "requires": { + "node-forge": "^1" + } + }, + "semantic-release": { + "version": "21.0.7", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-21.0.7.tgz", + "integrity": "sha512-peRDSXN+hF8EFSKzze90ff/EnAmgITHQ/a3SZpRV3479ny0BIZWEJ33uX6/GlOSKdaSxo9hVRDyv2/u2MuF+Bw==", + "dev": true, + "peer": true, + "requires": { + "@semantic-release/commit-analyzer": "^10.0.0", + "@semantic-release/error": "^4.0.0", + "@semantic-release/github": "^9.0.0", + "@semantic-release/npm": "^10.0.2", + "@semantic-release/release-notes-generator": "^11.0.0", + "aggregate-error": "^4.0.1", + "cosmiconfig": "^8.0.0", + "debug": "^4.0.0", + "env-ci": "^9.0.0", + "execa": "^7.0.0", + "figures": "^5.0.0", + "find-versions": "^5.1.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^3.0.0", + "hosted-git-info": "^6.0.0", + "lodash-es": "^4.17.21", + "marked": "^5.0.0", + "marked-terminal": "^5.1.1", + "micromatch": "^4.0.2", + "p-each-series": "^3.0.0", + "p-reduce": "^3.0.0", + "read-pkg-up": "^10.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^4.0.0", + "signale": "^1.2.1", + "yargs": "^17.5.1" + }, + "dependencies": { + "@semantic-release/error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/error/-/error-4.0.0.tgz", + "integrity": "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==", + "dev": true, + "peer": true + }, + "aggregate-error": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", + "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "dev": true, + "peer": true, + "requires": { + "clean-stack": "^4.0.0", + "indent-string": "^5.0.0" + } + }, + "clean-stack": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", + "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", + "dev": true, + "peer": true, + "requires": { + "escape-string-regexp": "5.0.0" + } + }, + "execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "peer": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "figures": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", + "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "dev": true, + "peer": true, + "requires": { + "escape-string-regexp": "^5.0.0", + "is-unicode-supported": "^1.2.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "peer": true + }, + "indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "peer": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true + }, + "is-unicode-supported": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", + "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "dev": true, + "peer": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "peer": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "peer": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "peer": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "p-reduce": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz", + "integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==", + "dev": true, + "peer": true + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "peer": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "peer": true + } + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "dev": true, + "peer": true, + "requires": { + "semver": "^7.3.5" + } + }, + "semver-regex": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz", + "integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==", + "dev": true, + "peer": true + }, + "send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "requires": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "serialize-javascript": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", + "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true + }, + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, + "set-prototype-of": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-prototype-of/-/set-prototype-of-1.0.0.tgz", + "integrity": "sha512-OeTRSF+prexqa0ZOjfYR2pdGG/9nyzoXhsDj9M/0R8cgK1r9SkiQiqGdQQcObmnalKVPaTLrF8P71OacYqcYGw==" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + }, + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "requires": { + "kind-of": "^6.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "signale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz", + "integrity": "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==", + "dev": true, + "peer": true, + "requires": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "peer": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dev": true, + "peer": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + } + } + }, + "sigstore": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", + "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", + "dev": true, + "requires": { + "@sigstore/bundle": "^1.1.0", + "@sigstore/protobuf-specs": "^0.2.0", + "@sigstore/sign": "^1.0.0", + "@sigstore/tuf": "^1.0.3", + "make-fetch-happen": "^11.0.1" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, + "sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, + "socket.io": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.7.2.tgz", + "integrity": "sha512-bvKVS29/I5fl2FGLNHuXlQaUH/BlzX1IN6S+NKLNZpBsPZIDH+90eQmCs2Railn4YUiww4SzUedJ6+uzwFnKLw==", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "cors": "~2.8.5", + "debug": "~4.3.2", + "engine.io": "~6.5.2", + "socket.io-adapter": "~2.5.2", + "socket.io-parser": "~4.2.4" + } + }, + "socket.io-adapter": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.2.tgz", + "integrity": "sha512-87C3LO/NOMc+eMcpcxUBebGjkpMDkNBS9tf7KJqcDsmL936EChtVva71Dw2q4tQcuVC+hAUy4an2NO/sYXmwRA==", + "dev": true, + "requires": { + "ws": "~8.11.0" + }, + "dependencies": { + "ws": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", + "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "dev": true, + "requires": {} + } + } + }, + "socket.io-parser": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", + "dev": true, + "requires": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1" + } + }, + "sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "source-map-loader": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-4.0.1.tgz", + "integrity": "sha512-oqXpzDIByKONVY8g1NUPOTQhe0UTU5bWUl32GSkqK2LjJj0HmwTMVKxcUip0RgAYhY1mqgOxjbQM48a0mmeNfA==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "iconv-lite": "^0.6.3", + "source-map-js": "^1.0.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "spawn-error-forwarder": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", + "integrity": "sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==", + "dev": true, + "peer": true + }, + "spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "peer": true, + "requires": { + "through": "2" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "peer": true, + "requires": { + "readable-stream": "^3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "peer": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.5.tgz", + "integrity": "sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==", + "dev": true, + "requires": { + "minipass": "^7.0.3" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==" + }, + "stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + }, + "sterfive-bonjour-service": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sterfive-bonjour-service/-/sterfive-bonjour-service-1.1.4.tgz", + "integrity": "sha512-QqDpnBb3KLD6ytdY2KSxsynw1jJAvzfOloQt83GQNXO6CGf84ZY+37tpOEZo1FzgUkFiVsL7pYyg71olDppI/w==", + "requires": { + "@types/multicast-dns": "^7.2.1", + "array-flatten": "^2.1.2", + "dns-equal": "^1.0.0", + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.4" + }, + "dependencies": { + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==" + } + } + }, + "stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "requires": { + "internal-slot": "^1.0.4" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==", + "dev": true, + "peer": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dev": true, + "requires": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "requires": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "peer": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "peer": true + }, + "strong-log-transformer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", + "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", + "dev": true, + "requires": { + "duplexer": "^0.1.1", + "minimist": "^1.2.0", + "through": "^2.3.4" + } + }, + "strtok3": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz", + "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==", + "requires": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^4.1.0" + } + }, + "superagent": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.1.2.tgz", + "integrity": "sha512-6WTxW1EB6yCxV5VFOIPQruWGHqc3yI7hEmZK6h+pyk69Lk/Ut7rLUY6W/ONF2MjBuGjvmMiIpsrVJ2vjrHlslA==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + } + }, + "supertest": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.3.3.tgz", + "integrity": "sha512-EMCG6G8gDu5qEqRQ3JjjPs6+FYT1a7Hv5ApHvtSghmOFJYtsU5S+pSb6Y2EUeCEY3CmEL3mmQ8YWlPOzQomabA==", + "dev": true, + "requires": { + "methods": "^1.1.2", + "superagent": "^8.0.5" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "peer": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "peer": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "swagger-ui-dist": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.3.2.tgz", + "integrity": "sha512-NZ8YDKqf58+bWbD3v1NnF9QCveqtovT8e/4fJoc/ZgafJdFSqVEYiXM+OnS6rg9Yrb8z6bwpJ4H6hLk7mMs36Q==" + }, + "swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "requires": { + "swagger-ui-dist": ">=5.0.0" + } + }, + "symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true + }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dev": true, + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "temp-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, + "peer": true + }, + "tempy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", + "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", + "dev": true, + "peer": true, + "requires": { + "is-stream": "^3.0.0", + "temp-dir": "^3.0.0", + "type-fest": "^2.12.2", + "unique-string": "^3.0.0" + }, + "dependencies": { + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "peer": true + }, + "type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "dev": true, + "peer": true + } + } + }, + "terser": { + "version": "5.19.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.19.2.tgz", + "integrity": "sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==", + "dev": true, + "requires": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.17", + "jest-worker": "^27.4.5", + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + }, + "supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "peer": true + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "peer": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==" + }, + "timm": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz", + "integrity": "sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw==" + }, + "tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==" + }, + "tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "dev": true, + "requires": { + "rimraf": "^3.0.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" + }, + "token-types": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz", + "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==", + "requires": { + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + } + }, + "tough-cookie": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz", + "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "dependencies": { + "universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true + } + } + }, + "tr46": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", + "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "traverse": { + "version": "0.6.7", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.7.tgz", + "integrity": "sha512-/y956gpUo9ZNCb99YjxG7OaslxZWHfCHAUUfshwqOXmxUIvqLjVO581BT+gM59+QV9tFe6/CGG53tsA1Y7RSdg==", + "dev": true, + "peer": true + }, + "tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true + }, + "trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "peer": true + }, + "triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==" + }, + "ts-api-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", + "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", + "dev": true, + "requires": {} + }, + "ts-jest": { + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", + "dev": true, + "requires": { + "bs-logger": "0.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", + "lodash.memoize": "4.x", + "make-error": "1.x", + "semver": "^7.5.3", + "yargs-parser": "^21.0.1" + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "dependencies": { + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + } + } + }, + "tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "requires": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + } + } + }, + "tslib": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", + "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" + }, + "tsoa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tsoa/-/tsoa-5.1.1.tgz", + "integrity": "sha512-U6+5CyD3+u9Dtza0fBnv4+lgmbZEskYljzRpKf3edGCAGtMKD2rfjtDw9jUdTfWb1FEDvsnR3pRvsSGBXaOdsA==", + "requires": { + "@tsoa/cli": "^5.1.1", + "@tsoa/runtime": "^5.0.0" + } + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, + "tsutils-etc": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/tsutils-etc/-/tsutils-etc-1.4.2.tgz", + "integrity": "sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==", + "dev": true, + "requires": { + "@types/yargs": "^17.0.0", + "yargs": "^17.0.0" + } + }, + "tsyringe": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.8.0.tgz", + "integrity": "sha512-YB1FG+axdxADa3ncEtRnQCFq/M0lALGLxSZeVNbTU8NqhOVc51nnv2CISTcvc1kyv6EGPtXVr0v6lWeDxiijOA==", + "requires": { + "tslib": "^1.9.3" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, + "tuf-js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", + "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", + "dev": true, + "requires": { + "@tufjs/models": "1.0.4", + "debug": "^4.3.4", + "make-fetch-happen": "^11.1.1" + } + }, + "tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + } + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, + "typed-assert": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/typed-assert/-/typed-assert-1.0.9.tgz", + "integrity": "sha512-KNNZtayBCtmnNmbo5mG47p1XsCyrx6iVqomjcZnec/1Y5GGARaxPs6r49RnSPeUP3YjNYiU9sQHAtY4BBvnZwg==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==" + }, + "ua-parser-js": { + "version": "0.7.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", + "integrity": "sha512-veRf7dawaj9xaWEu9HoTVn5Pggtc/qj+kqTOFvNiN1l0YdxwC1kvel57UCjThjGa3BHBihE8/UJAHI+uQHmd/g==", + "dev": true + }, + "uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true + }, + "unique-filename": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", + "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", + "dev": true, + "requires": { + "unique-slug": "^4.0.0" + } + }, + "unique-slug": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", + "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "dev": true, + "peer": true, + "requires": { + "crypto-random-string": "^4.0.0" + } + }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", + "dev": true, + "peer": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + }, + "update-browserslist-db": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, + "url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "peer": true + }, + "utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "requires": { + "pako": "^1.0.11" + } + }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + }, + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true + }, + "v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validate-npm-package-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.0.tgz", + "integrity": "sha512-YuKoXDAhBYxY7SfOKxHBDoSyENFeW5VvIIQp2TGQuit8gpK6MnWaQelBKxso72DoxTZfZdcP3W90LqpSkgPzLQ==", + "dev": true, + "requires": { + "builtins": "^5.0.0" + } + }, + "validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + }, + "vite": { + "version": "4.4.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.7.tgz", + "integrity": "sha512-6pYf9QJ1mHylfVh39HpuSfMPojPSKVxZvnclX1K1FyZ1PXDOcLBibdq5t1qxJSnL63ca8Wf4zts6mD8u8oc9Fw==", + "dev": true, + "requires": { + "esbuild": "^0.18.10", + "fsevents": "~2.3.2", + "postcss": "^8.4.26", + "rollup": "^3.25.2" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==", + "dev": true + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", + "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", + "dev": true, + "requires": { + "xml-name-validator": "^3.0.0" + } + }, + "walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "requires": { + "makeerror": "1.0.12" + } + }, + "watchpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", + "dev": true, + "requires": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "requires": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, + "webdav": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/webdav/-/webdav-4.10.0.tgz", + "integrity": "sha512-8PevPYhFsgbDhVGQQyrfBDYHiCYtN01qVX9zjFDA/OjIFqu28SsZuZdvGxBIQu2/e3Wp8M5oUpYvLM3uLP8g6A==", + "peer": true, + "requires": { + "axios": "^0.27.2", + "base-64": "^1.0.0", + "byte-length": "^1.0.2", + "fast-xml-parser": "^3.19.0", + "he": "^1.2.0", + "hot-patcher": "^0.5.0", + "layerr": "^0.1.2", + "md5": "^2.3.0", + "minimatch": "^5.0.1", + "nested-property": "^4.0.0", + "path-posix": "^1.0.0", + "url-join": "^4.0.1", + "url-parse": "^1.5.10" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "peer": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "peer": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "webidl-conversions": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", + "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", + "dev": true + }, + "webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "dependencies": { + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + } + } + } + }, + "webpack-dev-middleware": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-6.1.1.tgz", + "integrity": "sha512-y51HrHaFeeWir0YO4f0g+9GwZawuigzcAdRNon6jErXy/SqV/+O6eaVAzDqE6t3e3NpGeR5CS+cCDaTC+V3yEQ==", + "dev": true, + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.12", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + }, + "webpack-dev-server": { + "version": "4.15.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz", + "integrity": "sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==", + "dev": true, + "requires": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.1", + "ws": "^8.13.0" + }, + "dependencies": { + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "webpack-dev-middleware": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz", + "integrity": "sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==", + "dev": true, + "requires": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + } + } + } + }, + "webpack-merge": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.9.0.tgz", + "integrity": "sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg==", + "dev": true, + "requires": { + "clone-deep": "^4.0.1", + "wildcard": "^2.0.0" + } + }, + "webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true + }, + "webpack-subresource-integrity": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-5.1.0.tgz", + "integrity": "sha512-sacXoX+xd8r4WKsy9MvH/q/vBtEHr86cpImXwyg74pFIpERKt6FmB8cXpeuh0ZLgclOlHI4Wcll7+R5L02xk9Q==", + "dev": true, + "requires": { + "typed-assert": "^1.0.8" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "wget-improved-2": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/wget-improved-2/-/wget-improved-2-3.3.0.tgz", + "integrity": "sha512-NSPde/8mUqgmznPhO7oB5gS8IVUlR7GOlY857IaAf3PkkHbx/6FwZxUhW+GRP1GQbZDnCMF5fPieWXFng8Z43A==", + "requires": { + "minimist": "1.2.6", + "tunnel": "0.0.6" + }, + "dependencies": { + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + } + } + }, + "whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "dev": true, + "requires": { + "iconv-lite": "0.4.24" + } + }, + "whatwg-fetch": { + "version": "3.6.17", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.17.tgz", + "integrity": "sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ==" + }, + "whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "dev": true + }, + "whatwg-url": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", + "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", + "dev": true, + "requires": { + "lodash": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "dev": true + }, + "winston": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.10.0.tgz", + "integrity": "sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g==", + "requires": { + "@colors/colors": "1.5.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "winston-daily-rotate-file": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz", + "integrity": "sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==", + "requires": { + "file-stream-rotator": "^0.6.1", + "object-hash": "^2.0.1", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + } + }, + "winston-transport": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.5.0.tgz", + "integrity": "sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q==", + "requires": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + } + }, + "ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "requires": {} + }, + "xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "requires": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "peer": true, + "requires": { + "sax": "^1.2.4" + } + }, + "xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "dev": true + }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==" + }, + "xml-writer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/xml-writer/-/xml-writer-1.7.0.tgz", + "integrity": "sha512-elFVMRiV5jb59fbc87zzVa0C01QLBEWP909mRuWqFqrYC5wNTH5QW4AaKMNv7d6zAsuOulkD7wnztZNLQW0Nfg==" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + } + } + }, + "xmlbuilder": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-12.0.0.tgz", + "integrity": "sha512-lMo8DJ8u6JRWp0/Y4XLa/atVDr75H9litKlb2E5j3V3MesoL50EBgZDWoLT3F/LztVnG67GjPXLZpqcky/UMnQ==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "xpath": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.33.tgz", + "integrity": "sha512-NNXnzrkDrAzalLhIUc01jO2mOzXGXh1JwPgkihcLLzw98c0WgYDmmjSh1Kl3wzaxSVWMuA+fe0WTWOBDWCBmNA==" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "xxhashjs": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz", + "integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==", + "dev": true, + "requires": { + "cuint": "^0.2.2" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "requires": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + } + }, + "yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "requires": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + } + } + } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, + "zone.js": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.13.1.tgz", + "integrity": "sha512-+bIeDAFEBYuXRuU3qGQvzdPap+N1zjM4KkBAiiQuVVCrHrhjDuY6VkUhNa5+U27+9w0q3fbKiMCbpJ0XzMmSWA==", + "requires": { + "tslib": "^2.3.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..14c8b799 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "aas-portal-project", + "version": "3.0.0", + "description": "Web-based visualization and control of asset administration shells.", + "type": "module", + "scripts": { + "tsoa": "npm run tsoa -w aas-server", + "start": "docker build -f Dockerfile -t aasportal . && docker run -d --name AASPortal -p 80:80 --restart=always aasportal", + "header": "node copyright-header.js", + "coverage": "node coverage-summary.js", + "user-db": "docker run -p 27017:27017 -d --name aasportal-users -e MONGO_INITDB_DATABASE=aasportal-users mongo", + "lint": "ng lint", + "test": "npm run test -ws", + "tsc": "npm run tsc -ws", + "build": "npm run build -ws", + "build:debug": "npm run build:debug -ws", + "lib:build": "npm run build -w common -w aas-lib", + "lib:build:debug": "npm run build:debug -w common -w aas-lib", + "aas-portal:build": "npm run build -w common -w aas-lib -w aas-portal", + "aas-portal:build:debug": "npm run build:build -w common -w aas-lib -w aas-portal", + "aas-server:build": "npm run build -w common -w aas-server", + "aas-server:build:debug": "npm run build:debug -w common -w aas-server" + }, + "repository": { + "type": "git", + "url": "https://gitlab.cc-asp.fraunhofer.de/iosb-ina-big-data-plattformen/aasportal.git" + }, + "author": "Fraunhofer IOSB-INA", + "homepage": "https://www.iosb-ina.fraunhofer.de/", + "license": "Apache-2.0", + "workspaces": [ + "./projects/common", + "./projects/aas-server", + "./projects/aas-lib", + "./projects/aas-portal" + ], + "devDependencies": { + "@semantic-release/git": "^10.0.1", + "@semantic-release/gitlab": "^12.0.5" + } +} diff --git a/projects/aas-lib/.eslintrc.json b/projects/aas-lib/.eslintrc.json new file mode 100644 index 00000000..f9f1c647 --- /dev/null +++ b/projects/aas-lib/.eslintrc.json @@ -0,0 +1,37 @@ +{ + "extends": "../../.eslintrc.json", + "ignorePatterns": [ + "!**/*" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "fhg", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "fhg", + "style": "kebab-case" + } + ] + } + }, + { + "files": [ + "*.html" + ], + "rules": {} + } + ] +} diff --git a/projects/aas-lib/karma.conf.cjs b/projects/aas-lib/karma.conf.cjs new file mode 100644 index 00000000..012ced75 --- /dev/null +++ b/projects/aas-lib/karma.conf.cjs @@ -0,0 +1,56 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-junit-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + files: [ + { pattern: './src/**/*.ts', type: 'js' }, + ], + jasmineHtmlReporter: { + suppressAll: true // removes the duplicated traces + }, + junitReporter:{ + outputDir: '../../reports', + outputFile: 'aas-lib.xml', + useBrowserName: false + }, + coverageReporter: { + dir: require('path').join(__dirname, '../../reports/aas-lib'), + subdir: '.', + reporters: [ + { type: 'html' }, + { type: 'json-summary' }, + { type: 'cobertura' } + ] + }, + reporters: ['progress', 'kjhtml', 'junit'], + browsers: ['ChromeHeadlessNoSandbox'], + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: 'ChromeHeadless', + flags: ['--no-sandbox'] + } + }, + singleRun: true, + restartOnFileChange: true + }); +}; diff --git a/projects/aas-lib/ng-package.json b/projects/aas-lib/ng-package.json new file mode 100644 index 00000000..5a2e10de --- /dev/null +++ b/projects/aas-lib/ng-package.json @@ -0,0 +1,7 @@ +{ + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "./dist", + "lib": { + "entryFile": "src/public-api.ts" + } +} \ No newline at end of file diff --git a/projects/aas-lib/package.build.json b/projects/aas-lib/package.build.json new file mode 100644 index 00000000..d29d9702 --- /dev/null +++ b/projects/aas-lib/package.build.json @@ -0,0 +1,43 @@ +{ + "name": "aas-lib", + "version": "3.0.0", + "sideEffects": false, + "type": "module", + "scripts": { + "ng": "ng", + "test": "ng test", + "build": "node pre-build.js && ng build aas-lib && node post-build.js", + "build:debug": "node pre-build.js && ng build aas-lib --configuration development && node post-build.js", + "tsc": "rimraf build && tsc -p tsconfig.json", + "lint": "ng lint aas-lib", + "format": "ng lint aas-lib --fix" + }, + "peerDependencies": { + "@angular/animations": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "rxjs": "~7.8.1", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + } +} \ No newline at end of file diff --git a/projects/aas-lib/package.dev.json b/projects/aas-lib/package.dev.json new file mode 100644 index 00000000..7b212e37 --- /dev/null +++ b/projects/aas-lib/package.dev.json @@ -0,0 +1,56 @@ +{ + "name": "aas-lib", + "version": "3.0.0", + "sideEffects": false, + "type": "module", + "scripts": { + "ng": "ng", + "test": "ng test aas-lib", + "build": "node pre-build.js && ng build aas-lib && node post-build.js", + "build:debug": "node pre-build.js && ng build aas-lib --configuration development && node post-build.js", + "tsc": "rimraf build && tsc -p tsconfig.json", + "lint": "ng lint aas-lib", + "format": "ng lint aas-lib --fix" + }, + "module": "dist/fesm2022/aas-lib.mjs", + "typings": "dist/index.d.ts", + "exports": { + "./package.json": { + "default": "./package.json" + }, + ".": { + "types": "./dist/index.d.ts", + "esm2022": "./dist/esm2022/aas-lib.mjs", + "esm": "./dist/esm2022/aas-lib.mjs", + "default": "./dist/fesm2022/aas-lib.mjs" + } + }, + "peerDependencies": { + "@angular/animations": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "rxjs": "~7.8.1", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + } +} \ No newline at end of file diff --git a/projects/aas-lib/package.json b/projects/aas-lib/package.json new file mode 100644 index 00000000..7b212e37 --- /dev/null +++ b/projects/aas-lib/package.json @@ -0,0 +1,56 @@ +{ + "name": "aas-lib", + "version": "3.0.0", + "sideEffects": false, + "type": "module", + "scripts": { + "ng": "ng", + "test": "ng test aas-lib", + "build": "node pre-build.js && ng build aas-lib && node post-build.js", + "build:debug": "node pre-build.js && ng build aas-lib --configuration development && node post-build.js", + "tsc": "rimraf build && tsc -p tsconfig.json", + "lint": "ng lint aas-lib", + "format": "ng lint aas-lib --fix" + }, + "module": "dist/fesm2022/aas-lib.mjs", + "typings": "dist/index.d.ts", + "exports": { + "./package.json": { + "default": "./package.json" + }, + ".": { + "types": "./dist/index.d.ts", + "esm2022": "./dist/esm2022/aas-lib.mjs", + "esm": "./dist/esm2022/aas-lib.mjs", + "default": "./dist/fesm2022/aas-lib.mjs" + } + }, + "peerDependencies": { + "@angular/animations": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "rxjs": "~7.8.1", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + } +} \ No newline at end of file diff --git a/projects/aas-lib/post-build.js b/projects/aas-lib/post-build.js new file mode 100644 index 00000000..9fdc3334 --- /dev/null +++ b/projects/aas-lib/post-build.js @@ -0,0 +1,11 @@ +import { copyFile } from 'fs/promises'; +import { dirname, resolve } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +main(); + +async function main() { + await copyFile(resolve(__dirname, 'package.dev.json'), resolve(__dirname, 'package.json')); +} \ No newline at end of file diff --git a/projects/aas-lib/pre-build.js b/projects/aas-lib/pre-build.js new file mode 100644 index 00000000..b9a94176 --- /dev/null +++ b/projects/aas-lib/pre-build.js @@ -0,0 +1,11 @@ +import { copyFile } from 'fs/promises'; +import { dirname, resolve } from 'path'; +import { fileURLToPath } from 'url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +main(); + +async function main() { + await copyFile(resolve(__dirname, 'package.build.json'), resolve(__dirname, 'package.json')); +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-lib.module.ts b/projects/aas-lib/src/lib/aas-lib.module.ts new file mode 100644 index 00000000..af384d76 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-lib.module.ts @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { StoreModule } from '@ngrx/store'; +import { FormsModule } from '@angular/forms'; + +import { ToolbarComponent } from './toolbar/toolbar.component'; +import { NotifyComponent } from './notify/notify.component'; +import { LocalizeComponent } from './localize/localize.component'; +import { LoginFormComponent } from './auth/login-form/login-form.component'; +import { RegisterFormComponent } from './auth/register-form/register-form.component'; +import { ProfileFormComponent } from './auth/profile-form/profile-form.component'; +import { AuthComponent } from './auth/auth.component'; +import { LibraryTableComponent } from './library-table/library-table.component'; +import { HttpClientModule } from '@angular/common/http'; +import { aasTableReducer } from './aas-table/aas-table.reducer'; +import { MaxLengthPipe } from './max-length.pipe'; +import { AASTableComponent } from './aas-table/aas-table.component'; +import { SortableHeaderDirective } from './sortable-header.directive'; +import { AASTreeComponent } from './aas-tree/aas-tree.component'; +import { aasTreeReducer } from './aas-tree/aas-tree.reducer'; +import { OperationCallFormComponent } from './aas-tree/operation-call-form/operation-call-form.component'; +import { ShowImageFormComponent } from './aas-tree/show-image-form/show-image-form.component'; +import { ShowVideoFormComponent } from './aas-tree/show-video-form/show-video-form.component'; +import { customerFeedbackReducer } from './customer-feedback/customer-feedback.reducer'; +import { CustomerFeedbackComponent } from './customer-feedback/customer-feedback.component'; +import { ScoreComponent } from './score/score.component'; +import { DigitalNameplateComponent } from './digital-nameplate/digital-nameplate.component'; +import { messageTableReducer } from './message-table/massage-table.reducer'; +import { MessageTableComponent } from './message-table/message-table.component'; +import { SecuredImageComponent } from './secured-image/secured-image.component'; + +@NgModule({ + declarations: [ + NotifyComponent, + ToolbarComponent, + LocalizeComponent, + LoginFormComponent, + RegisterFormComponent, + ProfileFormComponent, + AuthComponent, + LibraryTableComponent, + MaxLengthPipe, + SortableHeaderDirective, + AASTableComponent, + AASTreeComponent, + OperationCallFormComponent, + ShowImageFormComponent, + ShowVideoFormComponent, + CustomerFeedbackComponent, + ScoreComponent, + DigitalNameplateComponent, + MessageTableComponent, + SecuredImageComponent + ], + imports: [ + CommonModule, + FormsModule, + TranslateModule, + NgbModule, + StoreModule.forFeature('messageTable', messageTableReducer), + StoreModule.forFeature('customerFeedback', customerFeedbackReducer), + StoreModule.forFeature('aasTable', aasTableReducer), + StoreModule.forFeature('tree', aasTreeReducer), + HttpClientModule + ], + exports: [ + NotifyComponent, + ToolbarComponent, + LocalizeComponent, + LoginFormComponent, + RegisterFormComponent, + ProfileFormComponent, + AuthComponent, + LibraryTableComponent, + MaxLengthPipe, + SortableHeaderDirective, + AASTableComponent, + AASTreeComponent, + CustomerFeedbackComponent, + ScoreComponent, + DigitalNameplateComponent, + MessageTableComponent, + SecuredImageComponent + ], + providers: [] +}) +export class AASLibModule { } \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.actions.ts b/projects/aas-lib/src/lib/aas-table/aas-table.actions.ts new file mode 100644 index 00000000..3fb4a917 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.actions.ts @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from '@ngrx/store'; +import { AASDocument } from 'common'; +import { SortDirection } from '../sortable-header.directive'; +import { AASTableRow } from './aas-table.state'; +import { ViewMode } from '../types/view-mode'; + +export enum AASTableActionType { + UPDATE_ROWS = '[AASTable] Update Rows', + SET_VIEW_MODE = '[AASTable] Set view mode', + SET_SHOW_ALL = '[AASTable] Set show all', + SET_SORT_PARAMETER = '[AASTable] Set sort parameter', + SET_FILTER = '[AASTable] Set filter', + EXPAND = '[AASTable] Expand', + COLLAPSE = '[AASTable] Collapse', + TOGGLE_SELECTED = '[AASTable] Toggle selected', + TOGGLE_SELECTIONS = '[AASTable] Toggle selections' +} + +export const updateRows = createAction( + AASTableActionType.UPDATE_ROWS, + props<{ documents: AASDocument[] }>()); + +export const setViewMode = createAction( + AASTableActionType.SET_VIEW_MODE, + props<{ documents: AASDocument[]; viewMode: ViewMode }>()); + +export const setShowAll = createAction( + AASTableActionType.SET_SHOW_ALL, + props<{ documents: AASDocument[]; showAll: boolean }>()); + +export const setFilter = createAction( + AASTableActionType.SET_FILTER, + props<{ filter?: string }>()); + +export const setSortParameter = createAction( + AASTableActionType.SET_SORT_PARAMETER, + props<{ column: string; direction: SortDirection }>()); + +export const expandRow = createAction( + AASTableActionType.EXPAND, + props<{ row: AASTableRow }>()); + +export const collapseRow = createAction( + AASTableActionType.COLLAPSE, + props<{ row: AASTableRow }>()); + +export const toggleSelected = createAction( + AASTableActionType.TOGGLE_SELECTED, + props<{ row: AASTableRow }>()); + +export const toggleSelections = createAction( + AASTableActionType.TOGGLE_SELECTIONS); diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.component.html b/projects/aas-lib/src/lib/aas-table/aas-table.component.html new file mode 100644 index 00000000..fbd95601 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.component.html @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + +
+ + + + +
COLUMN_NAME
+
+
COLUMN_ID
+
+ + + + + {{row.name | max:60}} +
{{row.name | max:60}}
+
+
{{row.id | max:80}}
+
+ + + + + + + + + + + + + +
+
+
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+
+ +
+
+ {{row.name | max:60}} +
{{row.name | max:60}}
+
+
+
+
{{row.id | max:80}}
+
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.component.scss b/projects/aas-lib/src/lib/aas-table/aas-table.component.scss new file mode 100644 index 00000000..fe1a49b1 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.component.scss @@ -0,0 +1,15 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +th.th-w-icon { + width: 48px; +} + +th.th-w-checkbox { + width: 32px; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.component.ts b/projects/aas-lib/src/lib/aas-table/aas-table.component.ts new file mode 100644 index 00000000..08aa73d3 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.component.ts @@ -0,0 +1,170 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, OnDestroy, QueryList, SimpleChanges, ViewChildren } from '@angular/core'; +import { Router } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { AASDocument } from 'common'; +import { first, Observable, Subscription } from 'rxjs'; +import { TranslateService } from '@ngx-translate/core'; + +import { ViewMode } from '../types/view-mode'; +import { AASTable } from '../types/aas-table'; +import { AASTableRow, AASTableFeatureState } from './aas-table.state'; +import * as AASTableSelectors from './aas-table.selectors'; +import * as AASTableActions from './aas-table.actions'; +import { AASQuery } from '../types/aas-query-params'; +import { NotifyService } from '../notify/notify.service'; +import { ClipboardService } from '../clipboard.service'; +import { SortEvent, SortableHeaderDirective } from '../sortable-header.directive'; + +@Component({ + selector: 'fhg-aas-table', + templateUrl: './aas-table.component.html', + styleUrls: ['./aas-table.component.scss'] +}) +export class AASTableComponent implements AASTable, OnChanges, OnDestroy { + private readonly store: Store; + private readonly subscription: Subscription = new Subscription(); + private _filter = ''; + + constructor( + private readonly router: Router, + translate: TranslateService, + store: Store, + private readonly notify: NotifyService, + private readonly clipboard: ClipboardService + ) { + this.store = store as Store; + this.selectedDocuments = this.store.select(AASTableSelectors.selectSelectedDocuments); + this.someSelections = this.store.select(AASTableSelectors.selectSomeSelections); + this.rows = this.store.select(AASTableSelectors.selectRows(translate)); + } + + @ViewChildren(SortableHeaderDirective) + public headers!: QueryList; + + @Input() + public viewMode: ViewMode = ViewMode.List; + + @Input() + public showAll = false; + + @Input() + public filter: Observable | null = null; + + @Input() + public documents: Observable | null = null; + + public rows: Observable; + + public readonly selectedDocuments: Observable; + + public readonly someSelections: Observable; + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['documents']) { + this.documents?.subscribe(documents => this.documentsChanged(documents)); + } + + if (changes['filter'] && this.filter) { + this.subscription.add(this.filter.subscribe(filter => { + this.store.dispatch(AASTableActions.setFilter({ filter })); + })); + } + + const showAllChange = changes['showAll']; + if (showAllChange && this.showAll !== showAllChange.previousValue) { + this.documents?.pipe(first()) + .subscribe(documents => this.store.dispatch(AASTableActions.setShowAll({ + documents, + showAll: this.showAll + }))); + } + + const viewModeChange = changes['viewMode']; + if (viewModeChange && this.viewMode !== viewModeChange.previousValue) { + this.documents?.pipe(first()) + .subscribe(documents => this.store.dispatch(AASTableActions.setViewMode({ + documents, + viewMode: this.viewMode + }))); + } + } + + public ngOnDestroy(): void { + this.subscription.unsubscribe(); + } + + public expand(row: AASTableRow): void { + if (this.viewMode === ViewMode.Tree) { + this.store.dispatch(AASTableActions.expandRow({ row })); + } + } + + public collapse(row: AASTableRow): void { + if (this.viewMode === ViewMode.Tree) { + this.store.dispatch(AASTableActions.collapseRow({ row })); + } + } + + public canOpen(row: AASTableRow): boolean { + return row.document.content != null; + } + + public open(row: AASTableRow): void { + const query: AASQuery = { + id: row.document.id, + url: row.document.container + }; + + if (this._filter) { + query.search = this._filter.replace(/&&/, '||'); + } + + this.clipboard.set('AASQuery', query); + this.router.navigateByUrl('/aas?format=AASQuery'); + } + + public onSort({ column, direction }: SortEvent) { + this.headers.forEach(header => { + if (header.sortable !== column) { + header.direction = ''; + } + }); + + this.store.dispatch(AASTableActions.setSortParameter({ column, direction })); + } + + public getFormatIcon(row: AASTableRow): string { + switch (row.type) { + case 'opc': + return '/assets/resources/opcua.32.png'; + case 'http': + return '/assets/resources/aas.32.png'; + default: + return '/assets/resources/aasx.32.png'; + } + } + + public getToolTip(row: AASTableRow): string { + return `${row.document.container}, ${row.document.endpoint.address}`; + } + + public toggleSelected(row: AASTableRow): void { + this.store.dispatch(AASTableActions.toggleSelected({ row })); + } + + public toggleSelections(): void { + this.store.dispatch(AASTableActions.toggleSelections()); + } + + private documentsChanged(documents: AASDocument[]): void { + this.store.dispatch(AASTableActions.updateRows({ documents })); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.filter.ts b/projects/aas-lib/src/lib/aas-table/aas-table.filter.ts new file mode 100644 index 00000000..b8473414 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.filter.ts @@ -0,0 +1,319 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { trim, noop } from 'lodash-es'; +import { AASTableRow } from './aas-table.state'; +import { TranslateService } from '@ngx-translate/core'; +import { normalize } from '../convert'; +import { + AASDocument, + getModelTypeFromAbbreviation, + AASAbbreviation, + convertToString, + aas, + parseDate, + parseNumber, + convertFromString +} from 'common'; + +type Operator = '=' | '<' | '>' | '<=' | '>=' | '!='; + +interface Query { + modelType: aas.ModelType; + operator?: Operator; + name?: string; + value?: string | boolean; +} + +export class AASTableFilter { + constructor(private readonly translate: TranslateService) { + } + + public do(input: AASTableRow[], searchText: string): AASTableRow[] { + const output: AASTableRow[] = []; + let start = false; + try { + const set = new Set(); + if (typeof searchText === 'string') { + for (const or of this.splitOr(searchText)) { + let rows = [...input]; + for (const and of this.splitAnd(or)) { + if (and.length >= 3) { + start = true; + const expression = and.toLocaleLowerCase(this.translate.currentLang); + if (expression.startsWith('#')) { + rows = [...this.where(rows, this.parseExpression(expression))]; + } else { + rows = [...this.filter(rows, expression)]; + } + } + } + + for (const row of rows) { + if (!set.has(row)) { + output.push(row); + set.add(row); + } + } + } + } + } catch (error) { + noop(); + } + + return start ? output : input; + } + + private splitOr(s: string): string[] { + return s.split('||').map(item => item.trim()); + } + + private splitAnd(s: string): string[] { + return s.split('&&').map(item => item.trim()); + } + + private *filter(rows: AASTableRow[], expression: string): Generator { + for (const row of rows) { + if (row.type.toLocaleLowerCase(this.translate.currentLang).indexOf(expression) >= 0 || + row.name.toLocaleLowerCase(this.translate.currentLang).indexOf(expression) >= 0 || + row.id.toLocaleLowerCase(this.translate.currentLang).indexOf(expression) >= 0) { + yield row; + } + } + } + + private parseExpression(expression: string): Query | undefined { + let query: Query | undefined; + const index = expression.indexOf(':'); + const tuple = this.parseOperator(expression); + if (index >= 0) { + const modelType = getModelTypeFromAbbreviation(expression.substring(1, index) as AASAbbreviation); + if (modelType) { + query = { modelType: modelType }; + if (tuple) { + query.name = expression.substring(index + 1, tuple.index).trim(); + query.value = this.fromString(expression.substring(tuple.index + tuple.operator.length)); + query.operator = tuple.operator; + } else { + query.name = expression.substring(index + 1); + } + } + } else if (tuple) { + const modelType = getModelTypeFromAbbreviation(expression.substring(1, tuple.index) as AASAbbreviation); + if (modelType) { + query = { modelType: modelType }; + query.value = this.fromString(expression.substring(tuple.index + tuple.operator.length)); + query.operator = tuple.operator; + } + } else { + const modelType = getModelTypeFromAbbreviation(expression.substring(1) as AASAbbreviation); + if (modelType) { + query = { modelType: modelType }; + } + } + + return query; + } + + private parseOperator(expression: string): { index: number, operator: Operator } | undefined { + let index = expression.indexOf('<='); + if (index > 0) { + return { index: index, operator: '<=' }; + } + + index = expression.indexOf('>='); + if (index > 0) { + return { index: index, operator: '>=' }; + } + + index = expression.indexOf('!='); + if (index > 0) { + return { index: index, operator: '!=' }; + } + + index = expression.indexOf('='); + if (index > 0) { + return { index, operator: '=' }; + } + + index = expression.indexOf('>'); + if (index > 0) { + return { index, operator: '>' }; + } + + index = expression.indexOf('<'); + if (index > 0) { + return { index, operator: '<' }; + } + + return undefined + } + + private fromString(s: string): string | boolean { + s = s.trim(); + switch (s.toLowerCase()) { + case 'true': + return true; + case 'false': + return false; + default: + return trim(s, '\'"'); + } + } + + private *where(rows: AASTableRow[], query: Query | undefined): Generator { + for (const row of rows) { + if (!query || this.match(row.document, query)) { + yield row; + } + } + } + + private match(document: AASDocument, query: Query): boolean { + if (document.content) { + if (document.content.assetAdministrationShells.some(shell => this.any(shell, query))) { + return true; + } + + if (document.content.submodels.some(submodel => this.any(submodel, query))) { + return true; + } + } + + return false; + } + + private any(parent: aas.Referable, query: Query): boolean { + if (parent.modelType === query.modelType) { + if (this.containsString(parent.idShort, query.name)) { + if (!parent || !query.value) { + return true; + } + + if (this.matchValue(parent, query.value, query.operator)) { + return true; + } + } + } + + for (const child of this.getChildren(parent)) { + if (this.any(child, query)) { + return true; + } + } + + return false; + } + + private matchValue(referable: aas.Referable, value: string | boolean, operator?: Operator): boolean { + switch (referable.modelType) { + case 'Property': + return this.matchProperty(referable as aas.Property, value, operator); + case 'File': { + const fileName = normalize((referable as aas.File).value ?? ''); + return fileName ? this.containsString(fileName, value as string) : false; + } + case 'Entity': { + const entity = referable as aas.Entity; + return entity.globalAssetId ? this.containsString(entity.globalAssetId, value as string) : false; + } + case 'ReferenceElement': { + const referenceElement = referable as aas.ReferenceElement; + return referenceElement.value.keys.some(key => this.containsString(key.value, value as string)); + } + case 'MultiLanguageProperty': { + const langString = (referable as aas.MultiLanguageProperty).value; + return langString ? langString.some(item => item ? this.containsString(item.text, value as string) : false) : false; + } + default: + return false; + } + } + + private matchProperty(property: aas.Property, b: string | boolean, operator: Operator = '='): boolean { + const a = convertFromString(property.value, property.valueType); + if (typeof a === 'boolean') { + return (typeof b === 'boolean') && a === b; + } else if (typeof b === 'boolean') { + return false; + } + + if (typeof a === 'number') { + if (typeof b === 'string') { + const index = b.indexOf('...'); + const isDate = this.isDate(property.valueType); + if (index >= 0) { + let min: number; + let max: number; + if (isDate) { + min = parseDate(b.substring(0, index).trim(), this.translate.currentLang)?.getTime() ?? 0; + max = parseDate(b.substring(index + 3).trim(), this.translate.currentLang)?.getTime() ?? 0; + } else { + min = parseNumber(b.substring(0, index).trim(), this.translate.currentLang); + max = parseNumber(b.substring(index + 3).trim(), this.translate.currentLang); + } + + return typeof min === 'number' && typeof max === 'number' && a >= min && a <= max; + } else { + const d = isDate + ? parseDate(b, this.translate.currentLang)?.getTime() ?? 0 + : parseNumber(b, this.translate.currentLang); + + if (typeof d !== 'number') { + return false; + } + + switch (operator) { + case '<': + return a < d; + case '>': + return a > d; + case '>=': + return a >= d; + case '<=': + return a <= d; + case '!=': + return Math.abs(a - d) > 0.000001; + default: + return Math.abs(a - d) <= 0.000001; + } + } + } + + return false; + } + + return this.containsString(convertToString(a), b) || + this.containsString(convertToString(a, this.translate.currentLang), b); + } + + private containsString(a: string, b?: string): boolean { + return b == null || a.toLowerCase().indexOf(b.toLowerCase()) >= 0; + } + + private getChildren(parent: aas.Referable): aas.Referable[] { + switch (parent.modelType) { + case 'Submodel': + return (parent as aas.Submodel).submodelElements ?? []; + case 'SubmodelElementCollection': + return (parent as aas.SubmodelElementCollection).value ?? []; + default: + return []; + } + } + + private isDate(valueType: aas.DataTypeDefXsd): boolean { + switch (valueType) { + case 'xs:date': + case 'xs:dateTime': + return true; + default: + return false; + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.reducer.ts b/projects/aas-lib/src/lib/aas-table/aas-table.reducer.ts new file mode 100644 index 00000000..b25255fc --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.reducer.ts @@ -0,0 +1,320 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from '@ngrx/store'; +import { aas, AASDocument, getChildren } from 'common'; +import { ViewMode } from '../types/view-mode'; +import * as AASTableActions from './aas-table.actions'; +import { AASTableRow, AASTableState } from './aas-table.state'; +import { SortDirection } from '../sortable-header.directive'; + +interface Tuple { + targets: AASDocument[]; + current: AASDocument; + sources: AASDocument[]; +} + +const initialState: AASTableState = { + column: '', + direction: '', + rows: [], + viewMode: ViewMode.List, + showAll: false +}; + +export const aasTableReducer = createReducer( + initialState, + on( + AASTableActions.collapseRow, + (state, { row }) => collapseRow(state, row) + ), + on( + AASTableActions.expandRow, + (state, { row }) => expandRow(state, row) + ), + on( + AASTableActions.setSortParameter, + (state, { column, direction }) => setSortParameter(state, column, direction) + ), + on( + AASTableActions.toggleSelected, + (state, { row }) => toggleSelected(state, row) + ), + on( + AASTableActions.toggleSelections, + (state) => toggleSelections(state) + ), + on( + AASTableActions.updateRows, + (state, { documents }) => updateRows(state, documents) + ), + on( + AASTableActions.setViewMode, + (state, { documents, viewMode }) => setViewMode(state, documents, viewMode) + ), + on( + AASTableActions.setShowAll, + (state, { documents, showAll }) => setShowAll(state, documents, showAll) + ), + on( + AASTableActions.setFilter, + (state, { filter }) => setFilter(state, filter) + ) +); + +function updateRows(state: AASTableState, documents: AASDocument[]): AASTableState { + let rows: AASTableRow[]; + if (state.viewMode === ViewMode.List) { + rows = initList(documents, state.showAll); + } else { + rows = initTree(documents, state.showAll); + } + + return { ...state, rows }; +} + +function setViewMode(state: AASTableState, documents: AASDocument[], viewMode: ViewMode): AASTableState { + let rows: AASTableRow[]; + if (viewMode === ViewMode.List) { + rows = initList(documents, state.showAll); + } else { + rows = initTree(documents, state.showAll); + } + + return { ...state, rows, viewMode }; +} + +function setShowAll(state: AASTableState, documents: AASDocument[], showAll: boolean): AASTableState { + let rows: AASTableRow[]; + if (state.viewMode === ViewMode.List) { + rows = initList(documents, showAll); + } else { + rows = initTree(documents, showAll); + } + + return { ...state, rows, showAll }; +} + +function setFilter(state: AASTableState, filter?: string): AASTableState { + return { ...state, filter }; +} + +function initList(documents: ReadonlyArray, showAll: boolean): AASTableRow[] { + const rows: AASTableRow[] = []; + for (const document of documents) { + if (showAll || document.content !== undefined) { + const row = new AASTableRow( + document, + false, + document.idShort, + document.id, + document.endpoint.type, + false, + false, + 0, + -1, + -1); + + rows.push(row); + } + } + + return rows; +} + +function initTree(documents: AASDocument[], showAll: boolean): AASTableRow[] { + const rows: AASTableRow[] = []; + const map = new Map(); + for (const document of documents) { + if (showAll || document.content) { + map.set(document.id, { targets: [], current: document, sources: [] }); + } + } + + for (const entry of map) { + const env = entry[1].current.content; + if (env) { + for (const referable of where(env.submodels)) { + if (referable && referable.modelType === 'ReferenceElement') { + const tuple = map.get((referable as aas.ReferenceElement).value.keys[0].value); + if (tuple) { + entry[1].sources.push(tuple.current); + tuple.targets.push(entry[1].current); + } + } + } + } + } + + let previous: AASTableRow | null = null; + for (const entry of map) { + if (entry[1].targets.length === 0) { + const root = entry[1].current; + const row = new AASTableRow( + root, + false, + root.idShort, + root.id, + root.endpoint.type, + false, + entry[1].sources.length === 0, + 0, + -1, + -1 + ); + + if (previous) { + previous.nextSibling = rows.length - 1; + } + + rows.push(row); + + if (!row.isLeaf && entry[1].sources.length > 0) { + row.firstChild = rows.length; + traverse(root, rows, 1); + } + + previous = row; + } + } + + return rows; + + function* where(elements: aas.Referable[]): Generator { + const stack: aas.Referable[][] = []; + stack.push(elements); + while (stack.length > 0) { + const children = stack.pop() as aas.Referable[]; + for (const child of children) { + if (child.modelType === 'ReferenceElement') { + const value = child as aas.ReferenceElement; + if (value && value.value.keys.some(item => item.type === 'AssetAdministrationShell')) { + yield child; + } + } + + const children = getChildren(child); + if (children.length > 0) { + stack.push(children); + } + } + } + } + + function traverse(parent: AASDocument, rows: AASTableRow[], level: number): void { + let previous: AASTableRow | null = null; + for (const child of map.get(parent.id)!.sources) { + const tuple = map.get(child.id)!; + const row = new AASTableRow( + child, + false, + child.idShort, + child.id, + child.endpoint.type, + false, + tuple.sources.length === 0, + level, + -1, + -1 + ); + + rows.push(row); + if (previous) { + previous.nextSibling = rows.length - 1; + } + + if (tuple.sources.length > 0) { + row.firstChild = rows.length; + traverse(child, rows, level + 1); + } + + previous = row; + } + } +} + +function setSortParameter(state: AASTableState, column: string, direction: SortDirection): AASTableState { + return { ...state, column, direction }; +} + +function expandRow(state: AASTableState, row: AASTableRow): AASTableState { + const rows = [...state.rows]; + const index = rows.indexOf(row); + rows[index] = new AASTableRow( + row.document, + false, + row.name, + row.id, + row.type, + true, + row.isLeaf, + row.level, + row.firstChild, + row.nextSibling); + + return { ...state, rows }; +} + +function collapseRow(state: AASTableState, row: AASTableRow): AASTableState { + const rows = [...state.rows]; + const index = rows.indexOf(row); + rows[index] = new AASTableRow( + row.document, + false, + row.name, + row.id, + row.type, + false, + row.isLeaf, + row.level, + row.firstChild, + row.nextSibling); + + return { ...state, rows }; +} + +function toggleSelected(state: AASTableState, row: AASTableRow) { + const rows = [...state.rows]; + const index = rows.indexOf(row); + rows[index] = new AASTableRow( + row.document, + !row.selected, + row.name, + row.id, + row.type, + row.expanded, + row.isLeaf, + row.level, + row.firstChild, + row.nextSibling); + + return { ...state, rows } +} + +function toggleSelections(state: AASTableState) { + const value = !state.rows.some(row => row.selected); + const rows = [...state.rows]; + for (let index = 0; index < rows.length; ++index) { + const row = rows[index]; + if (row.selected !== value) { + rows[index] = new AASTableRow( + row.document, + !row.selected, + row.name, + row.id, + row.type, + row.expanded, + row.isLeaf, + row.level, + row.firstChild, + row.nextSibling); + } + } + + return { ...state, rows } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.selectors.ts b/projects/aas-lib/src/lib/aas-table/aas-table.selectors.ts new file mode 100644 index 00000000..0a6091ef --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.selectors.ts @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from "@ngrx/store"; +import { AASDocument } from "common"; +import { AASTableRow, AASTableFeatureState } from "./aas-table.state"; +import { AASTableFilter } from './aas-table.filter'; +import { ViewMode } from '../types/view-mode'; +import { TranslateService } from '@ngx-translate/core'; + +const getRows = (state: AASTableFeatureState) => state.aasTable.rows; +const getState = (state: AASTableFeatureState) => state.aasTable; + +export const selectState = createSelector(getState, state => state); + +export const selectSelectedDocuments = createSelector( + getRows, + (rows: AASTableRow[]): AASDocument[] => { + return rows.filter(row => row.selected).map(row => row.document); + }); + +export const selectSomeSelections = createSelector( + getRows, + (rows: AASTableRow[]): boolean => { + return rows.some(row => row.selected); + }); + +export const selectRows = (translate: TranslateService) => { + const filter = new AASTableFilter(translate); + + return createSelector(getState, state => { + if (state.viewMode === ViewMode.List) { + let rows: AASTableRow[]; + if (state.column === '' || state.direction === '') { + rows = state.rows; + } else if (state.direction === 'asc') { + rows = [...state.rows].sort((a, b) => compare(a, b, state.column, translate.currentLang)); + } else { + rows = [...state.rows].sort((a, b) => compare(b, a, state.column, translate.currentLang)); + } + + return state.filter ? filter.do(rows, state.filter) : rows; + } else { + const rows: AASTableRow[] = []; + for (const root of state.rows.filter(row => row.level === 0)) { + rows.push(...root.getExpanded(state.rows)); + } + + return rows; + } + }); +} + +function compare(a: AASTableRow, b: AASTableRow, column: string, language: string): number { + switch (column) { + case 'name': + return a.name.localeCompare(b.name, language, { sensitivity: 'accent' }); + case 'type': + return a.type.localeCompare(b.type, language, { sensitivity: 'accent' }); + case 'id': + return a.id.localeCompare(b.id, language, { sensitivity: 'accent' }); + case 'document': + return a.document.timeStamp < b.document.timeStamp + ? -1 + : a.document.timeStamp > b.document.timeStamp ? -1 : 0; + default: + return 0; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-table/aas-table.state.ts b/projects/aas-lib/src/lib/aas-table/aas-table.state.ts new file mode 100644 index 00000000..471df1cd --- /dev/null +++ b/projects/aas-lib/src/lib/aas-table/aas-table.state.ts @@ -0,0 +1,76 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, EndpointType } from "common"; +import { SortDirection } from "../sortable-header.directive"; +import { ViewMode } from '../types/view-mode'; + +export class AASTableRow { + constructor( + public readonly document: AASDocument, + public readonly selected: boolean, + public readonly name: string, + public readonly id: string, + public readonly type: EndpointType, + public readonly expanded: boolean, + public readonly isLeaf: boolean, + public readonly level: number, + public firstChild: number, + public nextSibling: number) { + } + + public get hasChildren(): boolean { + return this.firstChild >= 0; + } + + public getChildren(rows: AASTableRow[]): AASTableRow[] { + const children: AASTableRow[] = []; + if (this.firstChild >= 0) { + let child = rows[this.firstChild]; + children.push(child); + while (child.nextSibling >= 0) { + child = rows[child.nextSibling]; + children.push(child); + } + } + + return children; + } + + public getExpanded(rows: AASTableRow[]): AASTableRow[] { + return this.traverse(rows, this, [this]); + } + + private traverse(rows: AASTableRow[], row: AASTableRow, expanded: AASTableRow[]): AASTableRow[] { + if (row.firstChild >= 0 && row.expanded) { + let child = rows[row.firstChild]; + expanded.push(child); + this.traverse(rows, child, expanded); + while (child.nextSibling >= 0) { + child = rows[child.nextSibling]; + expanded.push(child); + this.traverse(rows, child, expanded); + } + } + + return expanded; + } +} + +export interface AASTableState { + column: string; + direction: SortDirection; + viewMode: ViewMode; + showAll: boolean; + filter?: string; + rows: AASTableRow[]; +} + +export interface AASTableFeatureState { + aasTable: AASTableState; +} diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree-api.service.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree-api.service.ts new file mode 100644 index 00000000..a295c9a7 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree-api.service.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { aas, AASDocument, AuthResult } from 'common'; +import { encodeBase64Url } from '../convert'; + +/** The client side AAS provider service. */ +@Injectable({ + providedIn: 'root' +}) +export class AASTreeApiService { + constructor( + private readonly http: HttpClient + ) { } + + public getTokenAsync(url: string): Promise { + return new Promise((result, reject) => { + let data: AuthResult; + this.http.post( + '/api/v1/login', + { id: url }).subscribe( + { + next: value => data = value, + complete: () => result(data.token), + error: (error) => reject(error) + }); + }); + } + + /** + * Calls an operation. + * @param document The document to which the operation belongs. + * @param operation The operation to call. + * @returns The result of the operation call. + */ + public invoke(document: AASDocument, operation: aas.Operation): Promise { + return new Promise((result, reject) => { + let data: aas.Operation; + this.http.post( + `/api/v1/containers/${encodeBase64Url(document.container)}/documents/${encodeBase64Url(document.id)}`, + operation).subscribe({ + next: (value) => data = value, + complete: () => result(data), + error: (error) => reject(error) + }); + }); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree-search.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree-search.ts new file mode 100644 index 00000000..00c34cf8 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree-search.ts @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from '@ngrx/store'; +import { TranslateService } from '@ngx-translate/core'; +import { trim } from 'lodash-es'; +import { Subscription } from 'rxjs'; +import { normalize } from '../convert'; +import * as AASTreeActions from './aas-tree.actions'; +import * as AASTreeSelectors from './aas-tree.selectors'; +import { AASTreeRow, SearchTerm, SearchQuery, Operator, AASTreeFeatureState } from './aas-tree.state'; +import { + aas, + AASAbbreviation, + convertFromString, + convertToString, + getModelTypeFromAbbreviation, + parseDate, + parseNumber +} from 'common'; +import { Injectable } from '@angular/core'; + +@Injectable() +export class AASTreeSearch { + private store: Store + private readonly loop = true; + private subscription = new Subscription(); + private terms: SearchTerm[] = []; + private rows: AASTreeRow[] = []; + private index = -1; + + constructor(store: Store, private translate: TranslateService) { + this.store = store as Store + + this.subscription.add(this.store.select(AASTreeSelectors.selectRows).pipe() + .subscribe(rows => { + this.rows = rows; + })); + + this.subscription.add(this.store.select(AASTreeSelectors.selectTerms).pipe() + .subscribe(terms => { + this.terms = terms; + this.findFirst(); + })); + + this.subscription.add(this.store.select(AASTreeSelectors.selectMatchIndex).pipe() + .subscribe((value) => this.index = value)); + } + + public destroy(): void { + this.subscription.unsubscribe(); + } + + public start(value: string) { + if (value) { + const terms: SearchTerm[] = []; + for (const expression of this.splitOr(value)) { + const term: SearchTerm = {}; + if (expression.length >= 3) { + if (expression.startsWith('#')) { + const query = this.parseExpression(expression); + if (query) { + term.query = query; + } + } else { + term.text = expression.toLocaleLowerCase(this.translate.currentLang); + } + } + + if (term.text || term.query) { + terms.push(term); + } + } + + if (terms.length > 0) { + this.store.dispatch(AASTreeActions.setSearchText({ terms })); + } else { + this.store.dispatch(AASTreeActions.setMatchIndex({ index: -1 })); + } + } + } + + public findNext(): boolean { + let completed = false; + if (this.rows.length > 0 && (this.terms.length > 0)) { + let match = false; + let i = this.index < 0 ? 0 : this.index + 1; + const start = i; + while (this.loop) { + if (this.match(this.rows[i])) { + match = true; + break; + } + + if (++i >= this.rows.length) { + i = 0; + completed = true; + } + + if (i === start) { + break; + } + } + + this.store.dispatch(AASTreeActions.setMatchIndex({ index: match ? i : -1 })); + } + + return completed; + } + + public findPrevious(): boolean { + let completed = false; + if (this.rows.length > 0 && (this.terms.length > 0)) { + let match = false; + let i = this.index <= 0 ? this.rows.length - 1 : this.index - 1; + const start = i; + while (this.loop) { + if (this.match(this.rows[i])) { + match = true; + break; + } + + if (--i <= 0) { + i = this.rows.length - 1; + completed = true; + } + + if (i === start) { + break; + } + } + + this.store.dispatch(AASTreeActions.setMatchIndex({ index: match ? i : -1 })); + } + + return completed; + } + + private splitOr(s: string): string[] { + return s.split('||').map(item => item.trim()); + } + + private findFirst(): void { + if (this.rows.length > 0 && (this.terms.length > 0)) { + let match = false; + let i = this.index < 0 ? 0 : this.index; + const start = i; + while (this.loop) { + if (this.match(this.rows[i])) { + match = true; + break; + } + + if (++i >= this.rows.length) { + i = 0; + } + + if (i === start) { + break; + } + } + + this.store.dispatch(AASTreeActions.setMatchIndex({ index: match ? i : -1 })); + } + } + + private parseExpression(expression: string): SearchQuery | null { + let query: SearchQuery | null = null; + const index = expression.indexOf(':'); + const tuple = this.parseOperator(expression); + if (index >= 0) { + const modelType = getModelTypeFromAbbreviation(expression.substring(1, index) as AASAbbreviation); + if (modelType) { + query = { modelType: modelType }; + if (tuple) { + query.name = expression.substring(index + 1, tuple.index).trim(); + query.value = this.fromString(expression.substring(tuple.index + tuple.operator.length)); + query.operator = tuple.operator; + } else { + query.name = expression.substring(index + 1); + } + } + } else if (tuple) { + const modelType = getModelTypeFromAbbreviation(expression.substring(1, tuple.index) as AASAbbreviation); + if (modelType) { + query = { modelType: modelType }; + query.value = this.fromString(expression.substring(tuple.index + tuple.operator.length)); + query.operator = tuple.operator; + } + } else { + const modelType = getModelTypeFromAbbreviation(expression.substring(1) as AASAbbreviation); + if (modelType) { + query = { modelType: modelType }; + } + } + + return query; + } + + private parseOperator(expression: string): { index: number, operator: Operator } | undefined { + let index = expression.indexOf('<='); + if (index > 0) { + return { index: index, operator: '<=' }; + } + + index = expression.indexOf('>='); + if (index > 0) { + return { index: index, operator: '>=' }; + } + + index = expression.indexOf('!='); + if (index > 0) { + return { index: index, operator: '!=' }; + } + + index = expression.indexOf('='); + if (index > 0) { + return { index, operator: '=' }; + } + + index = expression.indexOf('>'); + if (index > 0) { + return { index, operator: '>' }; + } + + index = expression.indexOf('<'); + if (index > 0) { + return { index, operator: '<' }; + } + + return undefined + } + + private fromString(s: string): string | boolean { + s = s.trim(); + switch (s.toLowerCase()) { + case 'true': + return true; + case 'false': + return false; + default: + return trim(s, '\'"'); + } + } + + private match(row: AASTreeRow): boolean { + let match = false; + for (const term of this.terms) { + if (term.query) { + if (row.element.modelType === term.query.modelType) { + if (term.query.name) { + if (this.containsString(row.name, term.query.name)) { + if (term.query.value) { + match = this.matchValue(row.element!, term.query.value, term.query.operator); + } else { + match = true; + } + } + } else if (term.query.value) { + match = this.matchValue(row.element!, term.query.value, term.query.operator); + } else { + match = true; + } + } + } else if (term.text) { + match = row.name.toLocaleLowerCase(this.translate.currentLang).indexOf(term.text) >= 0 || + row.typeInfo.toLocaleLowerCase(this.translate.currentLang).indexOf(term.text) >= 0 || + (typeof row.value === 'string' && + row.value.toLocaleLowerCase(this.translate.currentLang).indexOf(term.text) >= 0); + } + + if (match) { + break; + } + } + + return match; + } + + private containsString(a: string, b?: string): boolean { + return b == null || a.toLowerCase().indexOf(b.toLowerCase()) >= 0; + } + + private matchValue(referable: aas.Referable, value: string | boolean, operator?: Operator): boolean { + switch (referable.modelType) { + case 'Property': + return this.matchProperty(referable as aas.Property, value, operator); + case 'File': { + const fileName = normalize((referable as aas.File).value ?? ''); + return fileName ? this.containsString(fileName, value as string) : false; + } + case 'Entity': { + const entity = referable as aas.Entity; + return entity.globalAssetId ? this.containsString(entity.globalAssetId, value as string) : false; + } + case 'ReferenceElement': { + const referenceElement = referable as aas.ReferenceElement; + return referenceElement.value.keys.some(key => this.containsString(key.value, value as string)); + } + case 'MultiLanguageProperty': { + const langString = (referable as aas.MultiLanguageProperty).value; + return langString ? langString.some(item => item ? this.containsString(item.text, value as string) : false) : false; + } + default: + return false; + } + } + + private matchProperty(property: aas.Property, b: string | boolean, operator: Operator = '='): boolean { + const a = convertFromString(property.value, property.valueType); + if (typeof a === 'boolean') { + return (typeof b === 'boolean') && a === b; + } else if (typeof b === 'boolean') { + return false; + } + + if (typeof a === 'number') { + if (typeof b === 'string') { + const index = b.indexOf('...'); + const isDate = this.isDate(property.valueType); + if (index >= 0) { + let min: number; + let max: number; + if (isDate) { + min = parseDate(b.substring(0, index).trim(), this.translate.currentLang)?.getTime() ?? 0; + max = parseDate(b.substring(index + 3).trim(), this.translate.currentLang)?.getTime() ?? 0; + } else { + min = parseNumber(b.substring(0, index).trim(), this.translate.currentLang); + max = parseNumber(b.substring(index + 3).trim(), this.translate.currentLang); + } + + return typeof min === 'number' && typeof max === 'number' && a >= min && a <= max; + } else { + const d = isDate + ? parseDate(b, this.translate.currentLang)?.getTime() ?? 0 + : parseNumber(b, this.translate.currentLang); + + if (typeof d !== 'number') { + return false; + } + + switch (operator) { + case '<': + return a < d; + case '>': + return a > d; + case '>=': + return a >= d; + case '<=': + return a <= d; + case '!=': + return Math.abs(a - d) > 0.000001; + default: + return Math.abs(a - d) <= 0.000001; + } + } + } + + return false; + } + + return this.containsString(convertToString(a), b) || + this.containsString(convertToString(a, this.translate.currentLang), b); + } + + private isDate(valueType: aas.DataTypeDefXsd): boolean { + switch (valueType) { + case 'xs:date': + case 'xs:dateTime': + return true; + default: + return false; + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.actions.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree.actions.ts new file mode 100644 index 00000000..213e13d3 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.actions.ts @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from '@ngrx/store'; +import { AASDocument } from 'common'; +import { AASTreeRow, SearchTerm } from './aas-tree.state'; +import { TypedAction } from '@ngrx/store/src/models'; + +export enum AASTreeActionType { + UPDATE_ROWS = '[AASTree] Update Rows', + EXPAND_ROW = '[AASTree] Expand Row', + COLLAPSE_ROW = '[AASTree] Collapse Row', + COLLAPSE = '[AASTree] Collapse', + TOGGLE_SELECTED = '[AASTree] Toggle selected', + TOGGLE_SELECTIONS = '[AASTree] Toggle selections', + SET_SEARCH_TEXT = '[AASTree] set search test', + SET_MATCH_INDEX = '[AASTree] set match index', + SET_ROW_VALUE = '[AASTree] set blob value' +} + +export const updateRows = createAction( + AASTreeActionType.UPDATE_ROWS, + props<{ document: AASDocument | null; localeId: string }>()); + +export const expandRow = createAction( + AASTreeActionType.EXPAND_ROW, + props<{ arg: number | AASTreeRow }>()); + +export const collapseRow = createAction( + AASTreeActionType.COLLAPSE_ROW, + props<{ row: AASTreeRow }>()); + +export const collapse = createAction( + AASTreeActionType.COLLAPSE); + +export const toggleSelected = createAction( + AASTreeActionType.TOGGLE_SELECTED, + props<{ row: AASTreeRow }>()); + +export const toggleSelections = createAction( + AASTreeActionType.TOGGLE_SELECTIONS, + props<{ document: AASDocument | null }>()); + +export const setSearchText = createAction( + AASTreeActionType.SET_SEARCH_TEXT, + props<{ terms: SearchTerm[] }>()); + +export const setMatchIndex = createAction( + AASTreeActionType.SET_MATCH_INDEX, + props<{ index: number }>()); + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.component.html b/projects/aas-lib/src/lib/aas-tree/aas-tree.component.html new file mode 100644 index 00000000..99604b5d --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.component.html @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+
+ +
+ +
+
+
+ +
+ +
+ +
+
+
+
+ {{node.abbreviation}}
+
+ {{node.name}} +  [ + {{node.typeInfo}} + ] +
+
+ {{node.name}} +  [ + {{node.typeInfo}} + ] +
+
+
+
{{getValue(node)}}
+ + {{node.value}} +
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.component.scss b/projects/aas-lib/src/lib/aas-tree/aas-tree.component.scss new file mode 100644 index 00000000..1edd6619 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.component.scss @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +th.aas-tree-th-checkbox { + width: 32px; +} + +span.text-small { + font-size: small; +} + +div.w-1{ + width: 4px; +} + +div.w-4{ + width: 16px; +} + +div.w-9{ + width: 36px; +} + +div.h-1{ + height: 4px; +} + +div.h-4 { + height: 16px; +} + +div.wh-4 { + width: 16px; + height: 16px; +} diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.component.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree.component.ts new file mode 100644 index 00000000..5a5acfdf --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.component.ts @@ -0,0 +1,535 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, } from '@angular/core'; +import { BehaviorSubject, Subscription, Observable, first } from 'rxjs'; +import { WebSocketSubject } from 'rxjs/webSocket'; +import { Store } from '@ngrx/store'; +import { TranslateService } from '@ngx-translate/core'; +import { Router } from '@angular/router'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { + aas, + LiveNode, + LiveRequest, + WebSocketData, + AASDocument, + convertToString, + toLocale, + EndpointType, + selectSubmodel, + getIdShortPath, +} from 'common'; + +import { AASTreeRow, AASTreeFeatureState } from './aas-tree.state'; +import { OnlineState } from '../types/online-state'; +import { ShowImageFormComponent } from './show-image-form/show-image-form.component'; +import { ShowVideoFormComponent } from './show-video-form/show-video-form.component'; +import { OperationCallFormComponent } from './operation-call-form/operation-call-form.component'; +import { AASTreeSearch } from './aas-tree-search'; +import { AASTree } from '../types/aas-tree'; +import { basename, encodeBase64Url, mimeTypeToExtension } from '../convert'; +import { AASQuery } from '../types/aas-query-params'; +import { ViewQuery } from '../types/view-query-params'; +import { WindowService } from '../window.service'; +import { DocumentService } from '../document.service'; +import { DownloadService } from '../download.service'; +import { WebSocketFactoryService } from '../web-socket-factory.service'; +import { ClipboardService } from '../clipboard.service'; +import { LogType, NotifyService } from '../notify/notify.service'; +import { SubmodelViewDescriptor, resolveSemanticId, supportedSubmodelTemplates } from '../submodel-template/submodel-template'; +import * as AASTreeActions from './aas-tree.actions'; +import * as AASTreeSelectors from './aas-tree.selectors'; +import { AASTreeApiService } from './aas-tree-api.service'; + +interface PropertyValue { + property: aas.Property, + value: BehaviorSubject +} + +@Component({ + selector: 'fhg-aas-tree', + templateUrl: './aas-tree.component.html', + styleUrls: ['./aas-tree.component.scss'], + providers: [AASTreeSearch] +}) +export class AASTreeComponent implements AASTree, OnInit, OnChanges, OnDestroy { + private readonly store: Store; + private readonly liveNodes: LiveNode[] = []; + private readonly map = new Map(); + private readonly subscription = new Subscription(); + + private webSocketSubject?: WebSocketSubject; + + constructor( + private readonly router: Router, + store: Store, + private readonly api: AASTreeApiService, + private readonly searching: AASTreeSearch, + private readonly modal: NgbModal, + private readonly window: WindowService, + private readonly dom: DocumentService, + private readonly download: DownloadService, + private readonly translate: TranslateService, + private readonly notify: NotifyService, + private readonly webSocketFactory: WebSocketFactoryService, + private readonly clipboard: ClipboardService + ) { + this.store = store as Store; + this.nodes = this.store.select(AASTreeSelectors.selectNodes); + this.selectedElements = this.store.select(AASTreeSelectors.selectSelectedElements); + this.someSelected = this.store.select(AASTreeSelectors.selectSomeSelected); + } + + @Input() + public document: AASDocument | null = null; + + @Input() + public state: OnlineState | null = 'offline'; + + @Input() + public search: Observable | null = null; + + public get onlineReady(): boolean { + return this.document?.onlineReady ?? false; + } + + public get readonly(): boolean { + return this.document?.readonly ?? true; + } + + public get modified(): boolean { + return this.document?.modified ?? false; + } + + public someSelected: Observable; + + public selectedElements: Observable; + + public nodes: Observable; + + public ngOnInit(): void { + this.subscription.add(this.store.select(AASTreeSelectors.selectError).pipe().subscribe(error => { + if (error) { + this.notify.error(error); + } + })); + + this.subscription.add(this.store.select(AASTreeSelectors.selectMatchIndex).pipe().subscribe(index => { + if (index >= 0) { + this.store.dispatch(AASTreeActions.expandRow({ arg: index })); + } + })); + + this.subscription.add(this.store.select(AASTreeSelectors.selectMatchRow).pipe().subscribe(row => { + if (row) { + setTimeout(() => { + const element = this.dom.getElementById(row.id); + element?.scrollIntoView({ block: 'center', behavior: 'smooth' }); + }) + } + })); + + this.subscription.add(this.translate.onLangChange.subscribe(() => { + this.store.dispatch(AASTreeActions.updateRows({ + document: this.document, + localeId: this.translate.currentLang + })); + })); + } + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['document']) { + this.store.dispatch(AASTreeActions.updateRows({ + document: this.document, + localeId: this.translate.currentLang + })); + } + + if (changes['search'] && this.search) { + this.subscription.add(this.search.subscribe((value) => this.searching.start(value))); + } + + const stateChange = changes['state']; + if (stateChange) { + if (stateChange.previousValue !== stateChange.currentValue) { + if (this.state === 'online') { + this.goOnline(); + } else { + this.goOffline(); + } + } + } + } + + public ngOnDestroy(): void { + this.subscription.unsubscribe(); + this.webSocketSubject?.unsubscribe(); + this.searching?.destroy(); + } + + public visualState(node: AASTreeRow): string { + let state = ''; + if (node.selected) { + state = 'table-primary'; + if (node.highlighted) { + state += ' table-success'; + } + } else if (node.highlighted) { + state = 'table-success'; + } + + return state; + } + + public getValue(node: AASTreeRow): string | boolean | undefined { + if (this.state === 'online' && node.element.modelType === 'Property') { + const property = node.element as aas.Property; + let value: string | boolean; + const item = property.nodeId && this.map.get(property.nodeId); + if (item) { + value = item.value.getValue(); + } else { + value = this.getPropertyValue(property); + } + + return value; + } else { + return node.value; + } + } + + public expand(node: AASTreeRow): void { + if (!node.expanded) { + this.store.dispatch(AASTreeActions.expandRow({ arg: node })); + } + } + + public collapse(node?: AASTreeRow): void { + if (node) { + if (node.expanded) { + this.store.dispatch(AASTreeActions.collapseRow({ row: node })); + } + } else { + this.store.dispatch(AASTreeActions.collapse()); + } + } + + public toggleSelections(): void { + this.store.dispatch(AASTreeActions.toggleSelections({ document: this.document })); + } + + public toggleSelection(node: AASTreeRow): void { + this.store.dispatch(AASTreeActions.toggleSelected({ row: node })); + } + + public open(node: AASTreeRow): void { + try { + switch (node.element.modelType) { + case 'File': + this.openFileAsync(node.element as aas.File); + break; + case 'Blob': + this.openBlobAsync(node.element as aas.Blob); + break; + case 'Entity': + if (this.state === 'offline') { + this.openEntity(node.element); + } else { + this.notify.info('ToDo...'); + } + break; + case 'ReferenceElement': + if (this.state === 'offline') { + this.openReference(node.element); + } else { + this.notify.info('ToDo...'); + } + break; + case 'Operation': + this.callOperationAsync(node.element as aas.Operation); + break; + case 'Property': { + const property = node.element as aas.Property; + this.window.open(String(property.value)); + break; + } + case 'Submodel': + this.navigateToView(node.element as aas.Submodel); + break; + } + } catch (error) { + this.notify.error(error); + } + } + + public findNext(): void { + this.searching.findNext(); + } + + public findPrevious(): void { + this.searching.findPrevious(); + } + + private navigateToView(submodel: aas.Submodel): void { + const semanticId = resolveSemanticId(submodel); + if (semanticId) { + const template = supportedSubmodelTemplates.get(semanticId); + if (template && this.document) { + const descriptor: SubmodelViewDescriptor = { + template, + submodels: [{ + id: this.document.id, + url: this.document.container, + idShort: submodel.idShort + }] + }; + + this.clipboard.set('ViewQuery', { descriptor } as ViewQuery); + this.router.navigateByUrl('/view?format=ViewQuery'); + } + } + } + + private async openFileAsync(file: aas.File): Promise { + if (file.value) { + const { name, url } = this.resolveFile(file); + if (name && url) { + if (file.contentType.startsWith('image/')) { + await this.showImageAsync(name, url); + } else if (file.contentType.startsWith('video/')) { + await this.showVideoAsync(name, url); + } else if (file.contentType.endsWith('/pdf')) { + const token = await this.api.getTokenAsync(url); + this.window.open(url + '?access_token=' + token); + } else if (file) { + await this.downloadFileAsync(name, url); + } + } + } + } + + private async openBlobAsync(blob: aas.Blob): Promise { + if (blob.contentType && this.document && blob.parent) { + const extension = mimeTypeToExtension(blob.contentType); + if (extension) { + const name = blob.idShort + extension; + if (blob.value) { + if (blob.contentType.startsWith('image/')) { + await this.showImageAsync(name, `data:${blob.contentType};base64,${blob.value}`); + } else if (blob.contentType.startsWith('video/')) { + await this.showVideoAsync(name, `data:${blob.contentType};base64,${blob.value}`); + } + } else { + const container = encodeBase64Url(this.document.container); + const id = encodeBase64Url(this.document.id); + const smId = encodeBase64Url(blob.parent.keys[0].value); + const path = getIdShortPath(blob); + const url = `/api/v1/containers/${container}/documents/${id}/submodels/${smId}/blobs/${path}/value`; + if (blob.contentType.startsWith('image/')) { + await this.showImageAsync(name, url); + } else if (blob.contentType.startsWith('video/')) { + await this.showVideoAsync(name, url); + } else if (blob.contentType.endsWith('/pdf')) { + + this.window.open(url); + } else if (blob) { + await this.downloadFileAsync(name, url); + } + } + } + } + } + + private openEntity(element: aas.Referable): void { + const entity = element as aas.Entity; + if (entity && entity.globalAssetId) { + this.clipboard.set('AASQuery', { id: entity.globalAssetId } as AASQuery); + this.router.navigateByUrl('/aas?format=AASQuery'); + } + } + + private openReference(element: aas.Referable): void { + const referenceElement = element as aas.ReferenceElement; + if (referenceElement && referenceElement.value) { + this.clipboard.set('AASQuery', { id: referenceElement.value.keys[0].value } as AASQuery); + this.router.navigateByUrl('/aas?format=AASQuery'); + } + } + + private async showImageAsync(name: string, src: string): Promise { + try { + const modalRef = this.modal.open(ShowImageFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.name = name; + modalRef.componentInstance.image = src; + await modalRef.result; + } catch (error) { + if (error) { + this.notify.error(error); + } + } + } + + private async showVideoAsync(name: string, src: string): Promise { + try { + const modalRef = this.modal.open(ShowVideoFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.name = name; + modalRef.componentInstance.video = src; + await modalRef.result; + } catch (error) { + if (error) { + this.notify.error(error); + } + } + } + + private async downloadFileAsync(name: string, url: string): Promise { + try { + this.download.downloadFileAsync(url, name); + } catch (error) { + this.notify.error(error); + } + } + + private async callOperationAsync(operation: aas.Operation): Promise { + try { + if (operation) { + const modalRef = this.modal.open(OperationCallFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.document = this.document; + modalRef.componentInstance.operation = operation; + await modalRef.result; + } + } + catch (error) { + if (error) { + this.notify.error(error); + } + } + } + + private getPropertyValue(property: aas.Property): string | boolean { + if (typeof property.value === 'boolean') { + return property.value; + } else { + return toLocale(property.value, property.valueType, this.translate.currentLang) ?? '-'; + } + } + + private goOnline(): void { + try { + this.store.select(AASTreeSelectors.selectSelectedRows).pipe(first()).subscribe( + { + next: (rows) => { + this.prepareOnline(rows); + this.play(); + }, + error: () => this.stop() + } + ) + } + catch (error) { + this.stop(); + } + } + + private goOffline(): void { + this.stop(); + } + + private play(): void { + if (this.document) { + this.webSocketSubject = this.webSocketFactory.create(); + this.webSocketSubject.subscribe( + { + next: this.onMessage, + error: this.onError + } + ); + + this.webSocketSubject.next(this.createMessage( + this.document.endpoint.type, + this.document.container, + this.document.id)); + } + } + + private stop(): void { + if (this.webSocketSubject) { + this.webSocketSubject.unsubscribe(); + this.webSocketSubject = undefined; + } + } + + private prepareOnline(rows: AASTreeRow[]): void { + if (this.document) { + this.liveNodes.splice(0, this.liveNodes.length); + this.map.clear(); + for (const row of rows) { + if (row.selected) { + const property = row.element as aas.Property; + if (property.nodeId) { + this.liveNodes.push({ + nodeId: property.nodeId, + valueType: property.valueType ?? 'undefined' + }); + + const subject = new BehaviorSubject(this.getPropertyValue(property)); + this.map.set(property.nodeId, { property: property, value: subject }); + } + } + } + } + } + + private createMessage(type: EndpointType, url: string, id: string): WebSocketData { + return { + type: 'LiveRequest', + data: { + type: type, + url: url, + id: id, + nodes: this.liveNodes + } as LiveRequest + }; + } + + private onMessage = (data: WebSocketData): void => { + if (data.type === 'LiveNode[]') { + for (const node of data.data as LiveNode[]) { + const item = this.map.get(node.nodeId); + if (item) { + item.value.next( + typeof node.value === 'boolean' + ? node.value + : convertToString(node.value, this.translate.currentLang)); + } + } + } + } + + private onError = (error: any): void => { + this.notify.log(LogType.Error, error); + } + + private resolveFile(file: aas.File): { url?: string, name?: string } { + const value: { url?: string, name?: string } = {}; + if (this.document?.content && file.value) { + const submodel = selectSubmodel(this.document.content, file); + if (submodel) { + const smId = encodeBase64Url(submodel.id); + const path = getIdShortPath(file); + value.name = basename(file.value); + const url = encodeBase64Url(this.document.container); + const id = encodeBase64Url(this.document.id); + value.url = `/api/v1/containers/${url}/documents/${id}/submodels/${smId}/submodel-elements/${path}/value`; + } + } + + return value; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.reducer.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree.reducer.ts new file mode 100644 index 00000000..1fd6d827 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.reducer.ts @@ -0,0 +1,667 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { isEqual } from 'lodash-es'; +import { createReducer, on } from '@ngrx/store'; +import { + AASDocument, + convertToString, + getAbbreviation, + getLocaleValue, + aas, + isProperty, + isReferenceElement, + isIdentifiable, + selectReferable, + isBooleanType, + toLocale, + toBoolean +} from 'common'; + +import { AASTreeRow, AASTreeState, DisplayType, SearchTerm } from './aas-tree.state'; +import * as AASTreeActions from './aas-tree.actions'; +import { basename, normalize, mimeTypeToExtension } from '../convert'; + +const initialState: AASTreeState = { + rows: [], + index: -1, + terms: [], + error: null +}; + +export const aasTreeReducer = createReducer( + initialState, + on( + AASTreeActions.collapse, + (state) => collapse(state) + ), + on( + AASTreeActions.collapseRow, + (state, { row }) => collapseRow(state, row) + ), + on( + AASTreeActions.expandRow, + (state, { arg }) => expandRow(state, arg) + ), + on( + AASTreeActions.setMatchIndex, + (state, { index }) => setMatchIndex(state, index) + ), + on( + AASTreeActions.setSearchText, + (state, { terms }) => setSearchText(state, terms) + ), + on( + AASTreeActions.toggleSelected, + (state, { row }) => toggleSelected(state, row) + ), + on( + AASTreeActions.toggleSelections, + (state, { document }) => toggleSelections(state, document) + ), + on( + AASTreeActions.updateRows, + (state, { document, localeId }) => { + try { + return updateRows(state, document, localeId); + } catch (error) { + return { ...state, error }; + } + } + ) +); + +function updateRows(state: AASTreeState, document: AASDocument | null, localeId: string): AASTreeState { + const rows: AASTreeRow[] = []; + const env = document?.content; + if (env) { + for (const shell of env.assetAdministrationShells) { + const row = createRow(shell, -1, 0, true); + rows.push(row); + row.firstChild = hasChildren(shell) ? rows.length : -1; + traverse(shell, rows.length - 1, 1); + for (const stateRow of state.rows) { + if (stateRow.expanded || stateRow.selected) { + const row = findRow(rows, stateRow.element); + if (row) { + row.expanded = stateRow.expanded; + row.selected = stateRow.selected; + } + } + } + } + } + + return { ...state, rows, error: null }; + + function traverse( + element: aas.Referable, + parent: number, + level: number): void { + let previous: AASTreeRow | null = null; + for (const child of getChildren(element)) { + const row = createRow(child, parent, level, false); + rows.push(row); + if (previous) { + previous.nextSibling = rows.length - 1; + } + + const descendants = getChildren(child); + if (descendants.length > 0) { + row.firstChild = rows.length; + traverse(child, rows.length - 1, level + 1); + } + + previous = row; + } + } + + function hasChildren(referable: aas.Referable): boolean { + switch (referable.modelType) { + case 'AssetAdministrationShell': { + const shell = referable as aas.AssetAdministrationShell; + return shell.submodels != null && shell.submodels.length > 0; + } + case 'Submodel': { + const submodel = referable as aas.Submodel; + return submodel.submodelElements != null && submodel.submodelElements.length > 0; + } + case 'SubmodelElementCollection': { + const collection = referable as aas.SubmodelElementCollection; + return collection.value != null && collection.value.length > 0; + } + case 'SubmodelElementList': { + const list = referable as aas.SubmodelElementList; + return list.value != null && list.value.length > 0; + } + default: + return false; + } + } + + function getChildren(referable: aas.Referable): aas.Referable[] { + switch (referable.modelType) { + case 'AssetAdministrationShell': { + const shell = referable as aas.AssetAdministrationShell; + const children: aas.Referable[] = []; + if (shell.submodels) { + for (const reference of shell.submodels) { + const submodel = selectReferable(env!, reference); + if (submodel) { + children.push(submodel); + } + } + } + + return children; + } + case 'Submodel': + return (referable as aas.Submodel).submodelElements ?? []; + case 'SubmodelElementCollection': + return (referable as aas.SubmodelElementCollection).value ?? []; + case 'SubmodelElementList': + return (referable as aas.SubmodelElementList).value ?? []; + default: + return []; + } + } + + function createRow(element: aas.Referable, parent: number, level: number, expanded: boolean): AASTreeRow { + let valueType = DisplayType.undefined; + let isLeaf = true; + switch (element.modelType) { + case 'AssetAdministrationShell': + case 'Submodel': + case 'SubmodelElementCollection': + case 'SubmodelElementList': + isLeaf = false; + break; + case 'Property': + valueType = getPropertyDisplayType(element as aas.Property); + break; + case 'MultiLanguageProperty': + case 'Range': + valueType = DisplayType.Text; + break; + case 'Entity': + case 'ReferenceElement': + case 'Operation': + valueType = DisplayType.Url; + break; + case 'File': { + const file = element as aas.File; + valueType = file.contentType && file.value ? DisplayType.Url : DisplayType.Text; + break; + } + case 'Blob': { + const blob = element as aas.Blob; + valueType = blob.contentType ? DisplayType.Url : DisplayType.Text; + break; + } + } + + return new AASTreeRow( + `row_${rows.length + 1}`, + element, + expanded, + false, + false, + level, + getAbbreviation(element.modelType) ?? '', + element.idShort, + getTypeInfo(element), + getValue(element, localeId), + valueType, + isLeaf, + parent, + -1, + -1); + + function getPropertyDisplayType(property: aas.Property): DisplayType { + switch (property.valueType) { + case 'xs:anyURI': + return DisplayType.Url; + case 'xs:boolean': + return DisplayType.Boolean; + default: + return DisplayType.Text; + } + } + } + + function findRow(rows: AASTreeRow[], referable: aas.Referable): AASTreeRow | undefined { + return rows.find((row) => isEqual(createReference(row.element), createReference(referable))); + } + + function createReference(referable: aas.Referable): aas.Reference { + let keys: aas.Key[]; + if (referable.parent) { + keys = [...referable.parent.keys.map(key => ({ ...key })), + { + type: referable.modelType as aas.KeyTypes, + value: referable.idShort, + }]; + } else if (isIdentifiable(referable)) { + keys = [{ + type: referable.modelType as aas.KeyTypes, + value: referable.id, + }]; + } else { + throw new Error('Unexpected referable.'); + } + + return { type: 'ModelReference', keys }; + } +} + +function expandRow(state: AASTreeState, arg: number | AASTreeRow): AASTreeState { + const rows = [...state.rows]; + const ancestors: AASTreeRow[] = []; + let row = typeof arg === 'number' ? state.rows[arg] : arg; + if (!row.expanded) { + expand(row); + } + + let parentRow = row.parent >= 0 ? state.rows[row.parent] : null; + while (parentRow) { + if (parentRow.expanded) { + break; + } + + ancestors.push(parentRow); + row = parentRow; + parentRow = row.parent >= 0 ? state.rows[row.parent] : null; + } + + while (ancestors.length > 0) { + const row = ancestors.pop(); + if (!row) { + break; + } + + expand(row); + } + + return { ...state, rows, error: null }; + + function expand(row: AASTreeRow) { + const index = rows.indexOf(row); + rows[index] = new AASTreeRow( + row.id, + row.element, + true, + row.selected, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } +} + +function collapseRow(state: AASTreeState, row: AASTreeRow): AASTreeState { + const rows = [...state.rows]; + const index = rows.indexOf(row); + rows[index] = new AASTreeRow( + row.id, + row.element, + false, + row.selected, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + + return { ...state, rows, error: null }; +} + +function collapse(state: AASTreeState): AASTreeState { + const rows = state.rows.map((row, index) => { + if (index === 0) { + if (!row.expanded) { + return new AASTreeRow( + row.id, + row.element, + true, + row.selected, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } + } else if (!row.isLeaf && row.expanded) { + return new AASTreeRow( + row.id, + row.element, + false, + row.selected, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } + + return row; + }); + + return { ...state, rows, error: null }; +} + +function toggleSelected(state: AASTreeState, row: AASTreeRow): AASTreeState { + const rows = [...state.rows]; + const index = rows.indexOf(row); + rows[index] = new AASTreeRow( + row.id, + row.element, + row.expanded, + !row.selected, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + + return { ...state, rows, error: null }; +} + +function toggleSelections(state: AASTreeState, document: AASDocument | null): AASTreeState { + const value = !state.rows.some(row => row.selected); + const rows = state.rows.map(row => { + if (value) { + if (!row.selected && isSelectable(row, document)) { + return new AASTreeRow( + row.id, + row.element, + row.expanded, + true, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } + } else if (row.selected) { + return new AASTreeRow( + row.id, + row.element, + row.expanded, + false, + row.highlighted, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } + + return row; + }); + + return { ...state, rows, error: null }; + + function isSelectable(row: AASTreeRow, document: AASDocument | null): boolean { + return document != null && + (!document.readonly || + !document.modified && row.element.modelType === 'Property'); + } +} + +function getTypeInfo(referable: aas.Referable | null): string { + let value: string; + if (referable) { + switch (referable.modelType) { + case 'AssetAdministrationShell': + value = (referable as aas.Submodel).id; + break; + case 'Submodel': + value = `Semantic ID: ${referenceToString((referable as aas.Submodel).semanticId)}`; + break; + case 'SubmodelElementCollection': + value = (referable as aas.SubmodelElementCollection).value?.length.toString() ?? '0'; + break; + case 'SubmodelElementList': + value = (referable as aas.SubmodelElementList).value?.length.toString() ?? '0'; + break; + case 'Property': + value = (referable as aas.Property).valueType; + break; + case 'Range': + value = (referable as aas.Range).valueType; + break; + case 'File': + value = (referable as aas.File).contentType; + break; + case 'Blob': + value = (referable as aas.Blob).contentType; + break; + case 'MultiLanguageProperty': { + const mlp = referable as aas.MultiLanguageProperty; + value = ''; + if (mlp && Array.isArray(mlp.value)) { + value += `${mlp.value.map(item => item.language).join(', ')}`; + } + break; + } + case 'Entity': { + const entity = referable as aas.Entity; + value = ''; + if (entity?.globalAssetId) { + value = entity.globalAssetId; + } + break; + } + case 'Operation': { + const operation = referable as aas.Operation; + value = ''; + if (operation.inputVariables && operation.inputVariables.length > 0) { + value += '(' + operation.inputVariables.map(v => variableToString(v.value)).join(', ') + ')'; + } + + if (operation.outputVariables && operation.outputVariables.length === 1) { + value += `: ${variableToString(operation.outputVariables[0].value)}`; + } + else if (operation.outputVariables && operation.outputVariables.length > 1) { + value += ': {' + operation.outputVariables.map(v => variableToString(v.value)).join(', ') + '}'; + } + break; + } + default: + value = '-'; + break; + } + } else { + value = '-'; + } + + return value; + + function variableToString(value: aas.SubmodelElement): string { + if (isProperty(value)) { + return `${value.idShort}: ${value.valueType}`; + } + + if (isReferenceElement(value)) { + return `${value.idShort}: ${value?.value?.keys.map(key => key.value).join('/')}`; + } + + return `${value.idShort}: ${value.modelType}` + } + + function referenceToString(reference?: aas.Reference): string { + return reference?.keys.map(key => key.value).join('/') ?? '-'; + } +} + +function getValue(referable: aas.Referable | null, localeId: string): boolean | string | undefined { + if (referable) { + switch (referable.modelType) { + case 'Property': + return getPropertyValue(referable as aas.Property, localeId); + case 'Range': { + const range = referable as aas.Range; + return `${convertToString(range.min, localeId)} ... ${convertToString(range.max, localeId)}`; + } + case 'File': { + const file = referable as aas.File; + return file.value ? basename(normalize(file.value)) : '-'; + } + case 'Blob': { + const blob = referable as aas.Blob; + const extension = mimeTypeToExtension(blob.contentType) ?? ''; + return blob.contentType ? `${blob.idShort}${extension}` : '-'; + } + case 'ReferenceElement': + return (referable as aas.ReferenceElement).value.keys.map(item => item.value).join('/'); + case 'RelationshipElement': + return getRelationshipElementValue(referable as aas.RelationshipElement); + case 'MultiLanguageProperty': + return getLocaleValue((referable as aas.MultiLanguageProperty).value, localeId) ?? '-'; + case 'Entity': + return (referable as aas.Entity).globalAssetId ?? '-'; + default: + return '-'; + } + } + + return ''; + + function getPropertyValue(property: aas.Property, localeId: string): string | boolean | undefined { + if (isBooleanType(property.valueType)) { + return toBoolean(property.value); + } else { + return toLocale(property.value, property.valueType, localeId); + } + } + + function getRelationshipElementValue(relationship: aas.RelationshipElement): string { + const first = relationship.first.keys.map(key => key.value).join('/'); + const second = relationship.second.keys.map(key => key.value).join('/'); + return `1. ${first}; 2. ${second}`; + } + + function isDate(valueType: aas.DataTypeDefXsd): boolean { + switch (valueType) { + case 'xs:date': + case 'xs:dateTime': + return true; + default: + return false; + } + } +} + +function setSearchText(state: AASTreeState, terms: SearchTerm[]): AASTreeState { + return { ...state, index: -1, terms }; +} + +function setMatchIndex(state: AASTreeState, index: number): AASTreeState { + if (index >= 0) { + return { + ...state, + rows: updateHighlighted(index), + index: index, + error: null + }; + } else { + return { + rows: updateHighlighted(-1), + index: -1, + terms: [], + error: null + }; + } + + function updateHighlighted(index: number): AASTreeRow[] { + const rows = [...state.rows]; + for (let i = 0; i < rows.length; i++) { + const row = rows[i]; + if (i === index) { + rows[i] = new AASTreeRow( + row.id, + row.element, + row.expanded, + row.selected, + true, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } + else if (rows[i].highlighted) { + rows[i] = new AASTreeRow( + row.id, + row.element, + row.expanded, + row.selected, + false, + row.level, + row.abbreviation, + row.name, + row.typeInfo, + row.value, + row.displayType, + row.isLeaf, + row.parent, + row.firstChild, + row.nextSibling); + } + } + + return rows; + } +} diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.selectors.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree.selectors.ts new file mode 100644 index 00000000..543a8aae --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.selectors.ts @@ -0,0 +1,52 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from '@ngrx/store'; +import { AASTreeFeatureState } from './aas-tree.state'; + +const getState = (state: AASTreeFeatureState) => state.tree; +const getRows = (state: AASTreeFeatureState) => state.tree.rows; +const getIndex = (state: AASTreeFeatureState) => state.tree.index; +const getTerms = (state: AASTreeFeatureState) => state.tree.terms; +const getError = (state: AASTreeFeatureState) => state.tree.error; + +export const selectRows = createSelector(getRows, rows => rows); + +export const selectMatchIndex = createSelector(getIndex, index => index); + +export const selectMatchRow = createSelector(getState, state => { + return state.index >= 0 ? state.rows[state.index] : undefined; +}); + +export const selectTerms = createSelector(getTerms, terms => terms); + +export const selectError = createSelector(getError, error => error); + +export const selectRow = (index: number) => { + return createSelector(getRows, rows => rows[index]); +} + +export const selectNodes = createSelector( + getRows, + rows => rows.find(row => row.level === 0)?.getExpanded(rows) ?? [] +); + +export const selectSelectedElements = createSelector( + getRows, + rows => rows.filter(row => row.selected).map(item => item.element) +); + +export const selectSomeSelected = createSelector( + getRows, + rows => rows.some(row => row.selected) +); + +export const selectSelectedRows = createSelector( + getRows, + rows => rows.filter(row => row.selected) +); diff --git a/projects/aas-lib/src/lib/aas-tree/aas-tree.state.ts b/projects/aas-lib/src/lib/aas-tree/aas-tree.state.ts new file mode 100644 index 00000000..e44d3beb --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/aas-tree.state.ts @@ -0,0 +1,109 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, isSubmodel } from "common"; +import { resolveSemanticId, supportedSubmodelTemplates } from '../submodel-template/submodel-template'; + +export class AASTreeRow { + constructor( + public readonly id: string, + public readonly element: aas.Referable, + public expanded: boolean, + public selected: boolean, + public readonly highlighted: boolean, + public readonly level: number, + public readonly abbreviation: string, + public readonly name: string, + public readonly typeInfo: string, + public readonly value: string | boolean | undefined, + public readonly displayType: DisplayType, + public readonly isLeaf: boolean, + public readonly parent: number, + public firstChild: number, + public nextSibling: number) { + } + + public get hasChildren(): boolean { + return this.firstChild >= 0; + } + + public get hasSemantic(): boolean { + const referable = this.element; + if (isSubmodel(referable)) { + const sematicId = resolveSemanticId(referable); + return sematicId != null && supportedSubmodelTemplates.has(sematicId); + } + + return false; + } + + public getChildren(rows: AASTreeRow[]): AASTreeRow[] { + const children: AASTreeRow[] = []; + if (this.firstChild >= 0) { + let child = rows[this.firstChild]; + children.push(child); + while (child.nextSibling >= 0) { + child = rows[child.nextSibling]; + children.push(child); + } + } + + return children; + } + + public getExpanded(rows: AASTreeRow[]): AASTreeRow[] { + return this.traverse(rows, this, [this]); + } + + private traverse(rows: AASTreeRow[], row: AASTreeRow, expanded: AASTreeRow[]): AASTreeRow[] { + if (row.firstChild >= 0 && row.expanded) { + let child = rows[row.firstChild]; + expanded.push(child); + this.traverse(rows, child, expanded); + while (child.nextSibling >= 0) { + child = rows[child.nextSibling]; + expanded.push(child); + this.traverse(rows, child, expanded); + } + } + + return expanded; + } +} + +export enum DisplayType { + undefined = '', + Text = 'text', + Boolean = 'boolean', + Url = 'url' +} + +export interface SearchTerm { + text?: string, + query?: SearchQuery +} + +export type Operator = '=' | '<' | '>' | '<=' | '>=' | '!='; + +export interface SearchQuery { + modelType: aas.ModelType; + operator?: Operator; + name?: string; + value?: string | boolean; +} + +export interface AASTreeState { + rows: AASTreeRow[]; + index: number; + terms: SearchTerm[]; + error: unknown; +} + +export interface AASTreeFeatureState { + tree: AASTreeState; +} diff --git a/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.html b/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.html new file mode 100644 index 00000000..1678d89f --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.html @@ -0,0 +1,87 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.scss b/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.ts b/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.ts new file mode 100644 index 00000000..bbc31e94 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/operation-call-form/operation-call-form.component.ts @@ -0,0 +1,176 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { cloneDeep } from 'lodash-es'; +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { AASTreeApiService } from '../aas-tree-api.service'; +import { messageToString } from '../../convert'; +import { ERRORS } from '../../types/errors'; +import { + AASDocument, + getLocaleValue, + ApplicationError, + determineType, + getDefaultValue, + isBooleanType, + aas, + isProperty, + toInvariant, + convertToString, + toBoolean +} from 'common'; + +export interface Bla { + submodelElement: aas.SubmodelElement; + name: string; + description?: string; + type: aas.DataTypeDefXsd; + value: string | boolean; + inputType: 'text' | 'checkbox'; +} + +@Component({ + selector: 'fhg-operation-call', + templateUrl: './operation-call-form.component.html', + styleUrls: ['./operation-call-form.component.scss'] +}) +export class OperationCallFormComponent { + private _operation!: aas.Operation; + + constructor( + private modal: NgbActiveModal, + private translate: TranslateService, + private api: AASTreeApiService) { + } + + public name = ''; + + public document: AASDocument | null = null; + + public result: aas.Operation | null = null; + + public canCall = true; + + public get operation(): aas.Operation { + return this._operation; + } + + public set operation(value: aas.Operation) { + this._operation = cloneDeep(value); + try { + this.applyToView(this._operation.inputVariables, this.inputVariables); + this.applyToView(this._operation.outputVariables, this.outputVariables); + } catch (error) { + this.messages.push(messageToString(error, this.translate)); + this.canCall = false; + } + } + + public readonly inputVariables: Bla[] = []; + + public readonly outputVariables: Bla[] = []; + + public messages: string[] = []; + + public async call(): Promise { + if (this.document && this.canCall) { + this.messages = []; + + try { + this.result = await this.api.invoke(this.document, this.applyToModel()); + if (this.result && Array.isArray(this.result.outputVariables)) { + this.applyToView(this.result.inputVariables, this.inputVariables); + this.applyToView(this.result.outputVariables, this.outputVariables); + } + } catch (error) { + this.messages.push(messageToString(error, this.translate)); + } + } + } + + public close(): void { + this.modal.close(); + } + + private applyToModel(): aas.Operation { + for (const item of this.inputVariables) { + const element = item.submodelElement; + if (isProperty(element)) { + const value = typeof item.value === 'boolean' + ? item.value.toString() + : toInvariant(item.value, item.type, this.translate.currentLang); + + if (value == null) { + throw new ApplicationError( + `The expression '${element.value}' for the variable '${element.idShort}' cannot be converted to the type '${element.valueType}'`, + ERRORS.INVALID_OPERATION_VARIABLE_EXPRESSION, + element.value, + element.idShort, + element.valueType); + } + + element.value = value; + } else { + // ToDo: + } + } + + return this._operation; + } + + private applyToView(sources: aas.OperationVariable[] | undefined, targets: Bla[]): void { + targets.splice(0, targets.length); + if (sources) { + for (const sourceVariable of sources) { + if (sourceVariable.value.modelType === 'Property') { + const source = sourceVariable.value as aas.Property; + const inputType = isBooleanType(source.valueType) ? 'checkbox' : 'text'; + + let valueType: aas.DataTypeDefXsd | undefined; + if (source.valueType) { + valueType = source.valueType; + } else if (source.value) { + valueType = determineType(source.value); + } + + if (!valueType) { + throw new ApplicationError(`The data type of the variable "${source.idShort}" is undefined.`, + ERRORS.UNKNOWN_VARIABLE_VALUE_TYPE, + source.idShort); + } + + let value = source.value; + if (!value) { + value = convertToString(getDefaultValue(valueType), this.translate.currentLang); + } + + targets.push({ + submodelElement: source, + name: source.idShort, + description: getLocaleValue(source.descriptions), + type: valueType, + inputType: inputType, + value: inputType === 'checkbox' ? toBoolean(value) : value + }); + } else { + const source = sourceVariable.value; + targets.push({ + submodelElement: source, + name: source.idShort, + description: getLocaleValue(source.descriptions), + type: 'xs:string', + inputType: 'text', + value: 'not implemented' + }); + } + } + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.html b/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.html new file mode 100644 index 00000000..ba03567f --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.html @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.scss b/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.ts b/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.ts new file mode 100644 index 00000000..81ecd1c7 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/show-image-form/show-image-form.component.ts @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from "@angular/core"; +import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; + +@Component({ + selector: 'fhg-show-image', + templateUrl: './show-image-form.component.html', + styleUrls: ['./show-image-form.component.scss'] +}) +export class ShowImageFormComponent { + private readonly _modal: NgbActiveModal; + + constructor(modal: NgbActiveModal) { + this._modal = modal; + } + + public name!: string; + + public image!: string; + + public close(): void { + this._modal.close(); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.html b/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.html new file mode 100644 index 00000000..ef7c9422 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.html @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.scss b/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.ts b/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.ts new file mode 100644 index 00000000..a78c61d3 --- /dev/null +++ b/projects/aas-lib/src/lib/aas-tree/show-video-form/show-video-form.component.ts @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from "@angular/core"; +import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; + +@Component({ + selector: 'fhg-show-video', + templateUrl: './show-video-form.component.html', + styleUrls: ['./show-video-form.component.scss'] +}) +export class ShowVideoFormComponent { + private readonly _modal: NgbActiveModal; + + constructor(modal: NgbActiveModal) { + this._modal = modal; + } + + public name!: string; + + public video!: string; + + public close(): void { + this._modal.close(); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/auth-api.service.ts b/projects/aas-lib/src/lib/auth/auth-api.service.ts new file mode 100644 index 00000000..1de383ea --- /dev/null +++ b/projects/aas-lib/src/lib/auth/auth-api.service.ts @@ -0,0 +1,117 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { Credentials, UserProfile, Cookie, AuthResult } from 'common'; +import { encodeBase64Url } from '../convert'; + +@Injectable({ + providedIn: 'root', +}) +export class AuthApiService { + constructor( + private readonly http: HttpClient + ) { } + + public registerUserAsync(profile: UserProfile): Promise { + return new Promise((result, reject) => { + let data: AuthResult; + this.http.post( + '/api/v1/register', + profile).subscribe( + { + next: (value) => data = value, + complete: () => result(data), + error: (error) => reject(error) + }); + }); + } + + public guestAsync(): Promise { + return new Promise((result, reject) => { + let data: AuthResult; + this.http.post( + '/api/v1/guest', undefined).subscribe( + { + next: value => data = value, + complete: () => result(data), + error: (error) => reject(error) + }); + }); + } + + public loginAsync(credentials: Credentials): Promise { + return new Promise((result, reject) => { + let data: AuthResult; + this.http.post( + '/api/v1/login', + credentials).subscribe( + { + next: value => data = value, + complete: () => result(data), + error: (error) => reject(error) + }); + }); + } + + public updateProfileAsync(id: string, profile: UserProfile): Promise { + return new Promise((result, reject) => { + let data: AuthResult; + this.http.put( + `/api/v1/users/${encodeBase64Url(id)}`, + profile).subscribe( + { + next: (value) => data = value, + complete: () => result(data), + error: (error) => reject(error) + }); + }); + } + + public updateProfile(id: string, profile: UserProfile): Observable { + return this.http.put(`/api/v1/users/${encodeBase64Url(id)}`, profile); + } + + public deleteUserAsync(id: string): Promise { + return new Promise((result, reject) => { + this.http.delete( + `/api/v1/users/${encodeBase64Url(id)}`) + .subscribe({ + complete: () => result(), + error: (error) => reject(error) + }); + }); + } + + public resetPasswordAsync(id: string): Promise { + return new Promise((result, reject) => { + this.http.delete( + `/api/v1/users/${encodeBase64Url(id)}/reset`) + .subscribe({ + complete: () => result(), + error: (error) => reject(error) + }); + }); + } + + public getCookies(id: string): Observable { + return this.http.get(`/api/v1/users/${encodeBase64Url(id)}/cookies`); + } + + public setCookie(id: string, cookie: Cookie): Observable { + return this.http.post( + `/api/v1/users/${encodeBase64Url(id)}/cookies/${cookie.name}`, + cookie); + } + + public deleteCookie(id: string, name: string): Observable { + return this.http.delete(`/api/v1/users/${encodeBase64Url(id)}/cookies/${name}`); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/auth.component.html b/projects/aas-lib/src/lib/auth/auth.component.html new file mode 100644 index 00000000..e61ebc59 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/auth.component.html @@ -0,0 +1,24 @@ + + + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/auth.component.scss b/projects/aas-lib/src/lib/auth/auth.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/auth.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/auth/auth.component.ts b/projects/aas-lib/src/lib/auth/auth.component.ts new file mode 100644 index 00000000..c7b9c34b --- /dev/null +++ b/projects/aas-lib/src/lib/auth/auth.component.ts @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from "@angular/core"; +import { NotifyService } from "../notify/notify.service"; +import { AuthService } from "./auth.service"; + +@Component({ + selector: "fhg-auth", + templateUrl: "./auth.component.html", + styleUrls: ["./auth.component.scss"], +}) +export class AuthComponent { + constructor( + private auth: AuthService, + private notify: NotifyService) { } + + public get userAuthenticated(): boolean { + return this.auth.authenticated; + } + + public get userName(): string | undefined { + return this.auth.name; + } + + public async registerUser(): Promise { + try { + await this.auth.registerAsync(); + } catch (error) { + this.notify.error(error); + } + } + + public async loginUser(): Promise { + try { + await this.auth.loginAsync(); + } catch (error) { + this.notify.error(error); + } + } + + public async logoutUser(): Promise { + try { + await this.auth.logoutAsync(); + } catch (error) { + this.notify.error(error); + } + } + + public async updateUserProfile(): Promise { + try { + await this.auth.updateUserProfileAsync(); + } catch (error) { + this.notify.error(error); + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/auth.interceptor.ts b/projects/aas-lib/src/lib/auth/auth.interceptor.ts new file mode 100644 index 00000000..f8d1a627 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/auth.interceptor.ts @@ -0,0 +1,27 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +@Injectable() +export class AuthInterceptor implements HttpInterceptor { + public intercept(req: HttpRequest, next: HttpHandler): Observable> { + const token = localStorage.getItem('.Token'); + if (token) { + const cloned = req.clone({ + headers: req.headers.set('Authorization', 'Bearer ' + token) + }); + + return next.handle(cloned); + } else { + return next.handle(req); + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/auth.service.ts b/projects/aas-lib/src/lib/auth/auth.service.ts new file mode 100644 index 00000000..1db7e125 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/auth.service.ts @@ -0,0 +1,330 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { BehaviorSubject, EMPTY, last, map, mergeMap, Observable } from 'rxjs'; +import jwtDecode from 'jwt-decode'; +import { + ApplicationError, + Credentials, + isUserAuthorized, + stringFormat, + UserProfile, + UserRole, + JWTPayload, + toBoolean +} from 'common'; + +import { NotifyService } from '../notify/notify.service'; +import { ERRORS } from '../types/errors'; +import { LoginFormComponent, LoginFormResult } from '../auth/login-form/login-form.component'; +import { ProfileFormComponent, ProfileFormResult } from '../auth/profile-form/profile-form.component'; +import { RegisterFormComponent, RegisterFormResult } from '../auth/register-form/register-form.component'; +import { AuthApiService } from './auth-api.service'; +import { WindowService } from '../window.service'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + private readonly $payload = new BehaviorSubject({ role: 'guest' }); + private readonly cookies = new Map(); + + constructor( + private modal: NgbModal, + private translate: TranslateService, + private api: AuthApiService, + private notify: NotifyService, + private window: WindowService + ) { + this.payload = this.$payload.asObservable(); + + const stayLoggedIn = toBoolean(this.window.getLocalStorageItem('.StayLoggedIn')); + let token = this.window.getLocalStorageItem('.Token'); + if (stayLoggedIn && token) { + if (this.isValid(token)) { + this.nextPayload(token); + } else { + token = null; + } + } + + if (!token) { + this.loginAsGuestAsync().catch(error => notify.error(error)); + } + } + + /** The e-mail of the current user. */ + public get userId(): string | undefined { + return this.$payload.getValue()?.sub; + } + + /** The name or alias of the current user. */ + public get name(): string | undefined { + return this.$payload.getValue()?.name ?? this.translate.instant('GUEST_USER'); + } + + /** The current user role. */ + public get role(): UserRole { + return this.$payload.getValue()?.role ?? 'guest'; + } + + /** Indicates whether the current user is authenticated. */ + public get authenticated(): boolean { + const payload = this.$payload.getValue(); + return payload.sub != null && (payload.role === 'editor' || payload.role === 'admin'); + } + + /** The current active JSON web token. */ + public readonly payload: Observable; + + /** + * User login. + * @param credentials The credentials. + */ + public async loginAsync(credentials?: Credentials): Promise { + if (credentials) { + const result = await this.api.loginAsync(credentials); + this.nextPayload(result.token); + } else { + const modalRef = this.modal.open(LoginFormComponent, { backdrop: 'static', animation: true, keyboard: true }); + const stayLoggedIn = toBoolean(this.window.getLocalStorageItem('.StayLoggedIn')); + const token = this.window.getLocalStorageItem('.Token'); + if (stayLoggedIn && token) { + modalRef.componentInstance.stayLoggedIn = stayLoggedIn; + } + + const result: LoginFormResult = await modalRef.result; + if (result != null) { + if (result.token) { + this.nextPayload(result.token); + if (result.stayLoggedIn) { + this.window.setLocalStorageItem('.StayLoggedIn', 'true'); + } else if (stayLoggedIn) { + this.window.removeLocalStorageItem('.StayLoggedIn'); + } + } else if (result.action === 'register') { + await this.registerAsync(); + } + } + } + } + + /** + * Ensures that the current user has the expected rights. + * @param role The expected user role. + */ + public async ensureAuthorizedAsync(role: UserRole): Promise { + if (!this.isAuthorized(role)) { + await this.loginAsync(); + if (!this.isAuthorized(role)) { + throw new ApplicationError('Unauthorized access.', ERRORS.UNAUTHORIZED_ACCESS); + } + } + } + + /** Logs out the current user. */ + public async logoutAsync(): Promise { + if (!this.userId) { + throw new Error('Invalid operation.'); + } + + await this.loginAsGuestAsync(); + } + + /** + * Registers a new user. + * @param profile The profile of the new user. + */ + public async registerAsync(profile?: UserProfile): Promise { + if (profile) { + const result = await this.api.registerUserAsync(profile); + this.nextPayload(result.token); + } else { + const modalRef = this.modal.open( + RegisterFormComponent, { + backdrop: 'static', + animation: true, + keyboard: true + }); + + const result: RegisterFormResult = await modalRef.result; + if (result) { + this.nextPayload(result.token); + if (result.stayLoggedIn) { + this.window.setLocalStorageItem('.StayLoggedIn', 'true'); + } else { + this.window.removeLocalStorageItem('.StayLoggedIn'); + } + } + } + } + + /** + * Updates the profile of the current user. + * @param profile The updated user profile. + */ + public async updateUserProfileAsync(profile?: UserProfile): Promise { + const payload = this.$payload.getValue(); + if (!payload || !payload.sub || !payload.name) { + throw new Error('Invalid operation.'); + } + + if (profile) { + const result = await this.api.updateProfileAsync(payload.sub, profile); + this.nextPayload(result.token); + } else { + profile = { id: payload.sub, name: payload.name }; + const form = this.modal.open( + ProfileFormComponent, { + backdrop: 'static', + animation: true, + keyboard: true + }); + + form.componentInstance.initialize(profile); + const result: ProfileFormResult = await form.result; + if (result) { + if (result.token) { + this.nextPayload(result.token); + } else if (result.action === 'deleteUser') { + const message = stringFormat(this.translate.instant('CMD_DELETE_USER'), this.userId); + if (this.window.confirm(message)) { + await this.deleteUserAsync(); + } + } + } + } + } + + /** + * Deletes the account of the current authenticated user. + */ + public async deleteUserAsync(): Promise { + const payload = this.$payload.getValue(); + if (!payload || !payload.sub || !payload.name) { + throw new Error('Invalid operation'); + } + + await this.api.deleteUserAsync(payload.sub); + await this.loginAsGuestAsync(); + } + + /** + * Determines whether the current user is authorized for the specified roles. + * @param expected The expected role, the current user must have. + */ + public isAuthorized(expected: UserRole): boolean { + return isUserAuthorized(this.role, expected); + } + + /** + * Indicates whether a cookie with the specified name exists. + * @param name The cookie name. + * @returns `true` if the cookie exists; otherwise, `false`. + */ + public checkCookie(name: string): boolean { + if (this.authenticated) { + return this.cookies.has(name); + } + + return this.window.getLocalStorageItem(name) != null; + } + + /** + * Gets the value of the cookie with the specified name. + * @param name The cookie name. + * @returns The cookie value. + */ + public getCookie(name: string): string | null { + let data: string | null; + const payload = this.$payload.getValue(); + if (payload) { + data = this.cookies.get(name) ?? null; + } else { + data = this.window.getLocalStorageItem(name); + } + + return data; + } + + /** + * Sets the value of the cookie with the specified name. + * @param name The cookie name. + * @param data The cookie value. + */ + public setCookie(name: string, data: string): void { + const payload = this.$payload.getValue(); + if (payload && payload.sub) { + const id = payload.sub; + this.api.setCookie(id, { name, data }).pipe( + last(), + mergeMap(() => this.api.getCookies(id))).subscribe( + { + next: (cookies) => cookies.forEach(cookie => this.cookies.set(cookie.name, cookie.data)), + error: (error) => this.notify.error(error) + }); + } else { + this.window.setLocalStorageItem(name, data); + } + } + + /** + * Deletes the cookie with the specified name. + * @param name The cookie name. + */ + public deleteCookie(name: string): Observable { + const payload = this.$payload.getValue(); + if (payload && payload.sub) { + const id = payload.sub; + return this.api.deleteCookie(id, name).pipe( + mergeMap(() => { + const values = this.api.getCookies(id); + return values; + }), + map(cookies => { + this.cookies.clear(); + cookies.forEach(cookie => this.cookies.set(cookie.name, cookie.data)); + })); + } else { + this.window.removeLocalStorageItem(name); + return EMPTY; + } + } + + private async loginAsGuestAsync(): Promise { + this.window.removeLocalStorageItem('.Token'); + this.window.removeLocalStorageItem('.StayLoggedIn'); + const result = await this.api.guestAsync(); + this.nextPayload(result.token); + } + + private isValid(token: string): boolean { + try { + const value = jwtDecode(token) as JWTPayload; + return value.exp == null || (Date.now() / 1000 < value.exp); + } catch (error) { + return false; + } + } + + private nextPayload(token: string): void { + this.window.setLocalStorageItem('.Token', token); + const payload = jwtDecode(token) as JWTPayload; + this.$payload.next(payload); + this.cookies.clear(); + if (payload.sub) { + this.api.getCookies(payload.sub).subscribe({ + next: (cookies) => cookies.forEach(cookie => this.cookies.set(cookie.name, cookie.data)), + error: (error) => this.notify.error(error) + }); + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/login-form/login-form.component.html b/projects/aas-lib/src/lib/auth/login-form/login-form.component.html new file mode 100644 index 00000000..82a592dc --- /dev/null +++ b/projects/aas-lib/src/lib/auth/login-form/login-form.component.html @@ -0,0 +1,48 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/login-form/login-form.component.scss b/projects/aas-lib/src/lib/auth/login-form/login-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/login-form/login-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/auth/login-form/login-form.component.ts b/projects/aas-lib/src/lib/auth/login-form/login-form.component.ts new file mode 100644 index 00000000..c2e5d3e0 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/login-form/login-form.component.ts @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { AuthResult, Credentials, isValidEMail, isValidPassword, stringFormat } from 'common'; +import { isEmpty } from 'lodash-es'; + +import { messageToString } from '../../convert'; +import { ERRORS } from '../../types/errors'; +import { INFO } from '../../types/info'; +import { MessageEntry } from '../../types/message-entry'; +import { AuthApiService } from '../auth-api.service'; + +export interface LoginFormResult { + action?: string; + stayLoggedIn?: boolean; + token?: string; +} + +@Component({ + selector: 'fhg-login', + templateUrl: './login-form.component.html', + styleUrls: ['./login-form.component.scss'] +}) +export class LoginFormComponent { + private newPasswordSent = false; + + constructor( + private modal: NgbActiveModal, + private translate: TranslateService, + private api: AuthApiService) { } + + public passwordPerEMail = false; + + public userId = ''; + + public password = ''; + + public stayLoggedIn = false; + + public messages: MessageEntry[] = []; + + public async resetPassword(): Promise { + this.clearMessages(); + if (!this.newPasswordSent) { + if (isEmpty(this.userId)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.EMAIL_REQUIRED))); + } else if (!isValidEMail(this.userId)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.INVALID_EMAIL))); + } else { + try { + this.pushMessage(stringFormat(this.translate.instant(INFO.NEW_PASSWORD_SENT), this.userId), 'bg-info w-100'); + } catch (error) { + this.pushMessage(messageToString(error, this.translate)); + } finally { + this.newPasswordSent = true; + } + } + } + } + + public registerUser(): void { + this.modal.close({ action: "register" } as LoginFormResult); + } + + public async submit(): Promise { + try { + this.clearMessages(); + if (isEmpty(this.userId)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.EMAIL_REQUIRED))); + } else if (!isValidEMail(this.userId)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.INVALID_EMAIL))); + } else if (isEmpty(this.password)) { + this.pushMessage(this.translate.instant(ERRORS.PASSWORD_REQUIRED)); + } else if (!isValidPassword(this.password)) { + this.pushMessage(this.translate.instant(ERRORS.INVALID_PASSWORD)); + } else { + const credentials: Credentials = { id: this.userId, password: this.password }; + const loginResult: AuthResult = await this.api.loginAsync(credentials); + const result: LoginFormResult = { + stayLoggedIn: this.stayLoggedIn, + token: loginResult.token + }; + + this.modal.close(result); + } + } + catch (error) { + this.pushMessage(messageToString(error, this.translate)); + } + } + + public cancel(): void { + this.modal.close(); + } + + private pushMessage(text: string, type = 'bg-danger w-100'): void { + this.messages = [{ + text: text, + classname: type, + autohide: false, + delay: 0 + }]; + } + + private clearMessages(): void { + this.messages = []; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.html b/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.html new file mode 100644 index 00000000..72b7e078 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.html @@ -0,0 +1,57 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.scss b/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.ts b/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.ts new file mode 100644 index 00000000..5284be39 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/profile-form/profile-form.component.ts @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { isEmpty } from 'lodash-es'; +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { getUserNameFromEMail, isValidEMail, isValidPassword, stringFormat, UserProfile } from 'common'; +import { messageToString } from '../../convert'; +import { ERRORS } from '../../types/errors'; +import { AuthApiService } from '../auth-api.service'; + +export interface ProfileFormResult { + action?: string; + token?: string; +} + +@Component({ + selector: 'fhg-profile', + templateUrl: './profile-form.component.html', + styleUrls: ['./profile-form.component.scss'] +}) +export class ProfileFormComponent { + private profile?: UserProfile; + + constructor( + private modal: NgbActiveModal, + private translate: TranslateService, + private api: AuthApiService + ) { } + + public id = ''; + + public name = ''; + + public defaultName = 'name'; + + public password1 = ''; + + public password2 = ''; + + public isCollapsed = true; + + public messages: string[] = []; + + public initialize(profile: UserProfile): void { + this.profile = profile; + + this.id = profile.id; + this.name = profile.name; + } + + public onInputEMail(): void { + this.defaultName = getUserNameFromEMail(this.id); + } + + public deleteUser(): void { + const result: ProfileFormResult = { action: 'deleteUser' }; + this.modal.close(result); + } + + public submit(): void { + this.clearMessages(); + if (isEmpty(this.id)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.EMAIL_REQUIRED))); + } else if (!isValidEMail(this.id)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.INVALID_EMAIL))); + } else if (!isEmpty(this.password1)) { + if (!isValidPassword(this.password1)) { + this.pushMessage(this.translate.instant(ERRORS.INVALID_PASSWORD)); + } else if (this.password1 !== this.password2) { + this.pushMessage(this.translate.instant(ERRORS.PASSWORDS_NOT_EQUAL)); + } + } + + if (this.messages.length === 0 && this.profile) { + const newProfile: UserProfile = { + id: this.id, + name: this.name ?? getUserNameFromEMail(this.id), + password: this.password1 + }; + + this.api.updateProfile(this.profile.id, newProfile).subscribe({ + next: (value) => { + const result: ProfileFormResult = { token: value.token }; + this.modal.close(result); + }, + error: (error) => { + this.pushMessage(messageToString(error, this.translate)); + } + }); + } + } + + public cancel(): void { + this.modal.close(); + } + + private pushMessage(message: string): void { + this.messages = [message] + } + + private clearMessages(): void { + this.messages = []; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/register-form/register-form.component.html b/projects/aas-lib/src/lib/auth/register-form/register-form.component.html new file mode 100644 index 00000000..583d2daa --- /dev/null +++ b/projects/aas-lib/src/lib/auth/register-form/register-form.component.html @@ -0,0 +1,51 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/auth/register-form/register-form.component.scss b/projects/aas-lib/src/lib/auth/register-form/register-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/auth/register-form/register-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/auth/register-form/register-form.component.ts b/projects/aas-lib/src/lib/auth/register-form/register-form.component.ts new file mode 100644 index 00000000..5426a32b --- /dev/null +++ b/projects/aas-lib/src/lib/auth/register-form/register-form.component.ts @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { isEmpty } from 'lodash-es'; +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { isValidEMail, isValidPassword, stringFormat, UserProfile, getUserNameFromEMail } from 'common'; +import { TranslateService } from '@ngx-translate/core'; + +import { AuthApiService } from '../auth-api.service'; +import { ERRORS } from '../../types/errors'; +import { messageToString } from '../../convert'; + +export interface RegisterFormResult { + stayLoggedIn: boolean; + token: string; +} + +@Component({ + selector: 'fhg-register', + templateUrl: './register-form.component.html', + styleUrls: ['./register-form.component.scss'], +}) +export class RegisterFormComponent { + constructor( + private modal: NgbActiveModal, + private translate: TranslateService, + private api: AuthApiService) { } + + public userId = ''; + + public name = ''; + + public defaultName = 'name'; + + public password1 = ''; + + public password2 = ''; + + public stayLoggedIn = false; + + public passwordAsEMail = false; + + public messages: string[] = []; + + public onInputEMail(): void { + this.defaultName = getUserNameFromEMail(this.userId); + } + + public async submit(): Promise { + try { + this.clearMessages(); + if (isEmpty(this.userId)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.EMAIL_REQUIRED))); + } else if (!isValidEMail(this.userId)) { + this.pushMessage(stringFormat(this.translate.instant(ERRORS.INVALID_EMAIL))); + } else if (!this.passwordAsEMail) { + if (isEmpty(this.password1)) { + this.pushMessage(this.translate.instant(ERRORS.PASSWORD_REQUIRED)); + } else if (!isValidPassword(this.password1)) { + this.pushMessage(this.translate.instant(ERRORS.INVALID_PASSWORD)); + } else if (this.password1 !== this.password2) { + this.pushMessage(this.translate.instant(ERRORS.PASSWORDS_NOT_EQUAL)); + } + } + + if (this.messages.length === 0) { + const profile: UserProfile = { + id: this.userId, + name: this.name ?? getUserNameFromEMail(this.userId), + password: this.password1 + }; + + let result: RegisterFormResult | undefined; + const token = (await this.api.registerUserAsync(profile)).token; + if (!this.passwordAsEMail) { + result = { + stayLoggedIn: this.stayLoggedIn, + token + }; + + this.modal.close(result); + } + } + } + catch (error) { + this.pushMessage(messageToString(error, this.translate)); + } + } + + public cancel(): void { + this.modal.close(); + } + + private pushMessage(message: string): void { + this.messages = [message] + } + + private clearMessages(): void { + this.messages = []; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/clipboard.service.ts b/projects/aas-lib/src/lib/clipboard.service.ts new file mode 100644 index 00000000..8747f6ad --- /dev/null +++ b/projects/aas-lib/src/lib/clipboard.service.ts @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class ClipboardService { + private readonly data = new Map(); + + public contains(format?: string): boolean { + return format ? this.data.has(format) : this.data.size > 0; + } + + public get(format: string): T { + return this.data.get(format); + } + + public set(format: string, data: any): void { + this.data.set(format, data); + } + + public clear(format?: string): void { + if (format) { + this.data.delete(format); + } + else { + this.data.clear(); + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/convert.ts b/projects/aas-lib/src/lib/convert.ts new file mode 100644 index 00000000..a0a3d7d7 --- /dev/null +++ b/projects/aas-lib/src/lib/convert.ts @@ -0,0 +1,266 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpErrorResponse } from "@angular/common/http"; +import { TranslateService } from "@ngx-translate/core"; +import { ApplicationError, ErrorData, stringFormat } from "common"; +import { noop, toString } from "lodash-es"; + +const mimeTypes = new Map( + [ + ['audio/aac', '.aac'], + ['application/x-abiword', '.abw'], + ['application/x-freearc', '.arc'], + ['image/avif', '.avif'], + ['video/x-msvideo', '.avi'], + ['application/vnd.amazon.ebook', '.azw'], + ['application/octet-stream', '.bin'], + ['.bmp', 'image/bmp'], + ['application/x-bzip', '.bz'], + ['application/x-bzip2', '.bz2'], + ['application/x-cdf', '.cda'], + ['application/x-csh', '.csh'], + ['text/css', '.css'], + ['text/csv', '.csv'], + ['application/msword', '.doc'], + ['application/vnd.openxmlformats-officedocument.wordprocessingml.document', '.docx'], + ['application/vnd.ms-fontobject', '.eot'], + ['application/epub+zip', '.epub'], + ['application/gzip', '.gz'], + ['image/gif', '.gif'], + ['text/html', '.html'], + ['image/vnd.microsoft.icon', '.ico'], + ['text/calendar', '.ics'], + ['application/java-archive', '.jar'], + ['image/jpeg', '.jar'], + ['text/javascript', '.js'], + ['application/json', '.json'], + ['application/ld+json', '.jsonld'], + ['audio/midi', '.midi'], + ['audio/x-midi', '.midi'], + ['audio/mpeg', '.mp3'], + ['video/mp4', '.mp4'], + ['video/mpeg', '.mpeg'], + ['application/vnd.apple.installer+xml', '.mpkg'], + ['application/vnd.oasis.opendocument.presentation', '.odp'], + ['application/vnd.oasis.opendocument.spreadsheet', '.ods'], + ['application/vnd.oasis.opendocument.text', '.odt'], + ['audio/ogg', '.oga'], + ['video/ogg', '.ogv'], + ['application/ogg', '.ogx'], + ['audio/opus', '.opus'], + ['font/otf', '.otf'], + ['image/png', '.png'], + ['application/pdf', '.pdf'], + ['application/x-httpd-php', '.php'], + ['application/vnd.ms-powerpoint', '.ppt'], + ['application/vnd.openxmlformats-officedocument.presentationml.presentation', '.pptx'], + ['application/vnd.rar', '.rar'], + ['application/rtf', '.rtf'], + ['application/x-sh', '.sh'], + ['image/svg+xml', '.svg'], + ['application/x-tar', '.tar'], + ['image/tiff', '.tiff'], + ['video/mp2t', '.ts'], + ['font/ttf', '.ttf'], + ['text/plain', '.txt'], + ['application/vnd.visio', '.vsd'], + ['audio/wav', '.wav'], + ['audio/webm', '.weba'], + ['video/webm', '.webp'], + ['font/woff', '.woff'], + ['font/woff2', '.woff2'], + ['application/xhtml+xml', '.xhtml'], + ['application/vnd.ms-excel', '.xls'], + ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', '.xlsx'], + ['application/xml', '.xml'], + ['text/xml', '.xml'], + ['application/vnd.mozilla.xul+xml', '.xul'], + ['application/zip', '.zip'], + ['video/3gpp', '.3gp'], + ['audio/3gpp', '.3gp'], + ['video/3gpp2', '.3g2'], + ['audio/3gpp2', '.3g2'], + ['application/x-7z-compressed', '.7z'] + ] +); + +/** + * Converts a message to a localized text. + * @param message The current message. + * @param translate The translate service. + * @returns The message as localized text. + */ +export function messageToString(message: any, translate: TranslateService): string { + let text: string; + if (message instanceof ApplicationError) { + text = format(message.message, message.name, message.args); + } else if (message instanceof Error) { + text = message.message; + } else if (typeof message === "string") { + text = message; + } else if (message instanceof HttpErrorResponse) { + if (isErrorData(message.error)) { + text = format(message.error.message, message.error.name, message.error.args); + } else { + text = message.message ?? `${message.status} ${message.statusText}`; + } + } else if (isErrorData(message)) { + text = format(message.message, message.name, message.args); + } else { + text = toString(message); + } + + return text; + + function isErrorData(value: object): value is ErrorData { + return typeof value === 'object' && 'message' in value && 'name' in value && 'type' in value; + } + + function format(message: string, name: string, args: any[]): string { + if (name) { + return stringFormat(translate.instant(name), args); + } + + return message; + } +} + +/** + * Resolves the specified error to an displayable object. + * @param error The error. + * @param translate The translation service. + * @returns + */ +export async function resolveError(error: unknown, translate: TranslateService): Promise { + let message = error; + if (error instanceof HttpErrorResponse) { + if (error.error instanceof Blob) { + if (error.error.type === 'application/json') { + try { + const buffer = await error.error.arrayBuffer(); + message = JSON.parse(new TextDecoder().decode(buffer)); + } catch (_) { + noop(); + } + } + } + } + + return messageToString(message, translate); +} + +/** + * Replaces all `\` in the specified path with `/`. + * @param path The path. + * @returns The normalized file path. + */ +export function normalize(path: string): string { + path = path.replace(/\\/g, '/'); + if (path.charAt(0) === '/') { + path = path.slice(1); + } else if (path.startsWith('./')) { + path = path.slice(2); + } + + return path; +} + +/** + * Gets the file name of the specified file path. + * @param path The file path. + * @returns The file name. + */ +export function basename(path: string): string { + let index = path.lastIndexOf('/'); + if (index < 0) { + index = path.lastIndexOf('\\'); + } + + return index < 0 ? path : path.substring(index + 1); +} + +/** + * Gets the extension of the specified file path. + * @param path The file path. + * @returns The extension. + */ +export function extension(path: string): string | undefined { + const name = basename(path); + const index = name.lastIndexOf('.'); + return index < 0 ? undefined : name.substring(index); +} + +/** + * Encodes a string to Base64Url. + * @param s The string to encode. + * @returns The encoded string. + */ +export function encodeBase64Url(s: string): string { + return window.btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); +} + +/** + * Decodes a Base64Url string. + * @param s The encoded string. + * @returns The decoded string. + */ +export function decodeBase64Url(s: string): string { + let data = s.replace(/-/g, '+').replace(/_/g, '/'); + const padding = s.length % 4; + if (padding > 0) { + data = (data + '===').slice(0, s.length + 4 - padding); + } + + return window.atob(data); +} + +/** + * Checks if the specified string is base64 encoded + * @param s The string to test. + * @return true if base64 encoded + */ +export function isBase64(s: string): boolean { + return /^[A-Za-z0-9+/]*[=]{0,2}$/.test(s); +} + +/** Returns the file extension that corresponds to the specified MIME type. */ +export function mimeTypeToExtension(mimeType: string): string | undefined { + return mimeTypes.get(mimeType); +} + +/** Returns the MIME type that corresponds ti the specified file extension */ +export function extensionToMimeType(extension: string): string | undefined { + for (const tuple of mimeTypes) { + if (tuple[1] === extension) { + return tuple[0]; + } + } + + return undefined; +} + +/** + * Converts a Blob to a base64 encoded string. + * @param blob The current Blob. + * @returns The base64 encoded string. + */ +export function convertBlobToBase64Async(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onloadend = () => { + const base64WithDataUrlPrefix = reader.result as string; + const index = base64WithDataUrlPrefix.indexOf(';base64,'); + const base64 = base64WithDataUrlPrefix.substring(index + 8); + resolve(base64); + }; + + reader.onerror = reject; + reader.readAsDataURL(blob); + }); +} diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.actions.ts b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.actions.ts new file mode 100644 index 00000000..22057a53 --- /dev/null +++ b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.actions.ts @@ -0,0 +1,24 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from "@ngrx/store"; +import { FeedbackItem, GeneralItem } from "./customer-feedback.state"; + +export enum CustomerFeedbackActionType { + INITIALIZE = '[CustomerFeedback] initialize' +} + +export const initialize = createAction( + CustomerFeedbackActionType.INITIALIZE, + props<{ + stars: number; + count: number; + starClassNames: string[]; + items: GeneralItem[]; + feedbacks: FeedbackItem[] + }>()); diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.html b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.html new file mode 100644 index 00000000..440a1568 --- /dev/null +++ b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.html @@ -0,0 +1,46 @@ + + +
+
+
+ CustomerFeedback.OverallRating ({{count | number}}) +
+
+ +   + + {{stars | number: '1.1-1'}} +
+
+
+
{{name}}
+
+
+
{{item.name}}
+
+ +
+
+
+
+ +
+
+
+ +   + +
+
{{feedback.createdAt}}
+
{{feedback.subject}}
+
+
{{feedback.message}}
+
+
+
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.scss b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.ts b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.ts new file mode 100644 index 00000000..0952cdb2 --- /dev/null +++ b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.component.ts @@ -0,0 +1,226 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { TranslateService } from '@ngx-translate/core'; +import { aas, getLocaleValue, getPreferredName } from 'common'; +import { Subscription } from 'rxjs'; +import * as CustomerFeedbackActions from './customer-feedback.actions'; +import { CustomerFeedbackFeatureState, FeedbackItem, GeneralItem } from './customer-feedback.state'; +import { DocumentSubmodelPair, SubmodelTemplate } from '../submodel-template/submodel-template'; +import { selectCustomerFeedback } from './customer-feedback.selectors'; + +@Component({ + selector: 'fhg-customer-feedback', + templateUrl: './customer-feedback.component.html', + styleUrls: ['./customer-feedback.component.scss'] +}) +export class CustomerFeedbackComponent implements SubmodelTemplate, OnInit, OnChanges, OnDestroy { + private static readonly maxStars = 5; + private readonly store: Store + private readonly map = new Map(); + private readonly subscription = new Subscription(); + + constructor( + store: Store, + private readonly translate: TranslateService + ) { + this.store = store as Store; + } + + @Input() + public submodels: DocumentSubmodelPair[] | null = null; + + public get name(): string { + let value: string | undefined; + if (this.submodels) { + const names = this.submodels.map( + item => getLocaleValue( + getPreferredName(item.document.content!, item.submodel), + this.translate.currentLang) ?? item.submodel.idShort); + + if (names.length <= 2) { + value = names.join(', '); + } else { + value = `${names[0]}, ..., ${names[names.length - 1]} (${names.length})`; + } + } + + return value ?? ''; + } + + public stars = 0.0; + + public count = 0; + + public items: GeneralItem[] = []; + + public feedbacks: FeedbackItem[] = []; + + public starClassNames: string[] = []; + + public ngOnInit(): void { + this.subscription.add(this.store.select(selectCustomerFeedback).pipe().subscribe(state => { + this.stars = state.stars; + this.count = state.count; + this.starClassNames = state.starClassNames; + this.items = state.items.filter(item => item.count > 0); + this.feedbacks = state.feedbacks; + })); + + this.subscription.add(this.translate.onLangChange.subscribe(() => { + this.init(); + })); + } + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['submodels']) { + this.init(); + } + } + + public ngOnDestroy(): void { + this.subscription.unsubscribe(); + } + + private init(): void { + this.map.clear(); + let count = 0; + let stars = 0.0; + const items: GeneralItem[] = []; + const feedbacks: FeedbackItem[] = []; + let starClassNames: string[] | undefined; + let sumStars = 0; + if (this.submodels) { + for (const pair of this.submodels) { + if (pair.submodel.submodelElements) { + for (const feedback of pair.submodel.submodelElements.filter( + item => item.modelType === 'SubmodelElementCollection')) { + const general = (feedback as aas.SubmodelElementCollection).value?.find( + item => item.modelType === 'SubmodelElementCollection' && item.idShort === 'General'); + + if (general) { + sumStars += this.getStars(feedback); + this.buildItems(general, items); + ++count; + } + + feedbacks.push({ + stars: this.initStarClassNames(this.getStars(feedback)), + createdAt: this.getCreatedAt(feedback), + subject: pair.submodel.idShort, + message: this.getMessage(feedback) + }); + } + } + } + + if (count > 0) { + stars = sumStars / count; + items.forEach(item => { + item.score = item.sum / item.count; + item.like = item.score >= 0.0; + }); + } + + starClassNames = this.initStarClassNames(stars); + } else { + starClassNames = this.initStarClassNames(0); + } + + this.store.dispatch(CustomerFeedbackActions.initialize({ + stars, + count, + starClassNames, + items, + feedbacks + })); + } + + private buildItems(general: aas.SubmodelElementCollection, items: GeneralItem[]): void { + if (general.value) { + for (const element of general.value.filter(child => child.modelType === 'SubmodelElementCollection')) { + let item = this.map.get(element.idShort); + if (!item) { + item = { + name: this.getName(element), + score: 0, + sum: 0.0, + count: 0, + like: false + }; + + this.map.set(element.idShort, item); + items.push(item); + } + + const score = this.getScore(element); + if (!Number.isNaN(score)) { + ++item.count; + item.sum += score; + } + } + } + } + + private getScore(element: aas.Referable): number { + let score = Number(this.findProperty(element, 'Score')?.value); + if (!score && !this.findProperty(element, 'Sentiment')?.value) { + score = Number.NaN; + } + + return score; + } + + private getStars(element: aas.Referable): number { + const property = this.findProperty(element, 'stars'); + return property ? Number(property.value) : 0.0; + } + + private getMessage(element: aas.Referable): string { + const property = this.findProperty(element, 'message'); + return property ? String(property.value) : '-'; + } + + private getCreatedAt(element: aas.Referable): string { + const property = this.findProperty(element, 'createdAt'); + if (property) { + const date = new Date(String(property.value)); + return date.toLocaleDateString(this.translate.currentLang); + } + + return '-'; + } + + private initStarClassNames(stars: number): string[] { + const starClassNames: string[] = []; + for (let i = 0; i < CustomerFeedbackComponent.maxStars; i++) { + let className: string; + const n = stars - i; + if (n > 0.0) { + className = n >= 1.0 ? 'bi bi-star-fill' : 'bi-star-half'; + } else { + className = 'bi bi-star'; + } + + starClassNames.push(className); + } + + return starClassNames; + } + + private getName(element: aas.Referable): string { + return this.translate.instant(`CustomerFeedback.${element.idShort}`); + } + + private findProperty(element: aas.SubmodelElementCollection, name: string): aas.Property | undefined { + return element.value?.find( + child => child.modelType === 'Property' && child.idShort === name) as aas.Property; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.reducer.ts b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.reducer.ts new file mode 100644 index 00000000..2be940fb --- /dev/null +++ b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.reducer.ts @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from "@ngrx/store"; +import * as CustomerFeedbackActions from "./customer-feedback.actions"; +import { CustomerFeedbackState, FeedbackItem, GeneralItem } from "./customer-feedback.state"; + +const initialState: CustomerFeedbackState = { + stars: 0.0, + count: 0, + starClassNames: [], + items: [], + feedbacks: [], + error: null +} + +export const customerFeedbackReducer = createReducer( + initialState, + on( + CustomerFeedbackActions.initialize, + (state, { stars, count, starClassNames, items, feedbacks }) => initialize(state, stars, count, starClassNames, items, feedbacks) + ) +) + +function initialize( + state: CustomerFeedbackState, + stars: number, + count: number, + starClassNames: string[], + items: GeneralItem[], + feedbacks: FeedbackItem[]): CustomerFeedbackState { + return { + ...state, + stars: stars, + count: count, + starClassNames: starClassNames, + items: items, + feedbacks: feedbacks, + error: null + }; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.selectors.ts b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.selectors.ts new file mode 100644 index 00000000..96def872 --- /dev/null +++ b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.selectors.ts @@ -0,0 +1,14 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from '@ngrx/store'; +import { CustomerFeedbackFeatureState } from './customer-feedback.state'; + +const getCustomerFeedback = (state: CustomerFeedbackFeatureState) => state.customerFeedback; + +export const selectCustomerFeedback = createSelector(getCustomerFeedback, (customerFeedback) => customerFeedback); \ No newline at end of file diff --git a/projects/aas-lib/src/lib/customer-feedback/customer-feedback.state.ts b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.state.ts new file mode 100644 index 00000000..afa480f8 --- /dev/null +++ b/projects/aas-lib/src/lib/customer-feedback/customer-feedback.state.ts @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface GeneralItem { + name: string; + score: number; + sum: number; + count: number; + like: boolean; +} + +export interface FeedbackItem { + stars: string[]; + createdAt: string; + subject: string; + message: string; +} + +export interface CustomerFeedbackState { + stars: number; + count: number; + starClassNames: string[]; + items: GeneralItem[]; + feedbacks: FeedbackItem[]; + error: unknown +} + +export interface CustomerFeedbackFeatureState { + customerFeedback: CustomerFeedbackState; +} diff --git a/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.html b/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.html new file mode 100644 index 00000000..5c5c5776 --- /dev/null +++ b/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.html @@ -0,0 +1,33 @@ + + +
+
+
+ {{nameplate.serialNumber}} +
+
+ {{nameplate.productCountryOfOrigin}}-{{nameplate.yearOfConstruction}} +
+
+
+
+ {{nameplate.manufacturerName}} +
+
+
+
+ {{nameplate.street}} +
+
+
+
+ {{nameplate.countryCode}}-{{nameplate.zip}} {{nameplate.cityTown}} +
+
+
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.scss b/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.ts b/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.ts new file mode 100644 index 00000000..085bf1ba --- /dev/null +++ b/projects/aas-lib/src/lib/digital-nameplate/digital-nameplate.component.ts @@ -0,0 +1,87 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { + aas, + convertToString, + getLocaleValue, + isMultiLanguageProperty, + isProperty, + isSubmodelElementCollection +} from 'common'; +import { DocumentSubmodelPair, SubmodelTemplate } from '../submodel-template/submodel-template'; + +export interface DigitalNameplate { + serialNumber: string; + productCountryOfOrigin: string; + yearOfConstruction: string; + countryCode: string; + zip: string; + manufacturerName: string; + cityTown: string; + street: string; +} + +@Component({ + selector: 'fhg-digital-nameplate', + templateUrl: './digital-nameplate.component.html', + styleUrls: ['./digital-nameplate.component.scss'] +}) +export class DigitalNameplateComponent implements SubmodelTemplate, OnChanges { + + constructor(private readonly translate: TranslateService) { } + + @Input() + public submodels: DocumentSubmodelPair[] | null = null; + + public nameplates: DigitalNameplate[] = []; + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['submodels']) { + this.init(); + } + } + + private init() { + this.nameplates = this.submodels?.map(pair => { + const submodel = pair.submodel; + return { + serialNumber: this.getPropertyValue(submodel, ['SerialNumber']), + productCountryOfOrigin: this.getPropertyValue(submodel, ['ProductCountryOfOrigin']), + yearOfConstruction: this.getPropertyValue(submodel, ['YearOfConstruction']), + manufacturerName: this.getPropertyValue(submodel, ['ManufacturerName']), + countryCode: this.getPropertyValue(submodel, ['PhysicalAddress', 'CountryCode']), + zip: this.getPropertyValue(submodel, ['PhysicalAddress', 'Zip']), + cityTown: this.getPropertyValue(submodel, ['PhysicalAddress', 'CityTown']), + street: this.getPropertyValue(submodel, ['PhysicalAddress', 'Street']) + }; + }) ?? []; + } + + private getPropertyValue(submodel: aas.Submodel, path: string[]): string { + let children = submodel.submodelElements; + for (const idShort of path) { + const child = children?.find(child => child.idShort === idShort); + if (!child) { + break; + } + + if (isSubmodelElementCollection(child)) { + children = child.value; + } else if (isProperty(child)) { + return convertToString(child.value, this.translate.currentLang); + } else if (isMultiLanguageProperty(child)) { + return getLocaleValue(child.value, this.translate.currentLang) ?? 'N/D'; + } + } + + return ''; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/document.service.ts b/projects/aas-lib/src/lib/document.service.ts new file mode 100644 index 00000000..1081dbbf --- /dev/null +++ b/projects/aas-lib/src/lib/document.service.ts @@ -0,0 +1,22 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class DocumentService { + public getElementById(elementId: string): HTMLElement | null { + return document.getElementById(elementId); + } + + public createElement(tagName: string, options?: ElementCreationOptions): HTMLElement { + return document.createElement(tagName, options); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/download.service.ts b/projects/aas-lib/src/lib/download.service.ts new file mode 100644 index 00000000..ef2735e7 --- /dev/null +++ b/projects/aas-lib/src/lib/download.service.ts @@ -0,0 +1,93 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClient, HttpEvent } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { map, Observable } from 'rxjs'; +import { encodeBase64Url } from './convert'; + +@Injectable({ + providedIn: 'root' +}) +export class DownloadService { + constructor( + private readonly http: HttpClient + ) { + } + + /** + * Download a file from the specified URL. + * @param url The URL to the file resource. + * @param filename The file name. + */ + public async downloadFileAsync(url: string, filename: string): Promise { + return new Promise((resolve, reject) => { + this.http.get( + url, + { + responseType: 'blob' + }).pipe(map(blob => { + const a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.setAttribute('download', filename); + a.click(); + URL.revokeObjectURL(a.href); + })).subscribe({ + error: (error) => reject(error), + complete: () => resolve() + }); + }); + } + + /** + * Downloads an AASX package file. + * @param url The endpoint URL. + * @param id The AAS identifier. + * @param name The file name. + */ + public downloadDocumentAsync(url: string, id: string, name: string): Promise { + return new Promise((resolve, reject) => { + this.http.get( + `/api/v1/containers/${encodeBase64Url(url)}/documents/${encodeBase64Url(id)}`, + { + responseType: 'blob' + }).pipe(map(blob => { + const a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + a.setAttribute('download', name); + a.click(); + URL.revokeObjectURL(a.href); + })).subscribe({ + error: (error) => reject(error), + complete: () => resolve() + }); + }); + } + + /** + * Uploads the specified aasx file. + * @param file A file. + * @param url The URL of the destination. + */ + public uploadDocuments(url: string, file: File | File[]): Observable> { + const data = new FormData(); + if (Array.isArray(file)) { + file.forEach(item => data.append('file', item)); + } else { + data.append('file', file); + } + + return this.http.post( + `/api/v1/containers/${encodeBase64Url(url)}/documents`, + data, + { + reportProgress: true, + observe: 'events' + }); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/library-table/library-table.component.html b/projects/aas-lib/src/lib/library-table/library-table.component.html new file mode 100644 index 00000000..731b8fd8 --- /dev/null +++ b/projects/aas-lib/src/lib/library-table/library-table.component.html @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + +
#COLUMN_PACKAGECOLUMN_VERSIONCOLUMN_LICENSECOLUMN_DESCRIPTION
{{library.id}} + {{library.name}} +
{{library.name}}
+
{{library.version}}{{library.license}}{{library.description}}
+
+ + +
+
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/library-table/library-table.component.scss b/projects/aas-lib/src/lib/library-table/library-table.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/library-table/library-table.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/library-table/library-table.component.ts b/projects/aas-lib/src/lib/library-table/library-table.component.ts new file mode 100644 index 00000000..3b49479f --- /dev/null +++ b/projects/aas-lib/src/lib/library-table/library-table.component.ts @@ -0,0 +1,52 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { Library } from 'common'; + +export interface LibraryRow extends Library { + id: number; +} + +@Component({ + selector: 'fhg-library-table', + templateUrl: './library-table.component.html', + styleUrls: ['./library-table.component.scss'] +}) +export class LibraryTableComponent implements OnChanges { + @Input() + public collection: Library[] = []; + + @Input() + public pageSize = 10; + + public libraries: LibraryRow[] = []; + + public get size(): number { + return this.collection.length; + } + + public page = 1; + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['collection'] || changes['pageSize']) { + this.refreshLibraries(); + } + } + + public refreshLibraries(): void { + if (this.pageSize > 0 && this.size > this.pageSize) { + this.libraries = this.collection.map((library, i) => ({ id: i + 1, ...library })).slice( + (this.page - 1) * this.pageSize, + (this.page - 1) * this.pageSize + this.pageSize, + ); + } else { + this.libraries = this.collection.map((library, i) => ({ id: i + 1, ...library })); + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/localize/culture-info.ts b/projects/aas-lib/src/lib/localize/culture-info.ts new file mode 100644 index 00000000..16c0310c --- /dev/null +++ b/projects/aas-lib/src/lib/localize/culture-info.ts @@ -0,0 +1,12 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface CultureInfo { + localeId: string; + name: string; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/localize/localize.component.html b/projects/aas-lib/src/lib/localize/localize.component.html new file mode 100644 index 00000000..f1e83d82 --- /dev/null +++ b/projects/aas-lib/src/lib/localize/localize.component.html @@ -0,0 +1,19 @@ + + + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/localize/localize.component.scss b/projects/aas-lib/src/lib/localize/localize.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/localize/localize.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/localize/localize.component.ts b/projects/aas-lib/src/lib/localize/localize.component.ts new file mode 100644 index 00000000..2ce4da76 --- /dev/null +++ b/projects/aas-lib/src/lib/localize/localize.component.ts @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; +import { Observable, BehaviorSubject, Subscription } from 'rxjs'; +import { CultureInfo } from './culture-info'; +import { WindowService } from '../window.service'; + +@Component({ + selector: 'fhg-localize', + templateUrl: './localize.component.html', + styleUrls: ['./localize.component.scss'] +}) +export class LocalizeComponent implements OnInit, OnChanges, OnDestroy { + private readonly subscription = new Subscription(); + private readonly _cultures = new BehaviorSubject([]); + private readonly _culture = new BehaviorSubject(undefined); + + constructor( + private readonly translate: TranslateService, + private readonly window: WindowService + ) { + this.cultures = this._cultures.asObservable(); + this.culture = this._culture.asObservable(); + } + + @Input() + public languages: string[] = ['en-us']; + + public readonly cultures: Observable; + + public readonly culture: Observable; + + public setCulture(value: CultureInfo): void { + this.translate.use(value.localeId); + this.window.setLocalStorageItem('.localeId', value.localeId); + } + + public ngOnInit(): void { + this.subscription.add(this.translate.onLangChange.subscribe(this.onLangChange)); + const localeId = this.window.getLocalStorageItem('.localeId'); + if (localeId && this.translate.currentLang !== localeId) { + this.translate.use(localeId); + } + + if (!this.translate.currentLang) { + this.translate.use(this.translate.defaultLang); + } + } + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['languages']) { + const items = this.languages.map(lang => ( + { + localeId: lang, + name: new Intl.DisplayNames([lang], { type: 'language' }).of(lang) + } as CultureInfo)); + + const current = this.findCulture(items, this.translate.currentLang) ?? + this.findCulture(items, this.translate.defaultLang) ?? + items[0]; + + this._cultures.next(items); + this._culture.next(current); + } + } + + public ngOnDestroy() { + this.subscription.unsubscribe(); + } + + private onLangChange = (value: LangChangeEvent): void => { + const item = this.findCulture(this._cultures.value, value.lang); + if (item) { + this._culture.next(item); + } + } + + private findCulture(cultures: CultureInfo[], localeId: string): CultureInfo | undefined { + localeId = localeId?.toLocaleLowerCase(); + return cultures.find(item => item.localeId.toLocaleLowerCase() === localeId); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/max-length.pipe.ts b/projects/aas-lib/src/lib/max-length.pipe.ts new file mode 100644 index 00000000..a90a7c4c --- /dev/null +++ b/projects/aas-lib/src/lib/max-length.pipe.ts @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'max' +}) +export class MaxLengthPipe implements PipeTransform { + private max = 80; + + public transform(value: string, max = 80): string { + this.max = Math.max(5, Number(max)); + + return value && value.length <= this.max ? value : this.shortenText(value); + } + + private shortenText(value: string): string { + const m2 = this.max / 2; + const start = value.slice(0, m2 - 1); + const end = value.slice(value.length - m2 + 2); + return start + '...' + end; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/message-table/massage-table.reducer.ts b/projects/aas-lib/src/lib/message-table/massage-table.reducer.ts new file mode 100644 index 00000000..d46645b5 --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/massage-table.reducer.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from '@ngrx/store'; +import * as MessageTableActions from './message-table.actions'; +import { MessageTableState } from './message-table.state'; + +const initialState: MessageTableState = { + showInfo: false, + showWarning: false, + showError: true, + column: '', + direction: '' +}; + +export const messageTableReducer = createReducer( + initialState, + on( + MessageTableActions.setSortParameter, + (state, { column, direction }) => setSortParameter(state, column, direction) + ), + on( + MessageTableActions.toggleShowError, + (state) => toggleShowError(state) + ), + on( + MessageTableActions.toggleShowInfo, + (state) => toggleShowInfo(state) + ), + on( + MessageTableActions.toggleShowWarning, + (state) => toggleShowWarning(state) + ) +); + +function setSortParameter(state: MessageTableState, column: string, direction: string): MessageTableState { + return { ...state, column, direction }; +} + +function toggleShowError(state: MessageTableState): MessageTableState { + return { ...state, showError: !state.showError }; +} + +function toggleShowInfo(state: MessageTableState): MessageTableState { + return { ...state, showInfo: !state.showInfo }; +} + +function toggleShowWarning(state: MessageTableState): MessageTableState { + return { ...state, showWarning: !state.showWarning }; +} diff --git a/projects/aas-lib/src/lib/message-table/message-table.actions.ts b/projects/aas-lib/src/lib/message-table/message-table.actions.ts new file mode 100644 index 00000000..dc227617 --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/message-table.actions.ts @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from '@ngrx/store'; + +export enum MessageTableActionType { + SET_SORT_PARAMETER = '[MessageTable] set sort parameter', + TOGGLE_SHOW_INFO = '[MessageTable] toggle show info', + TOGGLE_SHOW_WARNING = '[MessageTable] toggle show warning', + TOGGLE_SHOW_ERROR = '[MessageTable] toggle show error', +} + +export const setSortParameter = createAction( + MessageTableActionType.SET_SORT_PARAMETER, + props<{ column: string; direction: string}>()); + +export const toggleShowInfo = createAction( + MessageTableActionType.TOGGLE_SHOW_INFO); + +export const toggleShowWarning = createAction( + MessageTableActionType.TOGGLE_SHOW_WARNING); + +export const toggleShowError = createAction( + MessageTableActionType.TOGGLE_SHOW_ERROR); \ No newline at end of file diff --git a/projects/aas-lib/src/lib/message-table/message-table.component.html b/projects/aas-lib/src/lib/message-table/message-table.component.html new file mode 100644 index 00000000..b515e6a1 --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/message-table.component.html @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + +
+
+
COLUMN_MESSAGE_TYPE
+
+
+
+
COLUMN_TIMESTAMP
+
+
+
+
COLUMN_MESSAGE_TEXT
+
+
+
+ +
+
+ +
+
+ +
+
{{timestampToString(message.timestamp)}}{{message.text}}
+
+
+ + + + + + + + +
+ + +
+
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/message-table/message-table.component.scss b/projects/aas-lib/src/lib/message-table/message-table.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/message-table.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/message-table/message-table.component.ts b/projects/aas-lib/src/lib/message-table/message-table.component.ts new file mode 100644 index 00000000..e0b06a8a --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/message-table.component.ts @@ -0,0 +1,173 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, OnDestroy, OnInit, QueryList, SimpleChanges, ViewChildren } from '@angular/core'; +import { Store } from '@ngrx/store'; +import { TranslateService } from '@ngx-translate/core'; +import { Message } from 'common'; +import { Subscription } from 'rxjs'; +import { SortEvent, SortableHeaderDirective } from '../sortable-header.directive'; +import { MessageTableFeatureState, MessageTableState } from './message-table.state'; +import * as MessageTableActions from './message-table.actions'; +import * as MessageTableSelectors from './message-table.selectors'; + +@Component({ + selector: 'fhg-message-table', + templateUrl: './message-table.component.html', + styleUrls: ['./message-table.component.scss'] +}) +export class MessageTableComponent implements OnInit, OnChanges, OnDestroy { + private readonly dateTimeOptions: Intl.DateTimeFormatOptions = { + year: 'numeric', month: 'numeric', day: 'numeric', + hour: 'numeric', minute: 'numeric', second: 'numeric' + }; + + private readonly store: Store; + private readonly subscription = new Subscription(); + private _collection: Message[] = []; + private snapshot: MessageTableState = { + showInfo: false, + showWarning: false, + showError: true, + column: '', + direction: '' + }; + + constructor( + store: Store, + private translate: TranslateService) { + this.store = store as Store; + } + + @ViewChildren(SortableHeaderDirective) + public headers!: QueryList; + + @Input() + public collection: Message[] = []; + + @Input() + public pageSize = 10; + + public page = 1; + + public messages: Message[] = []; + + public get size(): number { + return this._collection.length; + } + + public get showInfo(): boolean { + return this.snapshot.showInfo; + } + + public get showWarning(): boolean { + return this.snapshot.showWarning; + } + + public get showError(): boolean { + return this.snapshot.showError; + } + + public ngOnInit(): void { + this.subscription.add(this.store.select(MessageTableSelectors.selectState).pipe() + .subscribe(state => { + this.snapshot = state; + this.filterSort(); + this.refreshMessages(); + })); + } + + public ngOnDestroy(): void { + this.subscription.unsubscribe(); + } + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['collection']) { + this.filterSort(); + this.refreshMessages(); + } + + if (changes['pageSize']) { + this.filterSort(); + this.refreshMessages(); + } + } + + public toggleShowInfo(): void { + this.store.dispatch(MessageTableActions.toggleShowInfo()); + } + + public toggleShowWarning(): void { + this.store.dispatch(MessageTableActions.toggleShowWarning()); + } + + public toggleShowError(): void { + this.store.dispatch(MessageTableActions.toggleShowError()); + } + + public onSort({ column, direction }: SortEvent): void { + this.headers.forEach(header => { + if (header.sortable !== column) { + header.direction = ''; + } + }); + + this.store.dispatch(MessageTableActions.setSortParameter({ column, direction })); + } + + public refreshMessages(): void { + if (this.pageSize > 0 && this.size > this.pageSize) { + this.messages = this._collection.slice( + (this.page - 1) * this.pageSize, + (this.page - 1) * this.pageSize + this.pageSize, + ); + } else { + this.messages = this._collection; + } + } + + public timestampToString(value: number): string { + return new Intl.DateTimeFormat(this.translate.currentLang, this.dateTimeOptions).format(value) + } + + private filterSort(): void { + if (this.snapshot.showError && this.snapshot.showWarning && this.snapshot.showInfo || + !this.snapshot.showError && !this.snapshot.showWarning && !this.snapshot.showInfo) { + this._collection = this.collection; + } + else { + this._collection = this.collection.filter(item => item.type === 'Error' && this.snapshot.showError || + item.type === 'Warning' && this.snapshot.showWarning || + item.type === 'Info' && this.snapshot.showInfo); + } + + if (this.snapshot.column && this.snapshot.direction) { + if (this.snapshot.direction === 'asc') { + this._collection.sort((a, b) => this.compare(a, b, this.snapshot.column)); + } else { + this._collection.sort((a, b) => this.compare(b, a, this.snapshot.column)); + } + } + } + + private compare(a: Message, b: Message, column: string): number { + switch (column) { + case 'text': + return a.text.localeCompare(b.text, this.translate.currentLang, { sensitivity: 'accent' }); + case 'type': + { + const value = a.type.localeCompare(b.type, this.translate.currentLang, { sensitivity: 'accent' }); + return value !== 0 ? value : (a.timestamp - b.timestamp); + } + case 'timestamp': + return a.timestamp - b.timestamp; + default: + return 0; + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/message-table/message-table.selectors.ts b/projects/aas-lib/src/lib/message-table/message-table.selectors.ts new file mode 100644 index 00000000..60f6aa46 --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/message-table.selectors.ts @@ -0,0 +1,14 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from '@ngrx/store'; +import { MessageTableFeatureState } from './message-table.state'; + +const getState = (state: MessageTableFeatureState) => state.messageTable; + +export const selectState = createSelector(getState, (state) => state); \ No newline at end of file diff --git a/projects/aas-lib/src/lib/message-table/message-table.state.ts b/projects/aas-lib/src/lib/message-table/message-table.state.ts new file mode 100644 index 00000000..44a03a1f --- /dev/null +++ b/projects/aas-lib/src/lib/message-table/message-table.state.ts @@ -0,0 +1,19 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface MessageTableState { + showInfo: boolean; + showWarning: boolean; + showError: boolean; + column: string; + direction: string; +} + +export interface MessageTableFeatureState { + messageTable: MessageTableState; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/notify/notify.component.html b/projects/aas-lib/src/lib/notify/notify.component.html new file mode 100644 index 00000000..f70a6256 --- /dev/null +++ b/projects/aas-lib/src/lib/notify/notify.component.html @@ -0,0 +1,10 @@ + + +{{message.text}} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/notify/notify.component.scss b/projects/aas-lib/src/lib/notify/notify.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/notify/notify.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/notify/notify.component.ts b/projects/aas-lib/src/lib/notify/notify.component.ts new file mode 100644 index 00000000..c21e307f --- /dev/null +++ b/projects/aas-lib/src/lib/notify/notify.component.ts @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, OnInit } from '@angular/core'; +import { MessageEntry } from '../types/message-entry'; +import { NotifyService } from './notify.service'; + +@Component({ + selector: 'fhg-notify', + templateUrl: './notify.component.html', + styleUrls: ['./notify.component.scss'] +}) +export class NotifyComponent implements OnInit { + + constructor(notify: NotifyService) { + this.notify = notify; + } + + public readonly notify: NotifyService; + + public close(message: MessageEntry) { + this.notify.remove(message); + } + + public ngOnInit(): void { + this.notify.clear(); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/notify/notify.service.ts b/projects/aas-lib/src/lib/notify/notify.service.ts new file mode 100644 index 00000000..de9ae4bb --- /dev/null +++ b/projects/aas-lib/src/lib/notify/notify.service.ts @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { isElement } from 'lodash-es'; +import { Injectable } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { resolveError } from '../convert'; +import { MessageEntry } from '../types/message-entry'; +import { stringFormat } from 'common'; + +export enum LogType { + Error, + Warning, + Info, + Debug +} + +@Injectable({ + providedIn: 'root' +}) +export class NotifyService { + constructor(private translate: TranslateService) { } + + public messages: MessageEntry[] = []; + + /** + * Displays an error message. + * @param error The error message. + */ + public async error(error: unknown): Promise { + if (error) { + const text = await resolveError(error, this.translate); + this.messages.push( + { + header: this.translate.instant('CAPTION_ERROR'), + text: text, + classname: 'bg-danger', + autohide: false, + delay: 5000 + }); + } + } + + /** + * Displays an information to the user. + * @param message The message. + */ + public info(message: string, ...args: any[]): void { + if (message && !isElement(message)) { + message = stringFormat(this.translate.instant(message), args); + this.messages.push( + { + header: this.translate.instant('CAPTION_INFO'), + text: message, + classname: 'bg-info', + autohide: true, + delay: 5000 + }); + } + } + + /** + * Removes the specified message. + * @param message The message to remove. + */ + public remove(message: MessageEntry) { + this.messages = this.messages.filter(item => item !== message); + } + + /** + * Clears all messages. + */ + public clear(): void { + this.messages.splice(0, this.messages.length); + } + + /** + * Prints a message to the browser console. + * @param type The message type. + * @param message The message. + */ + public log(type: LogType, message: any): void { + if (message) { + switch (type) { + case LogType.Error: + console.error(message); + break; + case LogType.Debug: + console.debug(message); + break; + case LogType.Warning: + console.warn(message); + break; + default: + console.log(message); + break; + } + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/score/score.component.html b/projects/aas-lib/src/lib/score/score.component.html new file mode 100644 index 00000000..b02cf8ac --- /dev/null +++ b/projects/aas-lib/src/lib/score/score.component.html @@ -0,0 +1,22 @@ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/projects/aas-lib/src/lib/score/score.component.scss b/projects/aas-lib/src/lib/score/score.component.scss new file mode 100644 index 00000000..2725225f --- /dev/null +++ b/projects/aas-lib/src/lib/score/score.component.scss @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + + div.score-pos { height: 16px }; + + div.score-neg { height: 16px }; \ No newline at end of file diff --git a/projects/aas-lib/src/lib/score/score.component.ts b/projects/aas-lib/src/lib/score/score.component.ts new file mode 100644 index 00000000..b3186e25 --- /dev/null +++ b/projects/aas-lib/src/lib/score/score.component.ts @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; + +@Component({ + selector: 'fhg-score', + templateUrl: './score.component.html', + styleUrls: ['./score.component.scss'] +}) +export class ScoreComponent implements OnChanges { + @Input() + public score = 0.0; + + public positive = 0; + + public negative = 0; + + public ngOnChanges(changes: SimpleChanges): void { + if(changes['score']) { + if (this.score >= 0.0) { + this.positive = Math.min(Math.round(this.score * 100), 100); + this.negative = 0; + } else { + this.positive = 0; + this.negative = Math.min(Math.round(Math.abs(this.score) * 100), 100); + } + } + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/secured-image/secured-image.component.html b/projects/aas-lib/src/lib/secured-image/secured-image.component.html new file mode 100644 index 00000000..5bc826ba --- /dev/null +++ b/projects/aas-lib/src/lib/secured-image/secured-image.component.html @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/secured-image/secured-image.component.scss b/projects/aas-lib/src/lib/secured-image/secured-image.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/projects/aas-lib/src/lib/secured-image/secured-image.component.ts b/projects/aas-lib/src/lib/secured-image/secured-image.component.ts new file mode 100644 index 00000000..eff32d44 --- /dev/null +++ b/projects/aas-lib/src/lib/secured-image/secured-image.component.ts @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { BehaviorSubject, Observable, map, switchMap } from 'rxjs'; +import { DomSanitizer } from '@angular/platform-browser'; + +@Component({ + selector: 'fhg-img', + templateUrl: './secured-image.component.html', + styleUrls: ['./secured-image.component.scss'] +}) +export class SecuredImageComponent implements OnChanges { + constructor(private httpClient: HttpClient, private domSanitizer: DomSanitizer) { + this.dataUrl$ = this.src$.pipe(switchMap(url => this.loadImage(url))); + } + + @Input() + public src = ''; + private src$ = new BehaviorSubject(this.src); + + @Input() + public alt?: string; + + @Input() + public classname?: string; + + @Input() + public width = -1; + + @Input() + public height = -1; + + public ngOnChanges(changes: SimpleChanges): void { + if (changes['src']) { + this.src$.next(this.src); + } + } + + public readonly dataUrl$: Observable; + + public onError(img: HTMLImageElement): void { + img.src = img.alt; + } + + private loadImage(url: string): Observable { + return this.httpClient + .get(url, { responseType: 'blob' }) + .pipe(map(e => this.domSanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(e)))); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/sortable-header.directive.ts b/projects/aas-lib/src/lib/sortable-header.directive.ts new file mode 100644 index 00000000..a163042a --- /dev/null +++ b/projects/aas-lib/src/lib/sortable-header.directive.ts @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Directive, EventEmitter, Input, Output } from "@angular/core"; + +const rotate: { [key: string]: SortDirection } = { 'asc': 'desc', 'desc': '', '': 'asc' }; + +export type SortDirection = 'asc' | 'desc' | ''; + +export interface SortEvent { + column: string; + direction: SortDirection; +} + +@Directive({ + selector: 'th[sortable]', + host: { + '[class.asc]': 'direction === "asc"', + '[class.desc]': 'direction === "desc"', + '(click)': 'rotate()' + } +}) +export class SortableHeaderDirective { + @Input() + public sortable = ''; + + @Input() + public direction: SortDirection = ''; + + @Output() + public sort = new EventEmitter(); + + public rotate() { + this.direction = rotate[this.direction]; + this.sort.emit({ column: this.sortable, direction: this.direction }); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/submodel-template/submodel-template.ts b/projects/aas-lib/src/lib/submodel-template/submodel-template.ts new file mode 100644 index 00000000..e4cb16dd --- /dev/null +++ b/projects/aas-lib/src/lib/submodel-template/submodel-template.ts @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, AASDocument } from 'common'; + +export interface DocumentSubmodelPair { + document: AASDocument; + submodel: aas.Submodel; +} + +export interface SubmodelViewDescriptor { + template?: string; + submodels: SubmodelReference[]; +} + +export interface SubmodelReference { + id: string; + url: string; + idShort: string; +} + +export interface SubmodelTemplate { + submodels: DocumentSubmodelPair[] | null; +} + +export const CustomerFeedback = 'urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback'; + +export const ZVEINameplate = 'https://admin-shell.io/zvei/nameplate/2/0/Nameplate'; + +export const FHGNameplate = 'urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate'; + +export const supportedSubmodelTemplates = new Map([ + [ZVEINameplate, 'Nameplate'], + [CustomerFeedback, 'CustomerFeedback'] +]); + +const semanticIdMap = new Map([ + ['https://www.hsu-hh.de/aut/aas/nameplate', ZVEINameplate], + [ZVEINameplate, ZVEINameplate], + ['urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate', ZVEINameplate], + ['https://admin-shell.io/zvei/nameplate/2/0/Nameplate', ZVEINameplate], + [CustomerFeedback, CustomerFeedback] +]); + +export function resolveSemanticId(value: aas.HasSemantic | aas.Reference | string): string | undefined { + let semanticId: string | undefined; + if (value) { + if (typeof value === 'string') { + semanticId = semanticIdMap.get(value); + } else if (isReference(value)) { + if (value.keys.length > 0) { + semanticId = semanticIdMap.get(value.keys[0].value); + } + } else { + if (value.semanticId?.keys != null && value.semanticId.keys.length > 0) { + semanticId = semanticIdMap.get(value.semanticId.keys[0].value); + } + } + } + + return semanticId; + + function isReference(value: any): value is aas.Reference { + return Array.isArray((value as aas.Reference).keys); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/toolbar/toolbar.component.html b/projects/aas-lib/src/lib/toolbar/toolbar.component.html new file mode 100644 index 00000000..ee4e528e --- /dev/null +++ b/projects/aas-lib/src/lib/toolbar/toolbar.component.html @@ -0,0 +1,109 @@ + + + \ No newline at end of file diff --git a/projects/aas-lib/src/lib/toolbar/toolbar.component.scss b/projects/aas-lib/src/lib/toolbar/toolbar.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-lib/src/lib/toolbar/toolbar.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-lib/src/lib/toolbar/toolbar.component.ts b/projects/aas-lib/src/lib/toolbar/toolbar.component.ts new file mode 100644 index 00000000..95bd5e30 --- /dev/null +++ b/projects/aas-lib/src/lib/toolbar/toolbar.component.ts @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { TranslateService } from '@ngx-translate/core'; +import { Subscription } from 'rxjs'; +import { ToolbarService } from './toolbar.service'; +import { + ToolbarDropDown, + ToolbarItem, + ToolbarItemGroup, + ToolbarItemType, + ToolbarRadio, + ToolbarTextInput, + ToolbarColorPicker, + ToolbarOption, + ToolbarSelect, + ToolbarCommandItem, + ToolbarCheckedItem as ToolbarCheckedItem +} from './toolbar'; + +@Component({ + selector: 'fhg-toolbar', + templateUrl: './toolbar.component.html', + styleUrls: ['./toolbar.component.scss'] +}) +export class ToolbarComponent implements OnInit, OnDestroy { + private readonly subscription = new Subscription(); + + constructor( + private translate: TranslateService, + private toolbar: ToolbarService) { } + + public groups: ToolbarItemGroup[] = []; + + public ngOnInit(): void { + this.subscription.add(this.toolbar.groups.subscribe( + (values) => this.groups = values + )); + } + + public ngOnDestroy() { + this.subscription.unsubscribe(); + } + + public getName(item: ToolbarItem): string | undefined { + if (typeof item.name === 'string') { + return this.translate.instant(item.name); + } + + return ''; + } + + public getValue(item: ToolbarItem): any { + if (this.isRadio(item)) { + return item.value; + } + + if (this.isColorPicker(item)) { + return item.value; + } + + if (this.isSelect(item)) { + return item.value; + } + + if (this.isTextInput(item)) { + return item.value; + } + + return null; + } + + public isChecked(item: ToolbarItem): boolean { + return this.isCheckedItem(item) ? item.checked : false; + } + + public getPlaceholder(item: ToolbarItem): string { + if (this.isTextInput(item)) { + return this.translate.instant(item.placeholder); + } + + return ''; + } + + public getDropdownItems(item: ToolbarItem): ToolbarItem[] { + return this.isDropdown(item) ? item.items : []; + } + + public getOptions(item: ToolbarItem): ToolbarOption[] { + return this.isSelect(item) ? item.options : []; + } + + public isSelected(item: ToolbarItem, option: ToolbarOption): boolean { + return this.isSelect(item) ? item.value === option.value : false; + } + + public canExecute(item: ToolbarItem, argument?: any): boolean { + if (this.isSelect(item)) { + const element = argument as HTMLSelectElement; + return element && element.selectedIndex >= 0 && + item.command.canExecute(element.options[element.selectedIndex].value); + } + + if (this.isCommandItem(item)) { + return item.command.canExecute(argument); + } + + return false; + } + + public execute(item: ToolbarItem, argument?: any): void { + if (this.isSelect(item)) { + const element = argument as HTMLSelectElement; + if (element && element.selectedIndex >= 0) { + item.command.execute(element.options[element.selectedIndex].value); + } + } + else if (this.isCommandItem(item)) { + item.command.execute(argument); + } + } + + public isButtonGroup(group: ToolbarItemGroup): boolean { + return group.items.every( + item => item.type === ToolbarItemType.Button || + item.type === ToolbarItemType.Dropdown || + item.type === ToolbarItemType.Radio || + item.type === ToolbarItemType.Checkbox); + } + + private isCommandItem(item: ToolbarItem): item is ToolbarCommandItem { + return 'command' in item; + } + + private isRadio(item: ToolbarItem): item is ToolbarRadio { + return item.type === ToolbarItemType.Radio; + } + + private isCheckedItem(item: ToolbarItem): item is ToolbarCheckedItem { + return 'checked' in item; + } + + private isTextInput(item: ToolbarItem): item is ToolbarTextInput { + return item.type === ToolbarItemType.TextInput; + } + + private isDropdown(item: ToolbarItem): item is ToolbarDropDown { + return item.type === ToolbarItemType.Dropdown; + } + + private isColorPicker(item: ToolbarItem): item is ToolbarColorPicker { + return item.type === ToolbarItemType.ColorPicker; + } + + private isSelect(item: ToolbarItem): item is ToolbarSelect { + return item.type === ToolbarItemType.Select; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/toolbar/toolbar.service.ts b/projects/aas-lib/src/lib/toolbar/toolbar.service.ts new file mode 100644 index 00000000..d1c1f29c --- /dev/null +++ b/projects/aas-lib/src/lib/toolbar/toolbar.service.ts @@ -0,0 +1,470 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { + Toolbar, + ToolbarCommandCanExecute, + ToolbarCommandExecute as ToolbarCommandExecute, + ToolbarDivider, + ToolbarItem, + ToolbarButton, + ToolbarMenuItem, + ToolbarDropDown, + ToolbarItemGroup, + ToolbarItemType, + ToolbarItemStyle, + ToolbarRadio, + ToolbarTextInput, + ToolbarSwitch, + ToolbarFileInput, + ToolbarColorPicker, + ToolbarCheckbox, + ToolbarSelect, + ToolbarOption, + ToolbarCheckedItem +} from './toolbar'; + +@Injectable({ + providedIn: 'root' +}) +export class ToolbarService { + private readonly toolbarGroups = new BehaviorSubject([]); + private subscription = new Subscription(); + private ready = false; + private nextId = 1; + + constructor() { + this.groups = this.toolbarGroups.asObservable(); + } + + public groups: Observable; + + public setToolbar(toolbar?: Toolbar | null): void { + if (toolbar != null) { + const inputTextGroups = toolbar.groups.filter(g => g.items.some(item => item.type === ToolbarItemType.TextInput)); + if (inputTextGroups.length === 1) { + inputTextGroups[0].fill = true; + } + + this.ready = true; + this.toolbarGroups.next(toolbar.groups); + } + else { + this.toolbarGroups.next([]); + this.nextId = 1; + this.subscription.unsubscribe(); + this.subscription = new Subscription(); + this.ready = false; + } + } + + public createGroup(items: ToolbarItem[], visible?: boolean | Observable): ToolbarItemGroup { + const group: ToolbarItemGroup = { + id: this.createId(), + visible: typeof visible === 'boolean' ? visible : true, + fill: false, + items: items + } + + if (visible instanceof Observable) { + this.subscription.add(visible.subscribe( + value => this.ready ? this.updateGroupVisible(group.id, value) : group.visible = value)); + } + + return group; + } + + public createButton(classname: string, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarButton { + const item: ToolbarButton = { + id: this.createId(), + type: ToolbarItemType.Button, + style: ToolbarItemStyle.Icon, + classname: classname, + command: { execute: execute, canExecute: canExecute ?? (() => true) } + }; + + return item; + } + + public createRadio( + classname: string, + value: string | boolean | number, + checked: boolean | Observable, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarRadio { + const radio: ToolbarRadio = { + id: this.createId(), + type: ToolbarItemType.Radio, + style: ToolbarItemStyle.Icon, + classname: classname, + value: value, + checked: typeof checked === 'boolean' ? checked : false, + command: { + execute: execute, + canExecute: canExecute ?? (() => true) + } + }; + + if (checked instanceof Observable) { + this.subscription.add(checked.subscribe( + state => this.ready ? this.updateChecked(radio.id, state) : radio.checked = state)); + } + + return radio; + } + + public createCheckbox( + classname: string, + checked: boolean | Observable, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarCheckbox { + const checkbox: ToolbarCheckbox = { + id: this.createId(), + type: ToolbarItemType.Checkbox, + style: ToolbarItemStyle.Icon, + classname: classname, + checked: typeof checked === 'boolean' ? checked : false, + command: { + execute: execute, + canExecute: canExecute ?? (() => true) + } + }; + + if (checked instanceof Observable) { + this.subscription.add(checked.subscribe( + value => this.ready ? this.updateChecked(checkbox.id, value) : checkbox.checked = value)); + } + + return checkbox; + } + + public createSwitch( + name: string, + checked: boolean | Observable, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarSwitch { + const item: ToolbarSwitch = { + id: this.createId(), + type: ToolbarItemType.Switch, + style: ToolbarItemStyle.Icon, + name: name, + checked: typeof checked === 'boolean' ? checked : false, + command: { + execute: execute, + canExecute: canExecute ?? (() => true) + } + }; + + if (checked instanceof Observable) { + this.subscription.add(checked.subscribe( + value => this.ready ? this.updateChecked(item.id, value) : item.checked = value)); + } + + return item; + } + + public createTextInput(classname: string, value: string | Observable, placeholder: string, execute: ToolbarCommandExecute): ToolbarTextInput { + const textInput: ToolbarTextInput = { + id: this.createId(), + type: ToolbarItemType.TextInput, + style: ToolbarItemStyle.Icon, + classname: classname, + value: typeof value === 'string' ? value : '', + placeholder: placeholder, + command: { execute: execute, canExecute: () => true } + }; + + if (value instanceof Observable) { + this.subscription.add( + value.subscribe(text => this.ready ? this.updateInputValue(textInput.id, text) : textInput.value = text)); + } + + return textInput; + } + + public createFileInput(name: string, execute: ToolbarCommandExecute): ToolbarFileInput { + const fileInput: ToolbarFileInput = { + id: this.createId(), + type: ToolbarItemType.FileInput, + style: ToolbarItemStyle.Icon, + name: name, + command: { execute: execute, canExecute: () => true } + }; + + return fileInput; + } + + public createDivider(): ToolbarItem { + return ({ + id: this.createId(), + type: ToolbarItemType.Divider, + style: ToolbarItemStyle.Text, + } as ToolbarDivider) as ToolbarItem; + } + + public createColorPicker( + value: string | Observable, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarColorPicker { + const item: ToolbarColorPicker = { + id: this.createId(), + value: typeof value === 'string' ? value : '', + type: ToolbarItemType.ColorPicker, + style: ToolbarItemStyle.Icon, + command: { execute: execute, canExecute: canExecute ?? (() => true) } + }; + + if (value instanceof Observable) { + this.subscription.add(value.subscribe( + color => this.ready ? this.updateColorPickerValue(item.id, color) : item.value = color)); + } + + return item; + } + + public createDropDown( + classname: string, + items: ToolbarItem[] | Observable, + name?: string | Observable, + enabled?: boolean | Observable): ToolbarDropDown { + const dropDown: ToolbarDropDown = { + id: this.createId(), + type: ToolbarItemType.Dropdown, + style: name ? ToolbarItemStyle.IconText : ToolbarItemStyle.Icon, + classname: classname, + name: typeof name === 'string' ? name : '', + items: Array.isArray(items) ? items : [], + enabled: typeof enabled === 'boolean' ? enabled : true + }; + + if (name instanceof Observable) { + this.subscription.add(name.subscribe( + value => this.ready ? this.updateDropDownName(dropDown.id, value) : dropDown.name = value)); + } + + if (items instanceof Observable) { + this.subscription.add(items.subscribe( + value => this.ready ? this.updateDropDownItems(dropDown.id, value) : dropDown.items = value)); + } + + if (enabled instanceof Observable) { + this.subscription.add(enabled.subscribe( + value => this.ready ? this.updateDropDownEnabled(dropDown.id, value) : dropDown.enabled = value)); + } + + return dropDown; + } + + public createMenuItem( + name: string, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarMenuItem { + const menuItem: ToolbarMenuItem = { + id: this.createId(), + type: ToolbarItemType.MenuItem, + style: ToolbarItemStyle.Text, + name: name, + command: { + execute: execute, + canExecute: canExecute ?? (() => true) + } + }; + + return menuItem; + } + + public createSelect( + options: ToolbarOption[] | Observable, + value: Observable, + execute: ToolbarCommandExecute, + canExecute?: ToolbarCommandCanExecute): ToolbarSelect { + const select: ToolbarSelect = { + id: this.createId(), + value: null, + type: ToolbarItemType.Select, + style: ToolbarItemStyle.Text, + options: Array.isArray(options) ? options : [], + command: { execute: execute, canExecute: canExecute ?? (() => true) } + }; + + if (value instanceof Observable) { + this.subscription.add(value.subscribe(v => this.ready ? this.updateSelectValue(select.id, v) : select.value = v)) + } + + if (options instanceof Observable) { + this.subscription.add(options.subscribe( + items => this.ready ? this.updateSelectOptions(select.id, items) : select.options = items)); + } + + return select; + } + + public createOption(name: string, value: T): ToolbarOption { + const option: ToolbarOption = { + id: this.createId(), + name: name, + value: value + }; + + return option; + } + + private updateGroupVisible(id: string, visible: boolean): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + const index = toolbarGroups.findIndex(item => item.id === id); + if (index >= 0) { + const group = toolbarGroups[index]; + toolbarGroups[index] = { ...group, visible }; + this.toolbarGroups.next(toolbarGroups); + } + } + + private updateChecked(id: string, checked: boolean): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const checkedItem = items[j] as ToolbarCheckedItem; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...checkedItem, checked } as ToolbarCheckedItem; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateColorPickerValue(id: string, value: string): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const colorPicker = items[j] as ToolbarColorPicker; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...colorPicker, value } as ToolbarColorPicker; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateDropDownName(id: string, name: string): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const dropDown = items[j] as ToolbarDropDown; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...dropDown, name } as ToolbarDropDown; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateDropDownItems(id: string, items: ToolbarItem[]): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const groupItems = group.items; + for (let j = 0; j < groupItems.length; j++) { + if (groupItems[j].id === id) { + const dropDown = groupItems[j] as ToolbarDropDown; + toolbarGroups[i] = { ...group, items: [...groupItems] }; + toolbarGroups[i].items[j] = { ...dropDown, items } as ToolbarDropDown; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateDropDownEnabled(id: string, enabled: boolean): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const dropDown = items[j] as ToolbarDropDown; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...dropDown, enabled } as ToolbarDropDown; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateSelectOptions(id: string, options: ToolbarOption[]): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const select = items[j] as ToolbarSelect; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...select, options } as ToolbarSelect; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateSelectValue(id: string, value: any): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const select = items[j] as ToolbarSelect; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...select, value } as ToolbarSelect; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private updateInputValue(id: string, value: string): void { + const toolbarGroups = [...this.toolbarGroups.getValue()]; + for (let i = 0; i < toolbarGroups.length; i++) { + const group = toolbarGroups[i]; + const items = group.items; + for (let j = 0; j < items.length; j++) { + if (items[j].id === id) { + const textInput = items[j] as ToolbarTextInput; + toolbarGroups[i] = { ...group, items: [...items] }; + toolbarGroups[i].items[j] = { ...textInput, value } as ToolbarTextInput; + this.toolbarGroups.next(toolbarGroups); + return; + } + } + } + } + + private createId(): string { + return 'fhg-ti-' + this.nextId++; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/toolbar/toolbar.ts b/projects/aas-lib/src/lib/toolbar/toolbar.ts new file mode 100644 index 00000000..4ce48eaa --- /dev/null +++ b/projects/aas-lib/src/lib/toolbar/toolbar.ts @@ -0,0 +1,128 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Observable } from "rxjs"; + +export type ToolbarCommandExecute = (argument?: any) => void; +export type ToolbarCommandCanExecute = (argument?: any) => boolean; + +export interface ToolbarCommand { + execute(argument?: any): void; + canExecute(argument?: any): boolean; +} + +export enum ToolbarItemType { + Button = 'Button', + TextInput = 'TextInput', + FileInput = 'FileInput', + Radio = 'Radio', + Switch = 'Switch', + Dropdown = 'Dropdown', + MenuItem = 'MenuItem', + Divider = 'Divider', + ColorPicker = 'ColorPicker', + Select = 'Select', + Checkbox = "Checkbox" +} + +export enum ToolbarItemStyle { + Text = 'Text', + Icon = 'Icon', + IconText = 'IconText' +} + +export interface ToolbarObject { + id: string; +} + +export interface ToolbarItem extends ToolbarObject { + type: ToolbarItemType; + style: ToolbarItemStyle; + name?: string; + classname?: string; + enabled?: boolean; +} + +export interface ToolbarCommandItem extends ToolbarItem { + command: ToolbarCommand; +} + +export interface ToolbarButton extends ToolbarCommandItem { + type: ToolbarItemType.Button; +} + +export interface ToolbarColorPicker extends ToolbarCommandItem { + type: ToolbarItemType.ColorPicker; + value: string; +} + +export interface ToolbarCheckedItem extends ToolbarCommandItem { + checked: boolean; +} + +export interface ToolbarRadio extends ToolbarCheckedItem { + type: ToolbarItemType.Radio; + value: string | boolean | number; +} + +export interface ToolbarCheckbox extends ToolbarCheckedItem { + type: ToolbarItemType.Checkbox; +} + +export interface ToolbarSwitch extends ToolbarCheckedItem { + type: ToolbarItemType.Switch; +} + +export interface ToolbarTextInput extends ToolbarCommandItem { + type: ToolbarItemType.TextInput; + value: string | Observable; + placeholder: string; +} + +export interface ToolbarFileInput extends ToolbarCommandItem { + type: ToolbarItemType.FileInput; +} + +export interface ToolbarDivider extends ToolbarItem { + type: ToolbarItemType.Divider; +} + +export interface ToolbarMenuItem extends ToolbarCommandItem { + type: ToolbarItemType.MenuItem; +} + +export interface ToolbarDropDown extends ToolbarItem { + type: ToolbarItemType.Dropdown; + items: ToolbarItem[]; +} + +export interface ToolbarOption extends ToolbarObject { + value: any; + name: string; +} + +export interface ToolbarSelect extends ToolbarCommandItem { + type: ToolbarItemType.Select; + value: any; + options: ToolbarOption[]; +} + +export interface ToolbarItemGroup extends ToolbarObject { + name?: string; + visible: boolean; + fill: boolean; + items: ToolbarItem[]; +} + +export interface Toolbar { + groups: ToolbarItemGroup[]; +} + +export function isToolbarSelect(item: ToolbarItem): item is ToolbarSelect { + return item.type === ToolbarItemType.Select; +} diff --git a/projects/aas-lib/src/lib/types/aas-query-params.ts b/projects/aas-lib/src/lib/types/aas-query-params.ts new file mode 100644 index 00000000..6a5d80bd --- /dev/null +++ b/projects/aas-lib/src/lib/types/aas-query-params.ts @@ -0,0 +1,18 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface AASQueryParams { + format?: string, + id?: string +} + +export interface AASQuery { + id: string; + url?: string; + search?: string; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/aas-table.ts b/projects/aas-lib/src/lib/types/aas-table.ts new file mode 100644 index 00000000..e7186100 --- /dev/null +++ b/projects/aas-lib/src/lib/types/aas-table.ts @@ -0,0 +1,14 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument } from "common"; +import { Observable } from "rxjs"; + +export interface AASTable { + readonly selectedDocuments: Observable; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/aas-tree.ts b/projects/aas-lib/src/lib/types/aas-tree.ts new file mode 100644 index 00000000..9627da4b --- /dev/null +++ b/projects/aas-lib/src/lib/types/aas-tree.ts @@ -0,0 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from 'common'; +import { Observable } from 'rxjs'; + +export interface AASTree { + selectedElements: Observable; + findNext(): void; + findPrevious(): void; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/errors.ts b/projects/aas-lib/src/lib/types/errors.ts new file mode 100644 index 00000000..21d2b06c --- /dev/null +++ b/projects/aas-lib/src/lib/types/errors.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export const ERRORS = { + WORKSPACE_NAME_ALREADY_EXISTS: 'ERROR_WORKSPACE_NAME_ALREADY_EXISTS', + INVALID_OPERATION_VARIABLE_EXPRESSION: 'ERROR_INVALID_OPERATION_VARIABLE_EXPRESSION', + UNKNOWN_VARIABLE_VALUE_TYPE: 'ERROR_UNKNOWN_VARIABLE_VALUE_TYPE', + EMAIL_REQUIRED: 'ERROR_EMAIL_REQUIRED', + INVALID_EMAIL: 'ERROR_INVALID_EMAIL', + PASSWORD_REQUIRED: 'ERROR_PASSWORD_REQUIRED', + INVALID_PASSWORD: 'ERROR_INVALID_PASSWORD', + PASSWORDS_NOT_EQUAL: 'ERROR_PASSWORDS_NOT_EQUAL', + DASHBOARD_PAGE_ALREADY_EXISTS: 'ERROR_DASHBOARD_PAGE_ALREADY_EXISTS', + UNAUTHORIZED_ACCESS: 'ERROR_UNAUTHORIZED_ACCESS', +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/info.ts b/projects/aas-lib/src/lib/types/info.ts new file mode 100644 index 00000000..e0a980b0 --- /dev/null +++ b/projects/aas-lib/src/lib/types/info.ts @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export const INFO = { + NEW_PASSWORD_SENT: 'INFO_NEW_PASSWORD_SENT' +}; \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/message-entry.ts b/projects/aas-lib/src/lib/types/message-entry.ts new file mode 100644 index 00000000..d4e364b5 --- /dev/null +++ b/projects/aas-lib/src/lib/types/message-entry.ts @@ -0,0 +1,15 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface MessageEntry { + header?: string; + text: string; + delay: number; + autohide: boolean; + classname?: string; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/online-state.ts b/projects/aas-lib/src/lib/types/online-state.ts new file mode 100644 index 00000000..cba75e32 --- /dev/null +++ b/projects/aas-lib/src/lib/types/online-state.ts @@ -0,0 +1,9 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export type OnlineState = 'offline' | 'online'; \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/view-mode.ts b/projects/aas-lib/src/lib/types/view-mode.ts new file mode 100644 index 00000000..db5b9be3 --- /dev/null +++ b/projects/aas-lib/src/lib/types/view-mode.ts @@ -0,0 +1,12 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export enum ViewMode { + List = 'list', + Tree = 'tree' +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/types/view-query-params.ts b/projects/aas-lib/src/lib/types/view-query-params.ts new file mode 100644 index 00000000..2732827f --- /dev/null +++ b/projects/aas-lib/src/lib/types/view-query-params.ts @@ -0,0 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { SubmodelViewDescriptor } from "../submodel-template/submodel-template"; + +export interface ViewQueryParams { + format: string, +} + +export interface ViewQuery { + descriptor: SubmodelViewDescriptor; +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/web-socket-factory.service.ts b/projects/aas-lib/src/lib/web-socket-factory.service.ts new file mode 100644 index 00000000..4d518338 --- /dev/null +++ b/projects/aas-lib/src/lib/web-socket-factory.service.ts @@ -0,0 +1,30 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { WebSocketData } from 'common'; +import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; + +@Injectable({ + providedIn: 'root' +}) +export class WebSocketFactoryService { + /** + * Creates a subject that communicates with a server via WebSocket. + * @param url The URL of the source. + * @returns A subject. + */ + public create(url?: string): WebSocketSubject { + if (!url) { + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + url = `${protocol}//${window.location.host}/websocket`; + } + + return webSocket(url); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/lib/window.service.ts b/projects/aas-lib/src/lib/window.service.ts new file mode 100644 index 00000000..4882142d --- /dev/null +++ b/projects/aas-lib/src/lib/window.service.ts @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class WindowService { + /** + * Opens a new browser window for the specified URL. + * @param url The URL. + */ + public open(url: string): void { + window.open(url, '_blank'); + } + + public alert(message: string): void { + window.alert(message); + } + + public prompt(message: string): string | null { + return window.prompt(message); + } + + public confirm(message: string): boolean | undefined { + return window.confirm(message); + } + + public getQueryParams(): URLSearchParams { + return new URLSearchParams(window.location.search); + } + + public getLocalStorageItem(key: string): string | null { + return window.localStorage.getItem(key); + } + + public setLocalStorageItem(key: string, value: string): void { + window.localStorage.setItem(key, value); + } + + public removeLocalStorageItem(key: string): void { + window.localStorage.removeItem(key); + } + + public clearLocalStorage(): void { + window.localStorage.clear(); + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/public-api.ts b/projects/aas-lib/src/public-api.ts new file mode 100644 index 00000000..e797a381 --- /dev/null +++ b/projects/aas-lib/src/public-api.ts @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export * from './lib/aas-lib.module'; + +export * from './lib/clipboard.service'; +export * from './lib/document.service'; +export * from './lib/window.service'; +export * from './lib/web-socket-factory.service'; +export * from './lib/download.service'; +export * from './lib/sortable-header.directive'; +export * from './lib/max-length.pipe'; +export * from './lib/convert'; + +export * from './lib/notify/notify.component'; +export * from './lib/notify/notify.service'; + +export * from './lib/toolbar/toolbar.component'; +export * from './lib/toolbar/toolbar.service'; +export * from './lib/toolbar/toolbar'; + +export * from './lib/localize/localize.component'; +export * from './lib/localize/culture-info'; + +export * from './lib/auth/auth.service'; +export * from './lib/auth/auth.interceptor'; +export * from './lib/auth/auth.component'; +export * from './lib/auth/login-form/login-form.component'; +export * from './lib/auth/profile-form/profile-form.component'; +export * from './lib/auth/register-form/register-form.component'; + +export * from './lib/library-table/library-table.component'; + +export * from './lib/submodel-template/submodel-template'; + +export * from './lib/types/aas-query-params'; +export * from './lib/types/aas-table'; +export * from './lib/types/aas-tree'; +export * from './lib/types/message-entry'; +export * from './lib/types/online-state'; +export * from './lib/types/view-mode'; +export * from './lib/types/view-query-params'; + +export * from './lib/aas-table/aas-table.component'; +export * from './lib/aas-table/aas-table.state'; + +export * from './lib/aas-tree/aas-tree.component'; +export * from './lib/aas-tree/aas-tree-api.service'; +export * from './lib/aas-tree/aas-tree.state'; + +export * from './lib/message-table/message-table.component'; + +export * from './lib/digital-nameplate/digital-nameplate.component'; + +export * from './lib/customer-feedback/customer-feedback.component'; +export * from './lib/customer-feedback/customer-feedback.state'; + +export * from './lib/score/score.component'; + +export * from './lib/secured-image/secured-image.component'; \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-table/aas-table.component.spec.ts b/projects/aas-lib/src/test/aas-table/aas-table.component.spec.ts new file mode 100644 index 00000000..1058c8ed --- /dev/null +++ b/projects/aas-lib/src/test/aas-table/aas-table.component.spec.ts @@ -0,0 +1,172 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Router } from '@angular/router'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { Store, StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AASDocument } from 'common'; +import { first, of } from 'rxjs'; +import { CommonModule } from '@angular/common'; +import { SimpleChange } from '@angular/core'; + +import * as ws from '../assets/test-document' +import { AASTableState } from 'src/lib/aas-table/aas-table.state'; +import { AASTableComponent } from 'src/lib/aas-table/aas-table.component'; +import { NotifyService } from 'src/lib/notify/notify.service'; +import { aasTableReducer } from 'src/lib/aas-table/aas-table.reducer'; +import { ViewMode } from 'src/lib/types/view-mode'; +import { MaxLengthPipe, SortableHeaderDirective } from 'src/public-api'; +import { selectState } from 'src/lib/aas-table/aas-table.selectors'; + +describe('AASTableComponent', () => { + let store: Store<{ aasTable: AASTableState }>; + let router: Router; + let component: AASTableComponent; + let fixture: ComponentFixture; + let document1: AASDocument; + let document2: AASDocument; + let document3: AASDocument; + + beforeEach(() => { + document1 = ws.createDocument('document1'); + document2 = ws.createDocument('document2'); + document3 = ws.createDocument('document3'); + document3.modified = true; + + TestBed.configureTestingModule({ + declarations: [ + AASTableComponent, + MaxLengthPipe, + SortableHeaderDirective + ], + providers: [ + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error', 'info', 'log']) + } + ], + imports: [ + CommonModule, + NgbModule, + StoreModule.forRoot( + { + aasTable: aasTableReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + store = TestBed.inject(Store); + router = TestBed.inject(Router); + fixture = TestBed.createComponent(AASTableComponent); + component = fixture.componentInstance; + component.filter = of(''); + component.documents = of([document1, document2, document3]); + component.ngOnChanges({ 'documents': new SimpleChange(null, component.documents, true) }); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('has an initial view mode "List"', function () { + expect(component.viewMode).toEqual(ViewMode.List); + }); + + it('has an initial showAll "false"', function () { + expect(component.showAll).toBeFalse(); + }); + + it('has initial an empty filter', function (done: DoneFn) { + component.filter?.pipe(first()).subscribe(value => { + expect(value).toEqual(''); + done(); + }) + }); + + it('provides initial an empty selectedDocuments property', function (done: DoneFn) { + component.selectedDocuments.pipe(first()).subscribe(documents => { + expect(documents).toEqual([]); + done(); + }) + + }); + + it('provides a rows property', function (done: DoneFn) { + component.rows.pipe(first()).subscribe(rows => { + expect(rows).toBeTruthy(); + done(); + }); + }); + + it('allows switching to viewMode "Tree"', function (done: DoneFn) { + component.viewMode = ViewMode.Tree; + component.ngOnChanges({ viewMode: new SimpleChange(ViewMode.List, ViewMode.Tree, true) }); + store.select(selectState).pipe(first()).subscribe(state => { + expect(state.viewMode).toEqual(ViewMode.Tree); + done(); + }); + }); + + it('allows switching to showAll "true"', function (done: DoneFn) { + component.showAll = true; + component.ngOnChanges({ showAll: new SimpleChange(false, true, true) }); + store.select(selectState).pipe(first()).subscribe(state => { + expect(state.showAll).toBeTrue(); + done(); + }); +}); + + it('allows set a filter', function (done: DoneFn) { + component.filter = of('document'); + component.ngOnChanges({ filter: new SimpleChange(of(''), component.filter, true) }); + + component.filter.pipe(first()).subscribe(value => { + expect(value).toEqual('document'); + done(); + }); + }); + + it('allows selecting a row', function (done: DoneFn) { + const checkbox: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('input[name="document1"]'); + checkbox.checked = true; + checkbox.dispatchEvent(new Event('change')); + fixture.detectChanges(); + store.select(state => state.aasTable.rows).pipe(first()).subscribe(rows => { + expect(rows[0].selected).toBeTrue(); + done(); + }); + }); + + it('allows selecting all rows', function (done: DoneFn) { + const checkbox: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#aas-table-checkbox'); + checkbox.checked = true; + checkbox.dispatchEvent(new Event('change')); + fixture.detectChanges(); + component.rows.pipe(first()).subscribe(rows => { + expect(rows.every(row => row.selected)).toBeTrue(); + done(); + }); + }); + + it('can navigate to an AAS document', function () { + spyOn(router, 'navigateByUrl'); + const anchorElement: HTMLAnchorElement = fixture.debugElement.nativeElement.querySelector('a[name="document1"]'); + anchorElement.dispatchEvent(new Event('click')); + fixture.detectChanges(); + expect(router.navigateByUrl).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-table/aas-table.filter.spec.ts b/projects/aas-lib/src/test/aas-table/aas-table.filter.spec.ts new file mode 100644 index 00000000..dadb73a2 --- /dev/null +++ b/projects/aas-lib/src/test/aas-table/aas-table.filter.spec.ts @@ -0,0 +1,133 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TranslateService } from '@ngx-translate/core'; +import { AASTableFilter } from 'src/lib/aas-table/aas-table.filter'; +import { AASTableRow } from 'src/lib/aas-table/aas-table.state'; +import { aasNoTechnicalData, sampleDocument } from '../assets/sample-document' + +describe('AASTableFilter', function () { + let filter: AASTableFilter; + let translate: jasmine.SpyObj; + let input: AASTableRow[]; + + beforeEach(function () { + translate = jasmine.createSpyObj('TranslateService', {}, { currentLang: 'en-us' }); + filter = new AASTableFilter(translate); + }); + + describe('full text search', function () { + beforeEach(function () { + input = [ + new AASTableRow(sampleDocument, false, 'name1', '111', 'file', false, false, 0, -1, -1), + new AASTableRow(sampleDocument, false, 'name2', '222', 'file', false, false, 0, -1, -1), + new AASTableRow(sampleDocument, false, 'name3', '333', 'file', false, false, 0, -1, -1), + new AASTableRow(sampleDocument, false, 'name41', '444', 'file', false, false, 0, -1, -1), + new AASTableRow(sampleDocument, false, 'name42', '555', 'file', false, false, 0, -1, -1), + new AASTableRow(sampleDocument, false, 'name43', '666', 'file', false, false, 0, -1, -1) + ]; + }); + + it('returns no result for "999"', function () { + expect(filter.do(input, '999')).toEqual([]); + }); + + it('returns 1 result for "111"', function () { + expect(filter.do(input, '111')).toEqual([input[0]]); + }); + + it('returns 3 result for "name4"', function () { + expect(filter.do(input, 'name4')).toEqual([input[3], input[4], input[5]]); + }); + + it('returns all for "NaMe"', function () { + expect(filter.do(input, 'NaMe')).toEqual(input); + }); + + it('returns 2 result for "111 || name2"', function () { + expect(filter.do(input, '111 || name2')).toEqual([input[0], input[1]]); + }); + + it('returns 1 result for "111 && name1"', function () { + expect(filter.do(input, '111 && name1')).toEqual([input[0]]); + }); + + it('returns 1 result for "name4 && 444"', function () { + expect(filter.do(input, 'name4 && 444')).toEqual([input[3]]); + }); + + it('returns 1 result for "name1 && 111 || name2 && 222"', function () { + expect(filter.do(input, 'name1 && 111 || name4 && 666')).toEqual([input[0], input[5]]); + }); + }); + + describe('pattern search', function () { + beforeEach(function () { + input = [ + new AASTableRow(sampleDocument, false, 'name1', '111', 'file', false, false, 0, -1, -1), + new AASTableRow(aasNoTechnicalData, false, 'name2', '222', 'file', false, false, 0, -1, -1), + ]; + }); + + it('returns 1 result for "#prop:MaxRotationSpeed"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed')).toEqual([input[0]]); + }); + + it('returns 1 result for "#prop:MaxRotationSpeed=5000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed=5000')).toEqual([input[0]]); + }); + + it('returns 1 result for "#prop:MaxRotationSpeed >= 4000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed >= 4000')).toEqual([input[0]]); + }); + + it('returns 0 result for "#prop:MaxRotationSpeed >= 5000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed >= 5000')).toEqual([input[0]]); + }); + + it('returns 1 result for "#prop:MaxRotationSpeed > 4999"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed > 4999')).toEqual([input[0]]); + }); + + it('returns no result for "#prop:MaxRotationSpeed > 5000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed > 5000')).toEqual([]); + }); + + it('returns 1 result for "#prop:MaxRotationSpeed <= 5000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed <= 5000')).toEqual([input[0]]); + }); + + it('returns 0 result for "#prop:MaxRotationSpeed < 5001"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed < 5001')).toEqual([input[0]]); + }); + + it('returns 0 result for "#prop:MaxRotationSpeed < 5000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed < 5000')).toEqual([]); + }); + + it('returns 0 result for "#prop:MaxRotationSpeed = 4999...5001"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed = 4999...5001')).toEqual([input[0]]); + }); + + it('returns 0 result for "#prop:MaxRotationSpeed != 5000"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed != 5000')).toEqual([]); + }); + + it('returns 0 result for "#prop:MaxRotationSpeed != 4999"', function () { + expect(filter.do(input, '#prop:MaxRotationSpeed != 4999')).toEqual([input[0]]); + }); + + it('returns 1 result for "#prop=5000"', function () { + expect(filter.do(input, '#prop=5000')).toEqual([input[0]]); + }); + + it('returns n results for "#prop"', function () { + expect(filter.do(input, '#prop').length > 0).toBeTrue(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-tree/aas-tree-api.service.spec.ts b/projects/aas-lib/src/test/aas-tree/aas-tree-api.service.spec.ts new file mode 100644 index 00000000..3614c6b2 --- /dev/null +++ b/projects/aas-lib/src/test/aas-tree/aas-tree-api.service.spec.ts @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { AASDocument, aas } from 'common'; +import { AASTreeApiService } from 'src/lib/aas-tree/aas-tree-api.service'; +import { AuthService } from 'src/lib/auth/auth.service'; + +describe('AASTreeApiService', function () { + let service: AASTreeApiService; + let httpTestingController: HttpTestingController; + let auth: jasmine.SpyObj; + + beforeEach(function () { + auth = jasmine.createSpyObj(['loginAsync']); + TestBed.configureTestingModule({ + declarations: [], + providers: [ + { + provide: AuthService, + useValue: auth + } + ], + imports: [ + HttpClientTestingModule + ], + }); + + service = TestBed.inject(AASTreeApiService); + httpTestingController = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + it('should created', function () { + expect(service).toBeTruthy(); + }); + + describe('invoke', function () { + it('invokes an operation', async function () { + const document = jasmine.createSpyObj({}, { + container: 'http://localhost/container', + id: 'http://localhost/aas' + }); + + const operation: aas.Operation = { + idShort: 'Noop', + modelType: 'Operation', + }; + + const promise = service.invoke(document, operation); + const url = `/api/v1/containers/aHR0cDovL2xvY2FsaG9zdC9jb250YWluZXI/documents/aHR0cDovL2xvY2FsaG9zdC9hYXM` + const req = httpTestingController.expectOne(url); + req.flush(operation); + await expectAsync(promise).toBeResolvedTo(operation); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-tree/aas-tree-search.spec.ts b/projects/aas-lib/src/test/aas-tree/aas-tree-search.spec.ts new file mode 100644 index 00000000..49119122 --- /dev/null +++ b/projects/aas-lib/src/test/aas-tree/aas-tree-search.spec.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core'; +import { AASTreeSearch } from 'src/lib/aas-tree/aas-tree-search'; +import { AASTreeFeatureState } from 'src/lib/aas-tree/aas-tree.state'; +import { aasTreeReducer } from 'src/lib/aas-tree/aas-tree.reducer'; +import * as AASTreeActions from 'src/lib/aas-tree/aas-tree.actions'; +import { sampleDocument } from '../assets/sample-document'; + +describe('AASTreeSearch', function () { + let store: Store; + let search: AASTreeSearch; + + beforeEach(async function () { + await TestBed.configureTestingModule( + { + declarations: [], + providers: [], + imports: [ + StoreModule.forRoot( + { + tree: aasTreeReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + } + ); + + store = TestBed.inject(Store); + search = new AASTreeSearch(store, TestBed.inject(TranslateService)); + + store.dispatch(AASTreeActions.updateRows({document: sampleDocument, localeId: 'en-us'})); + }); + + afterEach(function () { + search.destroy(); + }); + + it('should create', () => { + expect(search).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-tree/aas-tree.component.spec.ts b/projects/aas-lib/src/test/aas-tree/aas-tree.component.spec.ts new file mode 100644 index 00000000..8dc6c434 --- /dev/null +++ b/projects/aas-lib/src/test/aas-tree/aas-tree.component.spec.ts @@ -0,0 +1,327 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AASDocument, WebSocketData } from 'common'; +import { BehaviorSubject, Subject, first } from 'rxjs'; +import { AASTreeComponent } from 'src/lib/aas-tree/aas-tree.component'; +import { sampleDocument } from '../assets/sample-document'; +import { NotifyService } from 'src/lib/notify/notify.service'; +import { DownloadService } from 'src/lib/download.service'; +import { TestWindowService } from '../assets/test-window.service'; +import { WindowService } from 'src/lib/window.service'; +import { WebSocketFactoryService } from 'src/lib/web-socket-factory.service'; +import { TestWebSocketFactoryService } from '../assets/test-web-socket-factory.service'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { CommonModule } from '@angular/common'; +import { aasTreeReducer } from 'src/lib/aas-tree/aas-tree.reducer'; +import { AASTreeFeatureState, AASTreeRow } from 'src/lib/aas-tree/aas-tree.state'; +import { selectMatchIndex, selectMatchRow, selectRows, selectTerms } from 'src/lib/aas-tree/aas-tree.selectors'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { SimpleChange } from '@angular/core'; + +describe('AASTreeComponent', () => { + let component: AASTreeComponent; + let fixture: ComponentFixture; + let document: AASDocument; + let webSocketSubject: Subject; + let store: Store; + + beforeEach(() => { + document = sampleDocument; + webSocketSubject = new Subject(); + + TestBed.configureTestingModule({ + declarations: [ + AASTreeComponent + ], + providers: [ + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error', 'info', 'log']) + }, + { + provide: DownloadService, + useValue: jasmine.createSpyObj(['downloadFileAsync', 'downloadDocumentAsync', 'uploadDocuments']) + }, + { + provide: WindowService, + useValue: new TestWindowService() + }, + { + provide: WebSocketFactoryService, + useValue: new TestWebSocketFactoryService(webSocketSubject) + } + ], + imports: [ + NgbModule, + CommonModule, + HttpClientTestingModule, + StoreModule.forRoot( + { + tree: aasTreeReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(AASTreeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + store = TestBed.inject(Store); + + component.document = document; + component.ngOnChanges({ + 'document': new SimpleChange(null, document, true) + }); + }); + + afterEach(function () { + webSocketSubject?.unsubscribe(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('gets the current document', function () { + expect(component.document).toEqual(document); + }); + + it('indicates if document is online-ready', function () { + expect(component.onlineReady).toEqual(document.onlineReady ? document.onlineReady : false); + }); + + it('indicates if document is read-only', function () { + expect(component.readonly).toEqual(document.readonly); + }); + + it('indicates if the document is modified', function () { + expect(component.modified).toEqual(document.modified ? document.modified : false); + }); + + it('shows the current offline state', function () { + expect(component.state).toEqual('offline'); + }); + + it('indicates if no node is selected', function (done: DoneFn) { + component.someSelected.pipe(first()).subscribe(value => { + expect(value).toBeFalse(); + done(); + }) + }); + + it('shows the first level ExampleMotor', function (done: DoneFn) { + component.nodes.pipe(first()).subscribe(nodes => { + expect(nodes).toBeTruthy(); + expect(nodes.length).toEqual(5); + expect(nodes[0].element.idShort).toEqual('ExampleMotor'); + expect(nodes[0].expanded).toBeTrue(); + expect(nodes[1].element.idShort).toEqual('Identification'); + expect(nodes[2].element.idShort).toEqual('TechnicalData'); + expect(nodes[3].element.idShort).toEqual('OperationalData'); + expect(nodes[4].element.idShort).toEqual('Documentation'); + done(); + }); + }); + + + describe('toggleSelection', function () { + let nodes: AASTreeRow[]; + + beforeEach(function () { + component.nodes.pipe(first()).subscribe(values => nodes = values); + }); + + it('toggle selection of a row', function (done: DoneFn) { + component.toggleSelection(nodes[1]); + component.selectedElements.pipe(first()).subscribe(values => { + expect(values).toEqual([nodes[1].element]); + done(); + }); + }); + + it('toggle selection of all rows', function (done: DoneFn) { + component.toggleSelections(); + store.select(selectRows).pipe(first()).subscribe(values => { + expect(values.every(value => value.selected)).toBeTrue(); + done(); + }); + }); + }); + + describe('collapse', function () { + let nodes: AASTreeRow[]; + + beforeEach(function () { + component.nodes.pipe(first()).subscribe(values => nodes = values); + }); + + it('collapse root element', function (done: DoneFn) { + component.collapse(nodes[0]); + component.nodes.pipe(first()).subscribe(values => { + expect(values.length).toEqual(1); + expect(values[0].element.idShort).toEqual('ExampleMotor'); + expect(values[0].expanded).toBeFalse(); + done(); + }); + }); + + it('collapse to initial view', function () { + component.collapse(); + component.nodes.pipe(first()).subscribe(values => { + expect(values.length).toEqual(5); + expect(values[0].element.idShort).toEqual('ExampleMotor'); + expect(values[0].expanded).toBeTrue(); + expect(values[1].element.idShort).toEqual('Identification'); + expect(values[2].element.idShort).toEqual('TechnicalData'); + expect(values[3].element.idShort).toEqual('OperationalData'); + expect(values[4].element.idShort).toEqual('Documentation'); + }); + }); + }); + + describe('expand', function () { + let nodes: AASTreeRow[]; + + beforeEach(function () { + component.nodes.pipe(first()).subscribe(values => nodes = values); + }); + + it('expand submodel "Identification"', function (done: DoneFn) { + component.expand(nodes[1]); + component.nodes.pipe(first()).subscribe(values => { + expect(values.length).toEqual(9); + expect(values[1].element.idShort).toEqual('Identification'); + expect(values[0].expanded).toBeTrue(); + done(); + }); + }); + }); + + describe('search text "max"', function () { + let search: BehaviorSubject; + let store: Store; + + beforeEach(function () { + search = new BehaviorSubject(''); + component.search = search.asObservable(); + + component.ngOnChanges({ + 'search': new SimpleChange(null, search, true) + }); + + store = TestBed.inject(Store); + }); + + it('the search text must be at least three characters long', function (done: DoneFn) { + const subscription = store.select(selectMatchRow).pipe().subscribe(row => { + if (row) { + expect(row.name).toEqual('MaxRotationSpeed'); + subscription.unsubscribe(); + done(); + } + }); + + search.next('z'); + search.next('zy'); + search.next('max'); + }); + + it('finds the first occurrence of "max" at row 7', function (done: DoneFn) { + search.next('max'); + + store.select(selectMatchIndex).pipe(first()).subscribe(value => { + expect(value).toEqual(7); + done(); + }); + }); + + it('finds the next occurrence of "max" at row 8', function (done: DoneFn) { + search.next('max'); + + store.select(selectTerms).pipe(first()).subscribe(() => { + component.findNext(); + }); + + store.select(selectMatchIndex).pipe(first()).subscribe(value => { + expect(value).toEqual(8); + done(); + }); + }); + + it('finds the previous occurrence of "max" at row 25', function (done: DoneFn) { + search.next('max'); + + store.select(selectTerms).pipe(first()).subscribe(() => { + component.findPrevious(); + }); + + store.select(selectMatchIndex).pipe(first()).subscribe(value => { + expect(value).toEqual(8); + done(); + }); + }); + }); + + describe('search pattern', function () { + let search: BehaviorSubject; + let store: Store; + + beforeEach(function () { + search = new BehaviorSubject(''); + component.search = search.asObservable(); + + component.ngOnChanges({ + 'search': { + currentValue: search, + previousValue: null, + firstChange: true, + isFirstChange: () => true + } + }); + + store = TestBed.inject(Store); + }); + + it('finds the first occurrence of "#prop:max" at row 7', function (done: DoneFn) { + search.next('#prop:max'); + + store.select(selectMatchIndex).pipe(first()).subscribe(value => { + expect(value).toEqual(7); + done(); + }); + }); + + it('finds the first occurrence of "#prop:MaxTorque" at row 8', function (done: DoneFn) { + search.next('#prop:MaxTorque'); + + store.select(selectMatchIndex).pipe(first()).subscribe(value => { + expect(value).toEqual(8); + done(); + }); + }); + + it('finds the first occurrence of "#prop:serialnumber=P12345678I40" at row 5', function (done: DoneFn) { + search.next('#prop:serialnumber=P12345678I40'); + + store.select(selectMatchIndex).pipe(first()).subscribe(value => { + expect(value).toEqual(5); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-tree/opertation-call-form.component.spec.ts b/projects/aas-lib/src/test/aas-tree/opertation-call-form.component.spec.ts new file mode 100644 index 00000000..2a2f3514 --- /dev/null +++ b/projects/aas-lib/src/test/aas-tree/opertation-call-form.component.spec.ts @@ -0,0 +1,180 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { aas, AASDocument, convertToString } from 'common'; +import { cloneDeep } from 'lodash-es'; +import { AASTreeApiService } from 'src/lib/aas-tree/aas-tree-api.service'; +import { OperationCallFormComponent } from 'src/lib/aas-tree/operation-call-form/operation-call-form.component'; +import { sampleDocument } from '../assets/sample-document'; +import { ERRORS } from 'src/lib/types/errors'; + +describe('OperationCallFormComponent', () => { + let component: OperationCallFormComponent; + let fixture: ComponentFixture; + let operation: aas.Operation; + let api: AASTreeApiService; + let document: AASDocument; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [OperationCallFormComponent], + providers: [ + NgbModal, + NgbActiveModal + ], + imports: [ + HttpClientTestingModule, + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + api = TestBed.inject(AASTreeApiService); + fixture = TestBed.createComponent(OperationCallFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + document = sampleDocument; + + operation = { + category: 'CONSTANT', + kind: 'Instance', + methodId: '123', + modelType: 'Operation', + idShort: 'convert', + objectId: 'abc', + inputVariables: [], + inoutputVariables: [], + outputVariables: [] + }; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('calls an operation like toUpperCase(input: string): string', async function () { + operation.inputVariables = [createVariable('inString', 'xs:string', '')]; + operation.outputVariables = [createVariable('outString', 'xs:string', '')]; + + const resultOp = cloneDeep(operation); + (resultOp.inputVariables![0].value as aas.Property).value = 'Hello World!'; + (resultOp.outputVariables![0].value as aas.Property).value = 'Hello World!'.toUpperCase(); + + spyOn(api, 'invoke').and.returnValue(new Promise((result) => result(resultOp))) + component.document = document; + component.operation = operation; + component.inputVariables[0].value = 'Hello World!'; + + await component.call(); + + expect(component.inputVariables[0].value).toEqual('Hello World!'); + expect(component.outputVariables[0].value).toEqual('HELLO WORLD!'); + }); + + it('calls an operation like toggle(in: boolean): boolean', async function () { + operation.inputVariables = [createVariable('in', 'xs:boolean', false)]; + operation.outputVariables = [createVariable('out', 'xs:boolean', false)]; + + const resultOp = cloneDeep(operation); + (resultOp.inputVariables![0].value as aas.Property).value = 'false'; + (resultOp.outputVariables![0].value as aas.Property).value = 'true'; + + spyOn(api, 'invoke').and.returnValue(new Promise((result) => result(resultOp))) + component.document = document; + component.operation = operation; + component.inputVariables[0].value = false; + + await component.call(); + + expect(component.inputVariables[0].value).toEqual(false); + expect(component.outputVariables[0].value).toEqual(true); + }); + + it('calls an operation like increment(in: number): number', async function () { + operation.inputVariables = [createVariable('in', 'xs:int', 0)]; + operation.outputVariables = [createVariable('out', 'xs:int', 0)]; + + const resultOp = cloneDeep(operation); + (resultOp.inputVariables![0].value as aas.Property).value = '42'; + (resultOp.outputVariables![0].value as aas.Property).value = '43'; + + spyOn(api, 'invoke').and.returnValue(new Promise((result) => result(resultOp))) + component.document = document; + component.operation = operation; + component.inputVariables[0].value = '42'; + + await component.call(); + + expect(component.inputVariables[0].value).toEqual('42'); + expect((component.result?.outputVariables![0].value as aas.Property).value).toEqual('43'); + expect(component.outputVariables[0].value).toEqual('43'); + }); + + it('validates an input variable with undefined value (int => 0)', async function () { + operation.inputVariables = [createVariable('in', 'xs:int')]; + component.operation = operation; + expect(component.inputVariables[0].value).toEqual('0'); + }); + + it('validates an input variable with undefined value type (0 => int)', async function () { + operation.inputVariables = [createVariable('in', undefined, 0)]; + component.operation = operation; + expect(component.inputVariables[0].type).toEqual('xs:int'); + }); + + it('shows the message ERROR_UNKNOWN_VARIABLE_VALUE_TYPE if variable data type is undefined', function () { + operation.inputVariables = [createVariable('in')]; + component.operation = operation; + expect(component.messages.length).toEqual(1); + expect(component.messages[0].startsWith(ERRORS.UNKNOWN_VARIABLE_VALUE_TYPE)).toBeTrue(); + expect(component.canCall).toBeFalse(); + }); + + it('shows the message ERROR_INVALID_OPERATION_VARIABLE_EXPRESSION if an input variable expression is invalid', async function () { + operation.inputVariables = [createVariable('in', 'xs:int', 0)]; + operation.outputVariables = [createVariable('out', 'xs:int', 0)]; + + const dummy = cloneDeep(operation); + spyOn(api, 'invoke').and.returnValue(new Promise((result) => result(dummy))) + + component.document = document; + component.operation = operation; + component.inputVariables[0].value = 'invalid'; + + await component.call(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].startsWith(ERRORS.INVALID_OPERATION_VARIABLE_EXPRESSION)).toBeTrue(); + expect(component.canCall).toBeTrue(); + }); + + function createVariable(name: string, valueType?: aas.DataTypeDefXsd, value?: any): aas.OperationVariable { + return { + value: { + modelType: 'Property', + idShort: name, + kind: 'Instance', + valueType: valueType, + value: convertToString(value) + } as aas.Property + }; + } +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-tree/show-image-form.component.spec.ts b/projects/aas-lib/src/test/aas-tree/show-image-form.component.spec.ts new file mode 100644 index 00000000..181077cf --- /dev/null +++ b/projects/aas-lib/src/test/aas-tree/show-image-form.component.spec.ts @@ -0,0 +1,69 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { Component, Input } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { ShowImageFormComponent } from 'src/lib/aas-tree/show-image-form/show-image-form.component'; + +@Component({ + selector: 'fhg-img', + template: '
', +}) +class TestSecureImageComponent { + @Input() + public src = ''; + @Input() + public alt?:string; + @Input() + public classname?: string; + @Input() + public width = -1; + @Input() + public height = -1; +} + +describe('ShowImageFormComponent', () => { + let component: ShowImageFormComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + ShowImageFormComponent, + TestSecureImageComponent + ], + providers: [ + NgbModal, + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(ShowImageFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/aas-tree/show-video-form.component.spec.ts b/projects/aas-lib/src/test/aas-tree/show-video-form.component.spec.ts new file mode 100644 index 00000000..4aa5044b --- /dev/null +++ b/projects/aas-lib/src/test/aas-tree/show-video-form.component.spec.ts @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { ShowVideoFormComponent } from 'src/lib/aas-tree/show-video-form/show-video-form.component'; + +describe('ShowVideoFormComponent', () => { + let component: ShowVideoFormComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ShowVideoFormComponent], + providers: [ + NgbModal, + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(ShowVideoFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/assets/json-web-token.ts b/projects/aas-lib/src/test/assets/json-web-token.ts new file mode 100644 index 00000000..01c53b8b --- /dev/null +++ b/projects/aas-lib/src/test/assets/json-web-token.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +const guestToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZ3Vlc3QiLCJpYXQiOjE2OTA4ODgwMjd9.mUnIUXDwWOlE89QmgXjAVryZY_qWPL-ai-i76ClLTH8'; +const johnToken = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBlbWFpbC5jb20iLCJyb2xlIjoiZWRpdG9yIiwibmFtZSI6IkpvaG4ifQ.L-RbuQQdjgFOhiFqGVxXBBjnyUaAXvMeu9PM-fMshN0'; +const johnDoeToken = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBlbWFpbC5jb20iLCJyb2xlIjoiZWRpdG9yIiwibmFtZSI6IkpvaG4gRG9lIn0.JNBzGftOKu4HY9VzSS5ArWwBrgOc1rHi1ooFcMwcXvw'; + +export function getToken(name: string): string { + switch (name) { + case 'John': + return johnToken; + case 'John Doe': + return johnDoeToken; + default: + throw new Error('Not implemented.'); + } +} + +export function getGuestToken(): string { + return guestToken; +} \ No newline at end of file diff --git a/projects/aas-lib/src/test/assets/sample-document.ts b/projects/aas-lib/src/test/assets/sample-document.ts new file mode 100644 index 00000000..4cfb6593 --- /dev/null +++ b/projects/aas-lib/src/test/assets/sample-document.ts @@ -0,0 +1,3008 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, AASDocument, selectElement } from "common" + +const content: object = { + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassId" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassName" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassificationSystem" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationName" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationOfficialName" + }, + { + "idShort": "Title", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Title" + }, + { + "idShort": "Language", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Language" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/RotationSpeed" + }, + { + "idShort": "Torque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/Torque" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +}; + +const sampleNoTechnicalData: object = { + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassId" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassName" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassificationSystem" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationName" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationOfficialName" + }, + { + "idShort": "Title", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Title" + }, + { + "idShort": "Language", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Language" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/RotationSpeed" + }, + { + "idShort": "Torque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/Torque" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +}; + +const technicalData: object = { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] +}; + +export const sampleDocument: AASDocument = { + "id": "http://customer.com/aas/9175_7013_7091_9168", + "idShort": "ExampleMotor", + "container": "file:///samples?name=Samples&type=AasxDirectory", + "endpoint": { + "type": "file", + "address": "ExampleMotor.aasx" + }, + "timeStamp": 1675961220599, + "modified": false, + "readonly": false, + "onlineReady": false, + "content": content as aas.Environment +}; + +export const aasNoTechnicalData: AASDocument = { + "id": "http://customer.com/aas/9175_7013_7091_9168", + "idShort": "ExampleMotor", + "container": "file:///endpoints/samples?name=Samples&type=AasxDirectory", + "endpoint": { + "type": "file", + "address": "ExampleMotor.aasx" + }, + "timeStamp": 1675961220599, + "modified": false, + "readonly": false, + "onlineReady": false, + "content": sampleNoTechnicalData as aas.Environment +}; + +export const submodelTechnicalData: aas.Submodel = technicalData as aas.Submodel; + +export const rotationSpeed: aas.Property = selectElement(sampleDocument.content!, 'OperationalData', 'RotationSpeed')!; + +export const torque: aas.Property = selectElement(sampleDocument.content!, 'OperationalData', 'Torque')!; + +export const maxRotationSpeed: aas.Property = selectElement(sampleDocument.content!, 'TechnicalData', 'MaxRotationSpeed')!; \ No newline at end of file diff --git a/projects/aas-lib/src/test/assets/test-document.ts b/projects/aas-lib/src/test/assets/test-document.ts new file mode 100644 index 00000000..700be0a6 --- /dev/null +++ b/projects/aas-lib/src/test/assets/test-document.ts @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, AASContainer, AASWorkspace, aas } from 'common'; + +export function createContainer(url: string, documents: AASDocument[]): AASContainer { + return { + documents: documents, + url: url, + name: url + }; +} + +export function createWorkspace(name: string, containers: AASContainer[]): AASWorkspace { + return { + name: name, + containers: containers, + }; +} + +export function createDocument(name: string, url = 'http://localhost/container1'): AASDocument { + const document: AASDocument = { + id: `http://localhost/aas/${name}`, + idShort: name, + container: url, + endpoint: { address: '', type: 'file' }, + timeStamp: 0, + modified: false, + readonly: false, + onlineReady: false, + content: { assetAdministrationShells: [], submodels: [], conceptDescriptions: [] }, + }; + + return document; +} + +export function createDocumentHeader(name: string, url: string): AASDocument { + const document: AASDocument = { + id: `http://localhost/aas/${name}`, + idShort: name, + container: url, + endpoint: { address: '', type: 'file' }, + timeStamp: 0, + modified: false, + readonly: false, + onlineReady: false, + content: null, + }; + + return document; +} + +export function createContent(): aas.Environment { + return { assetAdministrationShells: [], submodels: [], conceptDescriptions: [] }; +} \ No newline at end of file diff --git a/projects/aas-lib/src/test/assets/test-web-socket-factory.service.ts b/projects/aas-lib/src/test/assets/test-web-socket-factory.service.ts new file mode 100644 index 00000000..4bee7ce2 --- /dev/null +++ b/projects/aas-lib/src/test/assets/test-web-socket-factory.service.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { WebSocketData } from 'common'; +import { Subject } from 'rxjs'; +import { WebSocketSubject } from 'rxjs/webSocket'; +import { WebSocketFactoryService } from '../../lib/web-socket-factory.service'; + +export class TestWebSocketFactoryService implements Partial { + constructor(private readonly subject: Subject) {} + + public create(): WebSocketSubject { + return this.subject as WebSocketSubject; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/test/assets/test-window.service.ts b/projects/aas-lib/src/test/assets/test-window.service.ts new file mode 100644 index 00000000..50131890 --- /dev/null +++ b/projects/aas-lib/src/test/assets/test-window.service.ts @@ -0,0 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { WindowService } from '../../lib/window.service'; + +export class TestWindowService implements Partial { + public open(url: string): void {} + + public confirm(message: string): boolean | undefined { + return true; + } +} \ No newline at end of file diff --git a/projects/aas-lib/src/test/auth/auth-api.service.spec.ts b/projects/aas-lib/src/test/auth/auth-api.service.spec.ts new file mode 100644 index 00000000..3d64ee67 --- /dev/null +++ b/projects/aas-lib/src/test/auth/auth-api.service.spec.ts @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { AuthResult, Cookie } from 'common'; + +import { AuthApiService } from 'src/lib/auth/auth-api.service'; +import { getGuestToken, getToken } from '../assets/json-web-token'; + +describe('AuthApiService', function () { + let service: AuthApiService; + let httpTestingController: HttpTestingController; + let userId: string; + + beforeEach(function () { + TestBed.configureTestingModule({ + declarations: [], + providers: [AuthApiService], + imports: [HttpClientTestingModule], + }); + + userId = 'john.doe@email.com'; + service = TestBed.inject(AuthApiService); + httpTestingController = TestBed.inject(HttpTestingController); + }); + + afterEach(function () { + httpTestingController.verify(); + }); + + it('should created', function () { + expect(service).toBeTruthy(); + }); + + describe('guestAsync', function () { + it('login guest', async function () { + const result: AuthResult = { token: getGuestToken() }; + const promise = service.guestAsync(); + const req = httpTestingController.expectOne('/api/v1/guest'); + req.flush(result); + await expectAsync(promise).toBeResolvedTo(result); + expect(req.request.method).toEqual('POST'); + }); + }); + + describe('loginAsync', function () { + it('login John', async function () { + const result: AuthResult = { token: getToken('John') }; + const promise = service.loginAsync({ id: 'john.doe@email.com', password: '1234.xyz' }); + const req = httpTestingController.expectOne('/api/v1/login'); + req.flush(result); + await expectAsync(promise).toBeResolvedTo(result); + expect(req.request.method).toEqual('POST'); + }); + }); + + describe('registerUserAsync', function () { + it('registers John as new user', async function () { + const result: AuthResult = { token: getToken('John') }; + const promise = service.registerUserAsync({ id: 'john.doe@email.com', name: 'John', password: '1234.xyz' }); + const req = httpTestingController.expectOne('/api/v1/register'); + req.flush(result); + await expectAsync(promise).toBeResolvedTo(result); + expect(req.request.method).toEqual('POST'); + }); + }); + + // describe('deleteUserAsync', function () { + // it('deletes a registered user', async function () { + // const promise = service.deleteUserAsync('john.doe@email.com', getToken('John')); + // const req = httpTestingController.expectOne('/api/v1/users/am9obi5kb2VAZW1haWwuY29t'); + // await expectAsync(promise).toBeResolved(); + // expect(req.request.method).toEqual('DELETE'); + // }); + // }); + + it('getCookies', function () { + const cookies: Cookie[] = [ + { + name: 'Cookie1', + data: "Hello world." + } + ]; + + service.getCookies(userId).subscribe(data => { + expect(data).toEqual(cookies); + }); + + const req = httpTestingController.expectOne('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies'); + expect(req.request.method).toEqual('GET'); + req.flush(cookies); + }); + + it('setCookie', function () { + service.setCookie(userId, { name: 'Cookie1', data: 'Hello world.' }).subscribe(); + const req = httpTestingController.expectOne('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1'); + expect(req.request.method).toEqual('POST'); + }); + + it('deleteCookie', function () { + service.deleteCookie(userId, 'Cookie1').subscribe(); + const req = httpTestingController.expectOne('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1'); + expect(req.request.method).toEqual('DELETE'); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/auth/auth.component.spec.ts b/projects/aas-lib/src/test/auth/auth.component.spec.ts new file mode 100644 index 00000000..baea0973 --- /dev/null +++ b/projects/aas-lib/src/test/auth/auth.component.spec.ts @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { NotifyService } from '../../lib/notify/notify.service'; +import { AuthService } from '../../lib/auth/auth.service'; + +import { AuthComponent } from '../../lib/auth/auth.component'; + +describe('AuthComponent', () => { + let component: AuthComponent; + let fixture: ComponentFixture; + let auth: jasmine.SpyObj; + + beforeEach(() => { + auth = jasmine.createSpyObj(['loginAsync']); + + TestBed.configureTestingModule({ + declarations: [AuthComponent], + providers: [ + NgbModal, + NgbActiveModal, + { + provide: AuthService, + useValue: auth + }, + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error', 'info']) + } + ], + imports: [ + HttpClientTestingModule, + CommonModule, + FormsModule, + ReactiveFormsModule, + NgbModule + ] + }); + + fixture = TestBed.createComponent(AuthComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/auth/auth.service.spec.ts b/projects/aas-lib/src/test/auth/auth.service.spec.ts new file mode 100644 index 00000000..3342f3bf --- /dev/null +++ b/projects/aas-lib/src/test/auth/auth.service.spec.ts @@ -0,0 +1,405 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { EMPTY, first, of, skip, skipWhile } from 'rxjs'; + +import { WindowService } from '../../lib/window.service'; +import { NotifyService } from '../../lib/notify/notify.service'; +import { AuthApiService } from '../../lib/auth/auth-api.service'; +import { AuthService } from '../../lib/auth/auth.service'; +import { AuthResult } from 'common'; +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; +import { LoginFormResult, ProfileFormResult, RegisterFormResult } from 'src/public-api'; +import { getGuestToken, getToken } from '../assets/json-web-token'; + +describe('AuthService', () => { + let service: AuthService; + let window: jasmine.SpyObj; + let api: jasmine.SpyObj; + let modal: NgbModal; + + describe('guest', function () { + let token: string; + + beforeEach(function () { + token = getGuestToken(); + api = jasmine.createSpyObj( + ['loginAsync', 'guestAsync', 'registerUserAsync', 'getCookies', 'updateProfileAsync']); + + api.guestAsync.and.returnValue(new Promise(resolve => resolve({ token }))); + api.getCookies.and.returnValue(EMPTY); + + window = jasmine.createSpyObj( + ['getLocalStorageItem', 'setLocalStorageItem', 'removeLocalStorageItem', 'clearLocalStorage']); + + window.getLocalStorageItem.and.returnValue(null); + + TestBed.configureTestingModule({ + declarations: [], + providers: [ + { + provide: WindowService, + useValue: window + }, + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error']) + }, + { + provide: AuthApiService, + useValue: api + } + ], + imports: [ + HttpClientTestingModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + service = TestBed.inject(AuthService); + modal = TestBed.inject(NgbModal); + }); + + it('should be created', (done: DoneFn) => { + expect(service).toBeTruthy(); + + service.payload.pipe(skip(1), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toBeUndefined(); + expect(service.authenticated).toBeFalse(); + expect(service.name).toEqual('GUEST_USER'); + expect(service.role).toEqual('guest'); + done(); + }); + }); + + it('provides a valid guest token', () => { + expect(service).toBeTruthy(); + }); + + describe('isAuthorized', function () { + it('indicates that a guest is authorized as guest', function () { + expect(service.isAuthorized('guest')).toBeTrue(); + }); + + it('indicates that a guest is not authorized as editor', function () { + expect(service.isAuthorized('editor')).toBeFalse(); + }); + + it('indicates that a guest is not authorized as admin', function () { + expect(service.isAuthorized('admin')).toBeFalse(); + }); + }); + + describe('loginAsync', function () { + let newToken: string; + + beforeEach(function () { + newToken = getToken('John'); + }); + + it('can login as arguments', function (done: DoneFn) { + api.loginAsync.and.returnValue(new Promise(resolve => resolve({ token: newToken }))); + service.loginAsync({ id: 'john.doe@email.com', password: 'password' }); + + service.payload.pipe(skipWhile(value => value.sub == null), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + + it('can login via form', function (done: DoneFn) { + api.loginAsync.and.returnValue(new Promise(resolve => resolve({ token: newToken }))); + service.loginAsync({ id: 'john.doe@email.com', password: 'password' }); + + spyOn(modal, 'open').and.returnValue(jasmine.createSpyObj({}, { + result: new Promise(resolve => resolve({ stayLoggedIn: true, token: newToken })) + })); + + service.loginAsync(); + service.payload.pipe(skipWhile(value => value.sub == null), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + }); + + describe('registerAsync', function () { + let newToken: string; + + beforeEach(function () { + newToken = getToken('John'); + }); + + it('allows registering a new user via arguments', function (done: DoneFn) { + api.registerUserAsync.and.returnValue(new Promise(resolve => resolve({ token: newToken }))); + + service.registerAsync({ + id: 'john.doe@email.com', + name: 'John', + password: '1234.xyz' + }); + + service.payload.pipe(skipWhile(value => value.sub == null), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + + it('allows registering a new user via form', function (done: DoneFn) { + api.registerUserAsync.and.returnValue(new Promise(resolve => resolve({ token: newToken }))); + + spyOn(modal, 'open').and.returnValue(jasmine.createSpyObj({}, { + result: new Promise(resolve => resolve({ stayLoggedIn: true, token: newToken })) + })); + + service.registerAsync(); + + service.payload.pipe(skipWhile(value => value.sub == null), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + + describe('logoutUserAsync', function () { + it('throws an error when try to logout', async function () { + await expectAsync(service.logoutAsync()).toBeRejected(); + }); + }); + + describe('updateUserProfileAsync', function () { + it('throw an error for a guest login', async function () { + await expectAsync(service.updateUserProfileAsync()).toBeRejected(); + }); + }); + + }); + }); + + describe('authorized user', function () { + let token: string; + + beforeEach(function () { + token = getToken('John'); + api = jasmine.createSpyObj( + ['loginAsync', 'guestAsync', 'registerUserAsync', 'getCookies', 'updateProfileAsync', 'setCookie', 'deleteCookie', 'deleteUserAsync']); + + api.getCookies.and.returnValue(of([{ name: 'Cookie1', data: 'The quick brown fox jumps over the lazy dog.' }])); + window = jasmine.createSpyObj( + ['getLocalStorageItem', 'setLocalStorageItem', 'removeLocalStorageItem', 'clearLocalStorage', 'confirm']); + + window.getLocalStorageItem.and.callFake(name => { + return name === '.StayLoggedIn' ? 'true' : token; + }); + + TestBed.configureTestingModule({ + declarations: [], + providers: [ + { + provide: WindowService, + useValue: window + }, + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error']) + }, + { + provide: AuthApiService, + useValue: api + } + ], + imports: [ + HttpClientTestingModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + service = TestBed.inject(AuthService); + modal = TestBed.inject(NgbModal); + }); + + it('should be created', (done: DoneFn) => { + expect(service).toBeTruthy(); + + service.payload.pipe(first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + + it('provides a valid user token', () => { + expect(service).toBeTruthy(); + }); + + describe('isAuthorized', function () { + it('indicates that the user is authorized as guest', function () { + expect(service.isAuthorized('guest')).toBeTrue(); + }); + + it('indicates that a guest is authorized as editor', function () { + expect(service.isAuthorized('editor')).toBeTrue(); + }); + + it('indicates that a guest is not authorized as admin', function () { + expect(service.isAuthorized('admin')).toBeFalse(); + }); + }); + + describe('logoutUserAsync', function () { + let guestToken: string; + + beforeEach(function () { + guestToken = getGuestToken(); + }); + + it('logs out the current user', function (done: DoneFn) { + api.guestAsync.and.returnValue(new Promise(resolve => resolve({ token: guestToken }))); + + service.logoutAsync(); + + service.payload.pipe(skipWhile(value => value.sub != null), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toBeUndefined(); + expect(service.authenticated).toBeFalse(); + expect(service.name).toEqual('GUEST_USER'); + expect(service.role).toEqual('guest'); + done(); + }); + }); + }); + + describe('updateUserProfileAsync', function () { + let newToken: string; + let guestToken: string; + + beforeEach(function () { + newToken = getToken('John Doe'); + guestToken = getGuestToken(); + }); + + it('updates the user profile via argument', function (done: DoneFn) { + api.updateProfileAsync.and.returnValue(new Promise(resolve => resolve({ token: newToken }))) + + service.updateUserProfileAsync({ id: 'john.doe@email.com', name: 'John Doe' }); + + service.payload.pipe(skipWhile(value => value.name !== 'John Doe'), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John Doe'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + + it('updates the user profile via form', function (done: DoneFn) { + api.updateProfileAsync.and.returnValue(new Promise(resolve => resolve({ token: newToken }))) + + spyOn(modal, 'open').and.returnValue(jasmine.createSpyObj({}, { + result: new Promise(resolve => resolve({ token: newToken })), + componentInstance: { initialize: jasmine.createSpy() } + })); + + service.updateUserProfileAsync(); + + service.payload.pipe(skipWhile(value => value.name !== 'John Doe'), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toEqual('john.doe@email.com'); + expect(service.authenticated).toBeTrue(); + expect(service.name).toEqual('John Doe'); + expect(service.role).toEqual('editor'); + done(); + }); + }); + + it('deletes a user via form', function (done: DoneFn) { + api.deleteUserAsync.and.returnValue(new Promise(resolve => resolve())) + api.guestAsync.and.returnValue(new Promise(resolve => resolve({ token: guestToken }))); + window.confirm.and.returnValue(true); + spyOn(modal, 'open').and.returnValue(jasmine.createSpyObj({}, { + result: new Promise(resolve => resolve({ action: 'deleteUser' })), + componentInstance: { initialize: jasmine.createSpy() } + })); + + service.updateUserProfileAsync(); + + service.payload.pipe(skipWhile(value => value.sub != null), first()).subscribe((value) => { + expect(value).toBeTruthy(); + expect(service.userId).toBeUndefined(); + expect(service.authenticated).toBeFalse(); + expect(service.name).toEqual('GUEST_USER'); + expect(service.role).toEqual('guest'); + done(); + }); + }); + }); + + describe('getCookie', function () { + it('returns the value of "Cookie1"', function () { + expect(service.getCookie('Cookie1')).toEqual('The quick brown fox jumps over the lazy dog.'); + }); + + }); + + describe('checkCookie', function () { + it('indicates that "Cookie1" exist', function () { + expect(service.checkCookie('Cookie1')).toBeTrue(); + }); + + it('indicates that "Unknown" not exist', function () { + expect(service.checkCookie('Unknown')).toBeFalse(); + }); + + }); + + describe('deleteCookie', function () { + it('deletes a cookie', function (done: DoneFn) { + api.deleteCookie.and.returnValue(of(void 0)); + api.getCookies.and.returnValue(of([])); + + service.deleteCookie('Cookie1').subscribe(() => { + expect(service.checkCookie('Cookie1')).toBeFalse(); + done(); + }) + }); + }); + }); +}); diff --git a/projects/aas-lib/src/test/auth/login-form.component.spec.ts b/projects/aas-lib/src/test/auth/login-form.component.spec.ts new file mode 100644 index 00000000..9d93a535 --- /dev/null +++ b/projects/aas-lib/src/test/auth/login-form.component.spec.ts @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; + +import { AuthApiService } from '../../lib/auth/auth-api.service'; +import { ERRORS } from '../../lib/types/errors'; +import { INFO } from '../../lib/types/info'; +import { LoginFormComponent, LoginFormResult } from '../../lib/auth/login-form/login-form.component'; +import { AuthResult } from 'common'; + +describe('LoginFormComponent', () => { + let component: LoginFormComponent; + let modal: NgbActiveModal; + let api: AuthApiService; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [LoginFormComponent], + providers: [ + NgbModal, + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + HttpClientTestingModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + modal = TestBed.inject(NgbActiveModal); + api = TestBed.inject(AuthApiService); + fixture = TestBed.createComponent(LoginFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('submits a valid user', fakeAsync(async () => { + const result: LoginFormResult = { token: 'a_token', stayLoggedIn: true }; + spyOn(modal, 'close').and.callFake((...args) => expect(args[0]).toEqual(result)); + spyOn(api, 'loginAsync').and.returnValue(new Promise((result) => result({ token: 'a_token' }))); + + component.userId = 'john.doe@email.com'; + component.password = '1234.Abcd'; + component.stayLoggedIn = true; + await component.submit(); + expect(component.messages.length).toEqual(0); + expect(modal.close).toHaveBeenCalled(); + })); + + it('does not login a user with empty e-mail', fakeAsync(async () => { + component.userId = ''; + component.password = '1234.Abcd'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(ERRORS.EMAIL_REQUIRED); + })); + + it('does not login a user with invalid e-mail', fakeAsync(async () => { + component.userId = 'invalidEMail'; + component.password = '1234.abcd'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(ERRORS.INVALID_EMAIL); + })); + + it('does not login a user with empty password', fakeAsync(async () => { + component.userId = 'john.doe@email.com'; + component.password = ''; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(ERRORS.PASSWORD_REQUIRED); + })); + + it('does not login a user with invalid password', fakeAsync(async () => { + component.userId = 'john.doe@email.com'; + component.password = '123'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(ERRORS.INVALID_PASSWORD); + })); + + it('does not login an unknown user', fakeAsync(async () => { + spyOn(modal, 'close').and.returnValue(); + spyOn(api, 'loginAsync').and + .returnValue(new Promise((_, reject) => reject(new Error('Unknown user')))); + + component.userId = 'unknown.user@email.com'; + component.password = '1234.abcd'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual('Unknown user'); + })); + + it('supports the reset of a forgotten password', async function () { + spyOn(api, 'resetPasswordAsync').and.returnValue(new Promise((result) => result())); + component.userId = 'john.doe@email.com'; + await component.resetPassword(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(INFO.NEW_PASSWORD_SENT); + }); + + it('can not reset password when e-mail is empty', fakeAsync(async () => { + component.userId = ''; + await component.resetPassword(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(ERRORS.EMAIL_REQUIRED); + })); + + it('an not reset password when e-mail is invalid', fakeAsync(async () => { + component.userId = 'invalidEMail'; + await component.resetPassword(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0].text).toEqual(ERRORS.INVALID_EMAIL); + })); + + it('supports navigation to the registration', function () { + spyOn(modal, 'close').and.callFake((...args) => expect(args[0]).toEqual({ action: 'register' } as LoginFormResult)); + component.registerUser(); + expect(modal.close).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/auth/profile-form.component.spec.ts b/projects/aas-lib/src/test/auth/profile-form.component.spec.ts new file mode 100644 index 00000000..260d08fb --- /dev/null +++ b/projects/aas-lib/src/test/auth/profile-form.component.spec.ts @@ -0,0 +1,106 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AuthResult } from 'common'; + +import { AuthApiService } from '../../lib/auth/auth-api.service'; +import { ERRORS } from '../../lib/types/errors'; +import { ProfileFormComponent } from '../../lib/auth/profile-form/profile-form.component'; +import { of } from 'rxjs'; + +describe('ProfileFormComponent', () => { + let component: ProfileFormComponent; + let fixture: ComponentFixture; + let modal: NgbActiveModal; + let api: AuthApiService; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ProfileFormComponent], + providers: [ + NgbModal, + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + HttpClientTestingModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + modal = TestBed.inject(NgbActiveModal); + api = TestBed.inject(AuthApiService); + fixture = TestBed.createComponent(ProfileFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('updates a user profile', (done: DoneFn) => { + spyOn(modal, 'close').and.callFake((...args) => { + expect(args[0]).toEqual({ token: 'new_token' }); + done(); + }); + + spyOn(api, 'updateProfile').and.returnValue(of({ token: 'new_token' } as AuthResult)); + + component.initialize({ name: 'John', id: 'john.doe@email.com' }); + component.name = 'John Doe'; + component.password1 = '1234.zyx'; + component.password2 = '1234.zyx'; + component.submit(); + }); + + it('does not update the profile if e-mail is empty', fakeAsync(async () => { + component.id = ''; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.EMAIL_REQUIRED); + })); + + it('does not update the profile if e-mail is invalid', fakeAsync(async () => { + component.id = 'invalidEMail'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.INVALID_EMAIL); + })); + + it('does not update the profile if password are not equal', fakeAsync(async () => { + component.id = 'john.doe@email.com'; + component.name = 'John Doe'; + component.password1 = '1234.zyx'; + component.password2 = '1234.abc'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.PASSWORDS_NOT_EQUAL); + })); + + it('does not update the profile if password is invalid', fakeAsync(async () => { + component.id = 'john.doe@email.com'; + component.password1 = '123'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.INVALID_PASSWORD); + })); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/auth/register-form.component.spec.ts b/projects/aas-lib/src/test/auth/register-form.component.spec.ts new file mode 100644 index 00000000..44598863 --- /dev/null +++ b/projects/aas-lib/src/test/auth/register-form.component.spec.ts @@ -0,0 +1,117 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AuthResult } from 'common'; + +import { RegisterFormComponent, RegisterFormResult } from '../../lib/auth/register-form/register-form.component'; +import { AuthApiService } from '../../lib/auth/auth-api.service'; +import { ERRORS } from '../../lib/types/errors'; +import { getToken } from '../assets/json-web-token'; + +describe('RegisterFormComponent', () => { + let component: RegisterFormComponent; + let fixture: ComponentFixture; + let modal: NgbActiveModal; + let api: AuthApiService; + let token: string; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [RegisterFormComponent], + providers: [ + NgbModal, + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + HttpClientTestingModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + modal = TestBed.inject(NgbActiveModal); + api = TestBed.inject(AuthApiService); + fixture = TestBed.createComponent(RegisterFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + token = getToken('John'); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('registers a new user', fakeAsync(async () => { + const result: RegisterFormResult = { stayLoggedIn: true, token: token }; + spyOn(modal, 'close').and.callFake((...args) => expect(args[0]).toEqual(result)); + spyOn(api, 'registerUserAsync').and.returnValue(new Promise((result) => result({ token }))); + + component.userId = 'john.doe@email.com'; + component.name = 'John Doe'; + component.password1 = '1234.Zyx'; + component.password2 = '1234.Zyx'; + component.stayLoggedIn = true; + await component.submit(); + expect(component.messages.length).toEqual(0); + expect(modal.close).toHaveBeenCalled(); + })); + + it('does not register a user with empty e-mail', fakeAsync(async () => { + component.userId = ''; + component.passwordAsEMail = true; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.EMAIL_REQUIRED); + })); + + it('does not register a user with invalid e-mail', fakeAsync(async () => { + component.userId = 'invalidEMail'; + component.passwordAsEMail = true; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.INVALID_EMAIL); + })); + + it('does not register a user with empty password', fakeAsync(async () => { + component.userId = 'john.doe@email.com'; + component.password1 = ''; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.PASSWORD_REQUIRED); + })); + + it('does not register a user with invalid password', fakeAsync(async () => { + component.userId = 'john.doe@email.com'; + component.password1 = '123'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.INVALID_PASSWORD); + })); + + it('does not register a user while invalid confirmed password', fakeAsync(async () => { + component.userId = 'john.doe@email.com'; + component.password1 = '1234.Zyx'; + component.password1 = 'Abcd.098'; + await component.submit(); + expect(component.messages.length).toEqual(1); + expect(component.messages[0]).toEqual(ERRORS.PASSWORDS_NOT_EQUAL); + })); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/clipboard.service.spec.ts b/projects/aas-lib/src/test/clipboard.service.spec.ts new file mode 100644 index 00000000..c6b5c97d --- /dev/null +++ b/projects/aas-lib/src/test/clipboard.service.spec.ts @@ -0,0 +1,61 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; + +import { ClipboardService } from '../lib/clipboard.service'; + +describe('ClipboardService', () => { + let clipboard: ClipboardService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + clipboard = TestBed.inject(ClipboardService); + }); + + it('should be created', () => { + expect(clipboard).toBeTruthy(); + }); + + it("can store multiple formats", function () { + clipboard.set("number", 42); + clipboard.set("string", "Hello World!"); + expect(clipboard.contains("number")).toBeTrue(); + expect(clipboard.contains("string")).toBeTrue(); + expect(clipboard.get("number")).toEqual(42); + expect(clipboard.get("string")).toEqual("Hello World!"); + }); + + it("gets undefined for unknown format", function () { + expect(clipboard.get("unknown")).toBeUndefined(); + }); + + it("overwrites an existing format", function () { + clipboard.set("number", 42); + expect(clipboard.get("number")).toEqual(42); + clipboard.set("number", 1); + expect(clipboard.get("number")).toEqual(1); + }); + + it("can clear a specific format", function () { + clipboard.set("number", 42); + clipboard.set("string", "Hello World!"); + clipboard.clear("number"); + expect(clipboard.contains("number")).toBeFalse(); + expect(clipboard.contains()).toBeTrue(); + }); + + it("can clear the clipboard", function () { + clipboard.set("number", 42); + clipboard.set("string", "Hello World!"); + clipboard.clear(); + expect(clipboard.contains("number")).toBeFalse(); + expect(clipboard.contains("string")).toBeFalse(); + expect(clipboard.contains()).toBeFalse(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/convert.spec.ts b/projects/aas-lib/src/test/convert.spec.ts new file mode 100644 index 00000000..f07a6e73 --- /dev/null +++ b/projects/aas-lib/src/test/convert.spec.ts @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TranslateService } from "@ngx-translate/core"; +import { ApplicationError } from "common"; +import { encodeBase64Url, basename, messageToString, normalize, decodeBase64Url, isBase64, mimeTypeToExtension, extensionToMimeType, extension, convertBlobToBase64Async } from "../lib/convert"; + +describe('convert', function () { + describe('basename', function () { + it('gets the file name of a file path', function () { + expect(basename('A:/hello/world/john.doe')).toEqual('john.doe'); + }); + }); + + describe('extension', function () { + it('gets the extension of a file path', function () { + expect(extension('A:/hello/world/john.doe')).toEqual('.doe'); + }); + + it('gets "undefined" of no extension exits', function () { + expect(extension('A:/hello/world/john-doe')).toBeUndefined(); + }); + }); + + describe('normalize', function () { + it('replaces all "\\" with "/"', function () { + expect(normalize('A:\\hello/world\\john.doe')).toEqual('A:/hello/world/john.doe'); + }); + }); + + describe('messageToString', function () { + let translate: jasmine.SpyObj; + + beforeEach(function () { + translate = jasmine.createSpyObj('TranslateService', ['instant'], { currentLang: 'en-us' }); + }); + + it('converts a message of type string', function () { + expect(messageToString('Hello World!', translate)).toEqual('Hello World!'); + }); + + it('converts an ApplicationError', function () { + translate.instant.and.returnValue('Hello {0}!'); + const error = new ApplicationError('Hello World!', 'HELLO_WORLD', 'World'); + expect(messageToString(error, translate)).toEqual('Hello World!'); + }); + }); + + describe('encodeBase64Url', function () { + it('converts an URL to Base64Url string', function () { + const b64url = encodeBase64Url('https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237'); + expect(b64url).toEqual('aHR0cHM6Ly9pb3NiLWluYS5mcmF1bmhvZmVyLmRlL2lkcy9hYXMvNTE3NF83MDAxXzAxMjJfOTIzNw'); + }); + }); + + describe('decodeBase64Url', function () { + it('converts a Base64Url string to an URL', function () { + const url = decodeBase64Url('aHR0cHM6Ly9pb3NiLWluYS5mcmF1bmhvZmVyLmRlL2lkcy9hYXMvNTE3NF83MDAxXzAxMjJfOTIzNw'); + expect(url).toEqual('https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237'); + }); + }); + + + describe('isBase64', function () { + it('indicates that "The quick brown fox jumps over the lazy dog." is not base64 encoded', function () { + expect(isBase64('The quick brown fox jumps over the lazy dog.')).toBeFalse(); + }); + + it('indicates that "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=" is base64 encoded', function () { + expect(isBase64('VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZy4=')).toBeTrue(); + }); + }); + + describe('mimeTypeToExtension', function () { + it('return ".png" for "image/png"', function () { + expect(mimeTypeToExtension('image/png')).toEqual('.png'); + }); + + it('return undefined for an unknown MIME type', function () { + expect(mimeTypeToExtension('unknown')).toBeUndefined(); + }); + + describe('extensionToMimeType', function () { + it('return "image/png" for ".png"', function () { + expect(extensionToMimeType('.png')).toEqual('image/png'); + }); + + it('return undefined for an unknown MIME type', function () { + expect(extensionToMimeType('unknown')).toBeUndefined(); + }); + }); + }); + + describe('convertBlobToBase64Async', function() { + it('converts the Blob content to a base64 encoded string', async function() { + const blob = new Blob(['Hello World!']); + await expectAsync(convertBlobToBase64Async(blob)).toBeResolvedTo('SGVsbG8gV29ybGQh'); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/customer-feedback/customer-feedback.component.spec.ts b/projects/aas-lib/src/test/customer-feedback/customer-feedback.component.spec.ts new file mode 100644 index 00000000..b9b1d838 --- /dev/null +++ b/projects/aas-lib/src/test/customer-feedback/customer-feedback.component.spec.ts @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { CustomerFeedbackComponent } from 'src/lib/customer-feedback/customer-feedback.component'; +import { customerFeedbackReducer } from 'src/lib/customer-feedback/customer-feedback.reducer'; + +describe('CustomerFeedbackComponent', () => { + let component: CustomerFeedbackComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + CustomerFeedbackComponent + ], + providers: [], + imports: [ + CommonModule, + StoreModule.forRoot({ + customerFeedback: customerFeedbackReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(CustomerFeedbackComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/digital-nameplate/digital-nameplate-document.ts b/projects/aas-lib/src/test/digital-nameplate/digital-nameplate-document.ts new file mode 100644 index 00000000..97ed14f2 --- /dev/null +++ b/projects/aas-lib/src/test/digital-nameplate/digital-nameplate-document.ts @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument } from "common"; + +const data: object = { + "id": "AssetAdministrationShell---2CEBD072", + "container": "C:\\Git\\aasportal\\data\\endpoints\\samples", + "endpoint": { + "type": "file", + "address": "IDTA 02006-2-0_Sample Digital Nameplate.aasx" + }, + "idShort": "AssetAdministrationShell---2CEBD072", + "timeStamp": 1677429431327, + "readonly": true, + "modified": false, + "onlineReady": false, + "content": { + "assetAdministrationShells": [], + "submodels": [ + { + "idShort": "Nameplate", + "modelType": "Submodel", + "id": "www.example.com/ids/sm/1225_9020_5022_1974", + "kind": "Instance", + "submodelElements": [ + { + "idShort": "ManufacturerName", + "modelType": "MultiLanguageProperty", + "parent": { + "type": "ModelReference", + "keys": [{ + "type": "Submodel", + "value": "www.example.com/ids/sm/1225_9020_5022_1974" + } + ] + }, + "kind": "Instance", + "value": [{ + "language": "de", + "text": "Muster AG" + } + ] + } + ] + } + ], + "conceptDescriptions": [] + } +}; + +export const nameplate = data as AASDocument; \ No newline at end of file diff --git a/projects/aas-lib/src/test/digital-nameplate/digital-nameplate.component.spec.ts b/projects/aas-lib/src/test/digital-nameplate/digital-nameplate.component.spec.ts new file mode 100644 index 00000000..a35ce704 --- /dev/null +++ b/projects/aas-lib/src/test/digital-nameplate/digital-nameplate.component.spec.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { SimpleChange } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { selectElement } from 'common'; +import { nameplate } from './digital-nameplate-document'; +import { DigitalNameplateComponent } from 'src/lib/digital-nameplate/digital-nameplate.component'; + +describe('DigitalNameplateComponent', () => { + let component: DigitalNameplateComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + DigitalNameplateComponent + ], + providers: [], + imports: [ + CommonModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(DigitalNameplateComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + component.submodels = [{ document: nameplate, submodel: selectElement(nameplate.content!, 'Nameplate')! }]; + component.ngOnChanges({ 'submodels': new SimpleChange(null, component.submodels, true) }); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('provides a "ManufacturerName" property', function () { + expect(component.nameplates[0].manufacturerName).toEqual('Muster AG'); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/document.service.spec.ts b/projects/aas-lib/src/test/document.service.spec.ts new file mode 100644 index 00000000..fb0c9e0e --- /dev/null +++ b/projects/aas-lib/src/test/document.service.spec.ts @@ -0,0 +1,24 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; + +import { DocumentService } from '../lib/document.service'; + +describe('DocumentService', () => { + let service: DocumentService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(DocumentService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/download.service.spec.ts b/projects/aas-lib/src/test/download.service.spec.ts new file mode 100644 index 00000000..310820ce --- /dev/null +++ b/projects/aas-lib/src/test/download.service.spec.ts @@ -0,0 +1,82 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClient } from '@angular/common/http'; +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { EMPTY } from 'rxjs'; + +import { DownloadService } from '../lib/download.service'; + +describe('DownloadService', () => { + let service: DownloadService; + let httpTestingController: HttpTestingController; + let httpClient: HttpClient; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [], + imports: [ + HttpClientTestingModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + + ] + }); + + service = TestBed.inject(DownloadService); + httpTestingController = TestBed.inject(HttpTestingController); + httpClient = TestBed.inject(HttpClient); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + describe('uploadDocuments', function () { + it('POST: /api/v1/containers/:url/documents/:id', function () { + const file = jasmine.createSpyObj( + ['arrayBuffer', 'slice', 'stream', 'text']); + + service.uploadDocuments('file:///samples', file).subscribe(); + const req = httpTestingController.expectOne('/api/v1/containers/ZmlsZTovLy9zYW1wbGVz/documents'); + expect(req.request.method).toEqual('POST'); + expect(req.request.body).toBeDefined(); + }); + }); + + describe('downloadDocumentAsync', function () { + it('downloads an AASX package file', async function () { + const spy = spyOn(httpClient, 'get').and.returnValue(EMPTY); + await expectAsync(service.downloadDocumentAsync( + 'http://localhost:1234', + 'https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237', + 'Test.aasx' + )).toBeResolved(); + + expect(spy).toHaveBeenCalled(); + }); + }); + + describe('downloadFileAsync', function () { + it('downloads a file resource', async function () { + const spy = spyOn(httpClient, 'get').and.returnValue(EMPTY); + await expectAsync(service.downloadFileAsync('http://localhost/folder/file', 'Test.txt')).toBeResolved(); + expect(spy).toHaveBeenCalled(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/library-table/library-table.component.spec.ts b/projects/aas-lib/src/test/library-table/library-table.component.spec.ts new file mode 100644 index 00000000..2138d7d4 --- /dev/null +++ b/projects/aas-lib/src/test/library-table/library-table.component.spec.ts @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { Library } from 'common'; + +import { LibraryTableComponent } from '../../lib/library-table/library-table.component'; + +describe('LibraryTableComponent', () => { + let component: LibraryTableComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [LibraryTableComponent], + providers: [], + imports: [ + CommonModule, + NgbModule, + TranslateModule.forRoot({ + defaultLanguage: 'en-us', + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) +] + }); + + fixture = TestBed.createComponent(LibraryTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('has an initial page size of 10', function () { + expect(component.pageSize).toEqual(10); + }); + + it('shows page 1', function () { + expect(component.page).toEqual(1); + }); + + describe('with pagination', function () { + let size: number; + + beforeEach(function () { + const collection: Library[] = []; + + size = component.pageSize + 1; + for (let i = 1; i <= size; i++) { + collection.push({ + name: 'Library ' + i, + description: 'Description library ' + i, + license: 'MIT', + homepage: 'https://www.fraunhofer.de', + version: '1.' + i, + }); + } + + component.collection = collection; + fixture.detectChanges(); + + component.ngOnChanges({ + "collection": new SimpleChange([], collection, true) + }); + }); + + it('has 11 libraries', function () { + expect(component.size).toEqual(size); + }); + + it('displays the first page with 10 entries', function () { + expect(component.libraries.length).toEqual(component.pageSize); + }); + + it('provides 2 pages', function () { + expect(component.page).toEqual(1); + expect(component.libraries.length).toEqual(10); + + component.page = 2; + fixture.detectChanges(); + component.refreshLibraries(); + expect(component.libraries.length).toEqual(1); + }); + }); + + describe('show/hide pagination', function () { + let size: number; + + beforeEach(function () { + const collection: Library[] = []; + + size = 10; + for (let i = 1; i <= size; i++) { + collection.push({ + name: 'Library ' + i, + description: 'Description library ' + i, + license: 'MIT', + homepage: 'https://www.fraunhofer.de', + version: '1.' + i, + }); + } + + component.collection = collection; + fixture.detectChanges(); + + component.ngOnChanges({ + "collection": new SimpleChange([], collection, true) + }) + }); + + it('hides pagination if size <= pageSize', function () { + component.pageSize = component.size; + fixture.detectChanges(); + const element: HTMLElement = fixture.debugElement.nativeElement; + const pagination: HTMLElement | null = element.querySelector('ngb-pagination'); + expect(pagination).toBeNull(); + }); + + it('shows pagination if size > pageSize', function () { + component.pageSize = component.size - 1; + fixture.detectChanges(); + const element: HTMLElement = fixture.debugElement.nativeElement; + const pagination: HTMLElement | null = element.querySelector('ngb-pagination'); + expect(pagination).toBeDefined(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/localize/localize.component.spec.ts b/projects/aas-lib/src/test/localize/localize.component.spec.ts new file mode 100644 index 00000000..95fe9b13 --- /dev/null +++ b/projects/aas-lib/src/test/localize/localize.component.spec.ts @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { first } from 'rxjs'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { CommonModule } from '@angular/common'; + +import { CultureInfo } from '../../lib/localize/culture-info'; +import { LocalizeComponent } from '../../lib/localize/localize.component'; +import { WindowService } from '../../lib/window.service'; + +describe('LocalizeComponent', () => { + let component: LocalizeComponent; + let fixture: ComponentFixture; + let window: jasmine.SpyObj; + + beforeEach(() => { + window = jasmine.createSpyObj(['getLocalStorageItem', 'setLocalStorageItem']); + + TestBed.configureTestingModule({ + declarations: [LocalizeComponent], + providers: [ + { + provide: WindowService, + useValue: window + } + ], + imports: [ + CommonModule, + NgbModule, + TranslateModule.forRoot({ + defaultLanguage: 'en-us', + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(LocalizeComponent); + component = fixture.componentInstance; + component.languages = ['en-us', 'de-de']; + component.ngOnChanges({ languages: new SimpleChange(undefined, component.languages, true) }); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('provides a list of supported languages', function (done: DoneFn) { + window.getLocalStorageItem.and.returnValue(null); + component.cultures.pipe(first()).subscribe(value => { + expect(value.map(item => item.localeId)).toEqual(['en-us', 'de-de']); + done(); + }); + }); + + it('returns the current language', function (done: DoneFn) { + component.culture.pipe(first()).subscribe(value => { + expect(value?.localeId).toEqual('en-us'); + done(); + }); + }); + + it('allows setting a new current language', function (done: DoneFn) { + component.cultures.pipe(first()).subscribe(value => { + component.setCulture(value.find(item => item.localeId === 'de-de') as CultureInfo); + component.culture.pipe(first()).subscribe(value => { + expect(value?.localeId).toEqual('de-de'); + done(); + }) + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/max-length/max-length.pipe.spec.ts b/projects/aas-lib/src/test/max-length/max-length.pipe.spec.ts new file mode 100644 index 00000000..cc44bb06 --- /dev/null +++ b/projects/aas-lib/src/test/max-length/max-length.pipe.spec.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { MaxLengthPipe } from "src/lib/max-length.pipe"; + +describe('MaxLengthPipe', () => { + it('create an instance', () => { + const pipe = new MaxLengthPipe(); + expect(pipe).toBeTruthy(); + }); + + it('does not transform if text length <= max', function () { + const pipe = new MaxLengthPipe(); + expect(pipe.transform('0123456789', 10)).toEqual('0123456789'); + }); + + it('does not transform if text length <= max', function () { + const pipe = new MaxLengthPipe(); + expect(pipe.transform('0123456789', 5)).toEqual('0...9'); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/message-table/message-table.component.spec.ts b/projects/aas-lib/src/test/message-table/message-table.component.spec.ts new file mode 100644 index 00000000..941477c7 --- /dev/null +++ b/projects/aas-lib/src/test/message-table/message-table.component.spec.ts @@ -0,0 +1,332 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { Store, StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { Message } from 'common'; +import { first } from 'rxjs'; +import { messageTableReducer } from 'src/lib/message-table/massage-table.reducer'; +import { MessageTableComponent } from 'src/lib/message-table/message-table.component'; +import { MessageTableFeatureState } from 'src/lib/message-table/message-table.state'; +import { SortableHeaderDirective } from 'src/public-api'; + +describe('MessageTableComponent', () => { + let component: MessageTableComponent; + let fixture: ComponentFixture; + let collection: Message[]; + const sizePerType = 5; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + MessageTableComponent, + SortableHeaderDirective + ], + providers: [], + imports: [ + CommonModule, + NgbModule, + StoreModule.forRoot( + { + messageTable: messageTableReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(MessageTableComponent); + component = fixture.componentInstance; + + collection = []; + for (let i = 1; i <= sizePerType; i++) { + collection.push({ + type: 'Info', + timestamp: Date.now(), + text: 'Info' + i + }); + collection.push({ + type: 'Warning', + timestamp: Date.now(), + text: 'Warning' + i + }); + collection.push({ + type: 'Error', + timestamp: Date.now(), + text: 'Error' + i + }); + } + + component.collection = collection; + fixture.detectChanges(); + + component.ngOnChanges({ + "collection": new SimpleChange([], collection, true) + }); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('has an initial page size of 10', function () { + expect(component.pageSize).toEqual(10); + }); + + it('shows page 1', function () { + expect(component.page).toEqual(1); + }); + + it('provides a collection with all messages (5 errors, 5 warnings, 5 info)', function () { + expect(component.collection.length).toEqual(3 * sizePerType); + }); + + it('shows initial only errors', function () { + expect(component.showError).toBeTrue(); + expect(component.showInfo).toBeFalse(); + expect(component.showWarning).toBeFalse(); + }); + + it('supports 3 sortable headers', function () { + expect(component.headers?.length).toEqual(3); + }); + + describe('show only errors', function () { + beforeEach(function () { + if (!component.showError) { + component.toggleShowError(); + } + + if (component.showInfo) { + component.toggleShowInfo(); + } + + if (component.showWarning) { + component.toggleShowWarning(); + } + + fixture.detectChanges(); + }); + + it('shows only errors', function () { + expect(component.size).toEqual(sizePerType); + expect(component.messages.every(message => message.type === 'Error')).toBeTrue(); + }); + + it('hides the pagination', function () { + const element: HTMLElement = fixture.debugElement.nativeElement; + const pagination: HTMLElement = element.querySelector('ngb-pagination')!; + expect(pagination).toBeNull(); + }); + }); + + describe('show only warnings', function () { + beforeEach(function () { + if (component.showError) { + component.toggleShowError(); + } + + if (component.showInfo) { + component.toggleShowInfo(); + } + + if (!component.showWarning) { + component.toggleShowWarning(); + } + + fixture.detectChanges(); + }); + + it('shows only warnings', function () { + expect(component.size).toEqual(sizePerType); + expect(component.messages.every(message => message.type === 'Warning')).toBeTrue(); + }); + + it('hides the pagination', function () { + const element: HTMLElement = fixture.debugElement.nativeElement; + const pagination: HTMLElement = element.querySelector('ngb-pagination')!; + expect(pagination).toBeNull(); + }); + }); + + describe('show only info', function () { + beforeEach(function () { + if (component.showError) { + component.toggleShowError(); + } + + if (!component.showInfo) { + component.toggleShowInfo(); + } + + if (component.showWarning) { + component.toggleShowWarning(); + } + + fixture.detectChanges(); + }); + + it('shows only info', function () { + expect(component.size).toEqual(sizePerType); + expect(component.messages.every(message => message.type === 'Info')).toBeTrue(); + }); + + it('hides the pagination', function () { + const element: HTMLElement = fixture.debugElement.nativeElement; + const pagination: HTMLElement = element.querySelector('ngb-pagination')!; + expect(pagination).toBeNull(); + }); + }); + + describe('show all messages', function () { + beforeEach(function () { + if (!component.showError) { + component.toggleShowError(); + } + + if (!component.showInfo) { + component.toggleShowInfo(); + } + + if (!component.showWarning) { + component.toggleShowWarning(); + } + }); + + it('shows all messages', function () { + expect(component.size).toEqual(3 * sizePerType); + }); + + it('shows the pagination', function () { + const element: HTMLElement = fixture.debugElement.nativeElement; + const pagination: HTMLElement = element.querySelector('ngb-pagination')!; + expect(pagination).toBeDefined(); + }); + + it('provides 2 pages (10, 5)', function () { + expect(component.page).toEqual(1); + expect(component.messages).toEqual(component.collection.slice(0, 10)); + + component.page = 2; + fixture.detectChanges(); + component.refreshMessages(); + expect(component.messages).toEqual(component.collection.slice(-5)); + }); + }); + + describe('sorting', function () { + let store: Store; + + beforeEach(function () { + store = TestBed.inject(Store); + + if (!component.showError) { + component.toggleShowError(); + } + + if (!component.showInfo) { + component.toggleShowInfo(); + } + + if (!component.showWarning) { + component.toggleShowWarning(); + } + }); + + it('shows the origin order', function (done: DoneFn) { + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual(''); + expect(state.direction).toEqual(''); + done(); + }); + }); + + it('can sort type column in ascending order', function (done: DoneFn) { + component.onSort({ column: 'type', direction: 'asc' }); + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual('type'); + expect(state.direction).toEqual('asc'); + done(); + }); + }); + + it('can sort type column in descending order', function (done: DoneFn) { + component.onSort({ column: 'type', direction: 'desc' }); + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual('type'); + expect(state.direction).toEqual('desc'); + done(); + }); + }); + + it('can sort timestamp column in ascending order', function (done: DoneFn) { + component.onSort({ column: 'timestamp', direction: 'asc' }); + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual('timestamp'); + expect(state.direction).toEqual('asc'); + done(); + }); + }); + + it('can sort timestamp column in descending order', function (done: DoneFn) { + component.onSort({ column: 'timestamp', direction: 'desc' }); + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual('timestamp'); + expect(state.direction).toEqual('desc'); + done(); + }); + }); + + it('can sort text column in ascending order', function (done: DoneFn) { + component.onSort({ column: 'text', direction: 'asc' }); + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual('text'); + expect(state.direction).toEqual('asc'); + done(); + }); + }); + + it('can sort text column in descending order', function (done: DoneFn) { + component.onSort({ column: 'text', direction: 'desc' }); + store.select(state => state.messageTable).pipe(first()).subscribe(state => { + expect(state.showError).toBeTrue(); + expect(state.showInfo).toBeTrue(); + expect(state.showWarning).toBeTrue(); + expect(state.column).toEqual('text'); + expect(state.direction).toEqual('desc'); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/notify/notify.service.spec.ts b/projects/aas-lib/src/test/notify/notify.service.spec.ts new file mode 100644 index 00000000..47afbe89 --- /dev/null +++ b/projects/aas-lib/src/test/notify/notify.service.spec.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { NotifyService } from '../../lib/notify/notify.service'; + +describe('NotifyService', () => { + let service: NotifyService; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [], + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + service = TestBed.inject(NotifyService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/score/score.component.spec.ts b/projects/aas-lib/src/test/score/score.component.spec.ts new file mode 100644 index 00000000..ca237b81 --- /dev/null +++ b/projects/aas-lib/src/test/score/score.component.spec.ts @@ -0,0 +1,91 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { SimpleChange } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ScoreComponent } from 'src/lib/score/score.component'; + + +describe('ScoreComponent', () => { + let component: ScoreComponent; + let fixture: ComponentFixture; + let positiveDiv: HTMLDivElement; + let negativeDiv: HTMLDivElement; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ScoreComponent] + }); + + fixture = TestBed.createComponent(ScoreComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + const element: HTMLElement = fixture.debugElement.nativeElement; + positiveDiv = element.querySelector('.score-pos')!; + negativeDiv = element.querySelector('.score-neg')!; + }); + + it('should create', () => { + expect(component).toBeTruthy(); + expect(positiveDiv).toBeTruthy(); + expect(negativeDiv).toBeTruthy(); + }); + + it('it shows a positive score', function () { + component.score = 0.42; + component.ngOnChanges({ score: new SimpleChange(0, component.score, true) }); + fixture.detectChanges(); + + expect(component.positive).toEqual(42); + expect(component.negative).toEqual(0); + + expect(positiveDiv.style.width).toEqual('42%'); + expect(negativeDiv.style.width).toEqual('0%'); + }); + + it('it shows a negative score', function () { + component.score = -0.42; + component.ngOnChanges({ score: new SimpleChange(0, component.score, true) }); + fixture.detectChanges(); + + expect(component.negative).toEqual(42); + expect(component.positive).toEqual(0); + expect(positiveDiv.style.width).toEqual('0%'); + expect(negativeDiv.style.width).toEqual('42%'); + }); + + it('it shows an undefined score', function () { + component.score = 0.0; + component.ngOnChanges({ score: new SimpleChange(0, component.score, true) }); + fixture.detectChanges(); + + expect(component.negative).toEqual(0); + expect(component.positive).toEqual(0); + expect(positiveDiv.style.width).toEqual('0%'); + expect(negativeDiv.style.width).toEqual('0%'); + }); + + it('it limits the positive score to 100%', function () { + component.score = 1234567.89; + component.ngOnChanges({ score: new SimpleChange(0, component.score, true) }); + fixture.detectChanges(); + + expect(component.positive).toEqual(100); + expect(component.negative).toEqual(0); + }); + + it('it shows a negative score', function () { + component.score = -1234567.89; + component.ngOnChanges({ score: new SimpleChange(0, component.score, true) }); + fixture.detectChanges(); + + expect(component.negative).toEqual(100); + expect(component.positive).toEqual(0); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/secured-image/secured-image.component.spec.ts b/projects/aas-lib/src/test/secured-image/secured-image.component.spec.ts new file mode 100644 index 00000000..99a8368e --- /dev/null +++ b/projects/aas-lib/src/test/secured-image/secured-image.component.spec.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; + +import { SecuredImageComponent } from '../../lib/secured-image/secured-image.component'; +import { CommonModule } from '@angular/common'; + +describe('SecuredImageComponent', () => { + let component: SecuredImageComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [SecuredImageComponent], + imports: [ + CommonModule, + HttpClientTestingModule] + }); + fixture = TestBed.createComponent(SecuredImageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/sortable-header/sortable-header.directive.spec.ts b/projects/aas-lib/src/test/sortable-header/sortable-header.directive.spec.ts new file mode 100644 index 00000000..875f42d3 --- /dev/null +++ b/projects/aas-lib/src/test/sortable-header/sortable-header.directive.spec.ts @@ -0,0 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { SortableHeaderDirective } from "src/lib/sortable-header.directive"; + +describe('SortableHeaderDirective', () => { + it('should create an instance', () => { + const directive = new SortableHeaderDirective(); + expect(directive).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/toolbar/toolbar.component.spec.ts b/projects/aas-lib/src/test/toolbar/toolbar.component.spec.ts new file mode 100644 index 00000000..a4c6c0fb --- /dev/null +++ b/projects/aas-lib/src/test/toolbar/toolbar.component.spec.ts @@ -0,0 +1,404 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { BehaviorSubject, first } from 'rxjs'; +import { + Toolbar, + ToolbarButton, + ToolbarCheckbox, + ToolbarColorPicker, + ToolbarCommandCanExecute, + ToolbarCommandExecute, + ToolbarDropDown, + ToolbarFileInput, + ToolbarMenuItem, + ToolbarOption, + ToolbarRadio, + ToolbarSelect, + ToolbarSwitch, + ToolbarTextInput +} from '../../lib/toolbar/toolbar'; + +import { ToolbarService } from '../../lib/toolbar/toolbar.service'; +import { ToolbarComponent } from '../../lib/toolbar/toolbar.component'; + +describe('ToolbarComponent', () => { + let component: ToolbarComponent; + let service: ToolbarService; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ToolbarComponent], + providers: [], + imports: [ + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + + ] + }); + + fixture = TestBed.createComponent(ToolbarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + + service = TestBed.inject(ToolbarService); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('toolbar button', function () { + let toolbar: Toolbar; + let button: ToolbarButton; + let execute: jasmine.Spy; + let canExecute: jasmine.Spy; + + beforeEach(function () { + execute = jasmine.createSpy('execute'); + canExecute = jasmine.createSpy('canExecute').and.returnValue(true); + button = service.createButton('bi bi-gear', execute, canExecute); + toolbar = { groups: [service.createGroup([button])] }; + service.setToolbar(toolbar); + }); + + it('should provide a button', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const buttonElement: HTMLButtonElement = toolbarElement.querySelector('button')!; + buttonElement.dispatchEvent(new Event('click')); + expect(execute).toHaveBeenCalled(); + done(); + }); + }); + }); + + describe('radio button', function () { + let toolbar: Toolbar; + let radio1: ToolbarRadio; + let radio2: ToolbarRadio; + let checked1: BehaviorSubject; + let checked2: BehaviorSubject; + let execute1: ToolbarCommandExecute; + let execute2: ToolbarCommandExecute; + + beforeEach(function () { + checked1 = new BehaviorSubject(true); + checked2 = new BehaviorSubject(false); + + execute1 = () => { + const value = checked1.getValue(); + checked1.next(!value); + checked2.next(value); + }; + + execute2 = () => () => { + const value = checked2.getValue(); + checked2.next(!value); + checked1.next(value); + };; + + radio1 = service.createRadio('bi bi-1-circle', '1', checked1.asObservable(), execute1); + radio2 = service.createRadio('bi bi-2-circle', '2', checked2.asObservable(), execute2); + toolbar = { groups: [service.createGroup([radio1, radio2])] }; + service.setToolbar(toolbar); + }); + + it('should provide radio buttons', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const radio1Element: HTMLInputElement = toolbarElement.querySelector('#' + radio1.id)!; + const radio2Element: HTMLInputElement = toolbarElement.querySelector('#' + radio2.id)!; + expect(radio1Element.checked).toBeTrue(); + expect(radio2Element.checked).toBeFalse(); + + radio2Element.checked = true; + checked2.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(radio1Element.checked).toBeFalse(); + expect(radio2Element.checked).toBeTrue(); + }); + + radio1Element.checked = true; + checked1.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(radio1Element.checked).toBeTrue(); + expect(radio2Element.checked).toBeFalse(); + done(); + }); + }); + }); + }); + + describe('checkbox', function () { + let toolbar: Toolbar; + let checkbox: ToolbarCheckbox; + let execute: ToolbarCommandExecute; + let canExecute: jasmine.Spy; + let checked: BehaviorSubject; + + beforeEach(function () { + checked = new BehaviorSubject(false); + + execute = () => { + checked.next(!checked.getValue()); + }; + + canExecute = jasmine.createSpy('canExecute').and.returnValue(true); + checkbox = service.createCheckbox('bi bi-check', checked.asObservable(), execute, canExecute); + toolbar = { groups: [service.createGroup([checkbox])] }; + service.setToolbar(toolbar); + }); + + it('should provide a checkbox', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const checkboxElement: HTMLInputElement = toolbarElement.querySelector('#' + checkbox.id)!; + expect(checkboxElement.checked).toBeFalse(); + + checkboxElement.checked = true; + checked.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(checkboxElement.checked).toBeTrue(); + }); + + checkboxElement.checked = false; + checked.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(checkboxElement.checked).toBeFalse(); + done(); + }); + }); + }); + }); + + describe('switch', function () { + let toolbar: Toolbar; + let toolbarSwitch: ToolbarSwitch; + let execute: ToolbarCommandExecute; + let canExecute: jasmine.Spy; + let checked: BehaviorSubject; + + beforeEach(function () { + checked = new BehaviorSubject(false); + + execute = () => { + checked.next(!checked.getValue()); + }; + + canExecute = jasmine.createSpy('canExecute').and.returnValue(true); + toolbarSwitch = service.createSwitch('switch', checked.asObservable(), execute, canExecute); + toolbar = { groups: [service.createGroup([toolbarSwitch])] }; + service.setToolbar(toolbar); + }); + + it('should provide a switch', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const switchElement: HTMLInputElement = toolbarElement.querySelector('#' + toolbarSwitch.id)!; + expect(switchElement.checked).toBeFalse(); + + switchElement.checked = true; + checked.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(switchElement.checked).toBeTrue(); + }); + + switchElement.checked = false; + checked.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(switchElement.checked).toBeFalse(); + done(); + }); + }); + }); + }); + + describe('dropdown menu', function () { + let toolbar: Toolbar; + let dropdown: ToolbarDropDown; + let menuItem: ToolbarMenuItem; + let execute: jasmine.Spy; + + beforeEach(function () { + execute = jasmine.createSpy('execute'); + menuItem = service.createMenuItem('command', execute); + dropdown = service.createDropDown('', [menuItem]); + + toolbar = { groups: [service.createGroup([dropdown])] }; + service.setToolbar(toolbar); + }); + + it('provides a dropdown menu', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const dropdownElement: HTMLDivElement = toolbarElement.querySelector('#' + dropdown.id)!; + dropdownElement.dispatchEvent(new Event('click')); + fixture.detectChanges(); + const menuItemElement: HTMLButtonElement = toolbarElement.querySelector('#' + menuItem.id)! + menuItemElement.dispatchEvent(new Event('click')); + expect(execute).toHaveBeenCalled(); + done(); + }); + }); + }); + + describe('text input', function () { + let toolbar: Toolbar; + let textInput: ToolbarTextInput; + let execute: ToolbarCommandExecute; + let canExecute: jasmine.Spy; + let value: BehaviorSubject; + + beforeEach(function () { + value = new BehaviorSubject(''); + + execute = (argument: string) => { + value.next(argument); + }; + + canExecute = jasmine.createSpy('canExecute').and.returnValue(true); + textInput = service.createTextInput('bi bi-pen', '', 'text input', execute); + toolbar = { groups: [service.createGroup([textInput])] }; + service.setToolbar(toolbar); + }); + + it('should provide a text input', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const inputElement: HTMLInputElement = toolbarElement.querySelector('#' + textInput.id)!; + expect(inputElement.value).toEqual(''); + + inputElement.value = 'Hello World!'; + inputElement.dispatchEvent(new Event('input')); + value.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(inputElement.value).toEqual('Hello World!'); + done(); + }); + }); + }); + }); + + describe('color picker', function () { + let toolbar: Toolbar; + let colorPicker: ToolbarColorPicker; + let execute: ToolbarCommandExecute; + let color: BehaviorSubject; + + beforeEach(function () { + color = new BehaviorSubject('#000000'); + + execute = (argument: string) => { + color.next(argument); + }; + + colorPicker = service.createColorPicker(color, execute); + toolbar = { groups: [service.createGroup([colorPicker])] }; + service.setToolbar(toolbar); + }); + + it('should provide a color picker', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const colorElement: HTMLInputElement = toolbarElement.querySelector('#' + colorPicker.id)!; + + colorElement.value = '#123456'; + colorElement.dispatchEvent(new Event('change')); + color.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(colorElement.value).toEqual('#123456'); + done(); + }); + }); + }); + }); + + describe('file input', function () { + let toolbar: Toolbar; + let fileInput: ToolbarFileInput; + let execute: ToolbarCommandExecute; + let canExecute: jasmine.Spy; + + beforeEach(function () { + execute = (argument: FileList) => { + }; + + canExecute = jasmine.createSpy('canExecute').and.returnValue(true); + fileInput = service.createFileInput('select file', execute); + toolbar = { groups: [service.createGroup([fileInput])] }; + service.setToolbar(toolbar); + }); + + it('should provide a file select', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const inputElement: HTMLInputElement = toolbarElement.querySelector('#' + fileInput.id)!; + const buttonElement: HTMLButtonElement = toolbarElement.querySelector('#' + fileInput.id + 'Addon')!; + expect(inputElement).toBeTruthy(); + expect(buttonElement).toBeTruthy(); + done(); + }); + }); + }); + + describe('select', function () { + let toolbar: Toolbar; + let select: ToolbarSelect; + let option1: ToolbarOption; + let option2: ToolbarOption; + let execute: ToolbarCommandExecute; + let value: BehaviorSubject; + + beforeEach(function () { + value = new BehaviorSubject('1'); + execute = (argument: string) => { + value.next(argument); + }; + + option1 = service.createOption('1', '1'); + option2 = service.createOption('2', '2'); + select = service.createSelect([option1, option2], value.asObservable(), execute); + toolbar = { groups: [service.createGroup([select])] }; + service.setToolbar(toolbar); + }); + + it('provides a select', function (done: DoneFn) { + service.groups.pipe(first()).subscribe(() => { + fixture.detectChanges(); + const toolbarElement: HTMLElement = fixture.debugElement.nativeElement; + const selectElement: HTMLSelectElement = toolbarElement.querySelector('#' + select.id)!; + expect(selectElement.value).toEqual(option1.value); + + selectElement.value = option2.value; + selectElement.dispatchEvent(new Event('change')); + }); + + value.asObservable().pipe(first()).subscribe(() => { + fixture.detectChanges(); + expect(value.getValue()).toEqual(option2.value); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/toolbar/toolbar.service.spec.ts b/projects/aas-lib/src/test/toolbar/toolbar.service.spec.ts new file mode 100644 index 00000000..63d73577 --- /dev/null +++ b/projects/aas-lib/src/test/toolbar/toolbar.service.spec.ts @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { first } from 'rxjs'; +import { Toolbar } from '../../lib/toolbar/toolbar'; +import { ToolbarService } from '../../lib/toolbar/toolbar.service'; + +describe('ToolbarService', () => { + let service: ToolbarService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ToolbarService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('allows set and reset a specific toolbar', function (done: DoneFn) { + const toolbar: Toolbar = { + groups: [ + service.createGroup( + [ + service.createButton('bi bi-gear', () => {}, () => true), + ] + ) + ] + } + + service.setToolbar(toolbar); + service.groups.pipe(first()).subscribe(values => { + expect(values).toEqual(toolbar.groups); + }); + + service.setToolbar(); + service.groups.pipe(first()).subscribe(values => { + expect(values.length).toEqual(0); + done(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/web-socket-factory.service.spec.ts b/projects/aas-lib/src/test/web-socket-factory.service.spec.ts new file mode 100644 index 00000000..e4e24975 --- /dev/null +++ b/projects/aas-lib/src/test/web-socket-factory.service.spec.ts @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { WebSocketData } from 'common'; +import { WebSocketSubject } from 'rxjs/webSocket'; + +import { WebSocketFactoryService } from '../lib/web-socket-factory.service'; + +describe('WindowService', () => { + let service: WebSocketFactoryService; + let webSocket: WebSocketSubject; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(WebSocketFactoryService); + }); + + afterEach(function(){ + webSocket?.unsubscribe(); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('creates a new WebSocket connection', function () { + webSocket = service.create("http://localhost:8888"); + expect(webSocket).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/src/test/window.service.spec.ts b/projects/aas-lib/src/test/window.service.spec.ts new file mode 100644 index 00000000..c8a74a01 --- /dev/null +++ b/projects/aas-lib/src/test/window.service.spec.ts @@ -0,0 +1,23 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { WindowService } from 'src/lib/window.service'; + +describe('WindowService', () => { + let service: WindowService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(WindowService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-lib/tsconfig.json b/projects/aas-lib/tsconfig.json new file mode 100644 index 00000000..ff31b78b --- /dev/null +++ b/projects/aas-lib/tsconfig.json @@ -0,0 +1,38 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./build", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "target": "es2022", + "module": "es2022", + "lib": [ + "es2022", + "dom" + ], + "types": [ + "@angular/localize", + "jasmine" + ] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} \ No newline at end of file diff --git a/projects/aas-lib/tsconfig.lib.json b/projects/aas-lib/tsconfig.lib.json new file mode 100644 index 00000000..fb73cf61 --- /dev/null +++ b/projects/aas-lib/tsconfig.lib.json @@ -0,0 +1,13 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/lib", + "declaration": true, + "declarationMap": true, + "inlineSources": true + }, + "exclude": [ + "src/test/**" + ] +} diff --git a/projects/aas-lib/tsconfig.lib.prod.json b/projects/aas-lib/tsconfig.lib.prod.json new file mode 100644 index 00000000..06de549e --- /dev/null +++ b/projects/aas-lib/tsconfig.lib.prod.json @@ -0,0 +1,10 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.lib.json", + "compilerOptions": { + "declarationMap": false + }, + "angularCompilerOptions": { + "compilationMode": "partial" + } +} diff --git a/projects/aas-lib/tsconfig.spec.json b/projects/aas-lib/tsconfig.spec.json new file mode 100644 index 00000000..d17278f0 --- /dev/null +++ b/projects/aas-lib/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "@angular/localize", + "jasmine" + ] + }, + "include": [ + "src/test/**/*.ts" + ] +} \ No newline at end of file diff --git a/projects/aas-portal/.eslintrc.json b/projects/aas-portal/.eslintrc.json new file mode 100644 index 00000000..f9f1c647 --- /dev/null +++ b/projects/aas-portal/.eslintrc.json @@ -0,0 +1,37 @@ +{ + "extends": "../../.eslintrc.json", + "ignorePatterns": [ + "!**/*" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "fhg", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "fhg", + "style": "kebab-case" + } + ] + } + }, + { + "files": [ + "*.html" + ], + "rules": {} + } + ] +} diff --git a/projects/aas-portal/karma.conf.cjs b/projects/aas-portal/karma.conf.cjs new file mode 100644 index 00000000..c19a1f5a --- /dev/null +++ b/projects/aas-portal/karma.conf.cjs @@ -0,0 +1,56 @@ +// Karma configuration file, see link for more information +// https://karma-runner.github.io/1.0/config/configuration-file.html + +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-junit-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + files: [ + { pattern: './src/**/*.ts', type: 'js' }, + ], + jasmineHtmlReporter: { + suppressAll: true // removes the duplicated traces + }, + junitReporter:{ + outputDir: '../../reports', + outputFile: 'aas-portal.xml', + useBrowserName: false + }, + coverageReporter: { + dir: require('path').join(__dirname, '../../reports/aas-portal'), + subdir: '.', + reporters: [ + { type: 'html' }, + { type: 'json-summary' }, + { type: 'cobertura' } + ] + }, + reporters: ['progress', 'kjhtml', 'junit'], + browsers: ['ChromeHeadlessNoSandbox'], + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: 'ChromeHeadless', + flags: ['--no-sandbox'] + } + }, + singleRun: true, + restartOnFileChange: true + }); +}; diff --git a/projects/aas-portal/nginx.conf b/projects/aas-portal/nginx.conf new file mode 100644 index 00000000..86b2349f --- /dev/null +++ b/projects/aas-portal/nginx.conf @@ -0,0 +1,45 @@ + +worker_processes 1; + +events { + worker_connections 1024; +} + +http { + include mime.types; + default_type application/octet-stream; + + sendfile on; + keepalive_timeout 65; + client_max_body_size 100M; + + server { + listen 80 default_server; + listen [::]:80 default_server; + server_name aasportal; + + location / { + root /usr/share/nginx/html; + try_files $uri $uri/ /index.html; + } + + location /api/ { + proxy_pass http://172.25.0.11:1337; + proxy_http_version 1.1; + } + + location /websocket { + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_cache_bypass $http_upgrade + proxy_set_header Host $host; + proxy_pass http://172.25.0.11:1337; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root html; + } + } +} diff --git a/projects/aas-portal/package.json b/projects/aas-portal/package.json new file mode 100644 index 00000000..882d216c --- /dev/null +++ b/projects/aas-portal/package.json @@ -0,0 +1,78 @@ +{ + "name": "aas-portal", + "version": "3.0.0", + "author": "Fraunhofer IOSB-INA", + "description": "Web-based visualization and control of asset administration shells.", + "homepage": "https://www.iosb-ina.fraunhofer.de/", + "license": "Apache-2.0", + "type": "module", + "scripts": { + "ng": "ng", + "serve": "ng serve --host=127.0.0.1", + "build": "ng build", + "build:debug": "ng build --configuration development", + "test": "ng test", + "tsc": "rimraf build && tsc -p tsconfig.json" + }, + "private": true, + "dependencies": { + "@angular/animations": "^16.1.8", + "@angular/common": "^16.1.8", + "@angular/compiler": "^16.1.8", + "@angular/core": "^16.1.8", + "@angular/forms": "^16.1.8", + "@angular/localize": "^16.1.8", + "@angular/platform-browser": "^16.1.8", + "@angular/platform-browser-dynamic": "^16.1.8", + "@angular/router": "^16.1.8", + "@ng-bootstrap/ng-bootstrap": "^15.1.0", + "@ngrx/effects": "^16.1.0", + "@ngrx/store": "^16.1.0", + "@ngx-translate/core": "^15.0.0", + "@ngx-translate/http-loader": "^8.0.0", + "@popperjs/core": "^2.11.8", + "@xmldom/xmldom": "^0.8.10", + "aas-lib": "2.0.0", + "bootstrap": "^5.3.1", + "bootstrap-icons": "^1.10.5", + "chart.js": "^4.3.3", + "common": "2.0.0", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "rxjs": "~7.8.1", + "tslib": "^2.6.1", + "uuid": "^8.3.2", + "zone.js": "~0.13.1" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^16.1.8", + "@angular-eslint/builder": "16.1.0", + "@angular-eslint/eslint-plugin": "16.1.0", + "@angular-eslint/eslint-plugin-template": "16.1.0", + "@angular-eslint/schematics": "16.1.0", + "@angular-eslint/template-parser": "16.1.0", + "@angular/cli": "^16.1.8", + "@angular/compiler-cli": "^16.1.8", + "@ngrx/eslint-plugin": "^16.1.0", + "@types/bootstrap": "^5.2.6", + "@types/jasmine": "^4.3.5", + "@types/jquery": "^3.5.16", + "@types/lodash-es": "^4.17.8", + "@types/uuid": "^8.3.4", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "eslint": "^8.46.0", + "jasmine-core": "^5.1.0", + "jest": "^29.6.2", + "karma": "^6.4.2", + "karma-chrome-launcher": "^3.2.0", + "karma-coverage": "^2.2.1", + "karma-jasmine": "^5.1.0", + "karma-jasmine-html-reporter": "^2.1.0", + "karma-junit-reporter": "^2.0.1", + "ng-packagr": "^16.1.0", + "rimraf": "^5.0.1", + "ts-node": "^10.9.1", + "typescript": "5.0.*" + } +} diff --git a/projects/aas-portal/proxy.conf.json b/projects/aas-portal/proxy.conf.json new file mode 100644 index 00000000..dcb5a6bf --- /dev/null +++ b/projects/aas-portal/proxy.conf.json @@ -0,0 +1,11 @@ +{ + "/api": { + "target": "http://localhost:1337", + "secure": false + }, + "/websocket": { + "target": "ws://localhost:1337", + "secure": false, + "ws": true + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas-api.service.ts b/projects/aas-portal/src/app/aas/aas-api.service.ts new file mode 100644 index 00000000..e2711ce2 --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas-api.service.ts @@ -0,0 +1,52 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { AASDocument, TemplateDescriptor } from 'common'; +import { Observable } from 'rxjs'; +import { encodeBase64Url } from 'aas-lib'; + +/** The client side AAS provider service. */ +@Injectable({ + providedIn: 'root' +}) +export class AASApiService { + constructor( + private readonly http: HttpClient + ) { + } + + /** + * Gets the templates. + * @returns An array of `TemplateDescriptor` items. + */ + public getTemplates(): Observable { + return this.http.get('/api/v1/templates'); + } + + /** + * Applies a changed AAS document. + * @param document The document to apply. + */ + public async putDocumentAsync(document: AASDocument): Promise { + const formData = new FormData(); + formData.append('content', JSON.stringify(document.content)) + return new Promise((resolve, reject) => { + let messages: string[]; + this.http.put( + `/api/v1/containers/${encodeBase64Url(document.container)}/documents/${encodeBase64Url(document.id)}`, + formData) + .subscribe({ + next: (value) => messages = value, + error: (error) => reject(error), + complete: () => resolve(messages) + }); + }); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.actions.ts b/projects/aas-portal/src/app/aas/aas.actions.ts new file mode 100644 index 00000000..7b34249e --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.actions.ts @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from '@ngrx/store'; +import { AASDocument, TemplateDescriptor } from 'common'; + +export enum AASActionType { + SET_TEMPLATE_STORAGE = '[AAS] Set template storage', + SET_DOCUMENT = '[AAS] Set document', + APPLY_DOCUMENT = '[AAS] Apply document', + RESET_MODIFIED = '[AAS] Reset modified', + SET_DASHBOARD = '[AAS] Set dashboard', + SET_SEARCH = '[AAS] Set search' +} + +export const setDocument = createAction( + AASActionType.SET_DOCUMENT, + props<{ document: AASDocument | null }>()); + +export const applyDocument = createAction( + AASActionType.APPLY_DOCUMENT, + props<{ document: AASDocument }>()); + +export const setTemplateStorage = createAction( + AASActionType.SET_TEMPLATE_STORAGE, + props<{ templates: TemplateDescriptor[] }>()); + +export const resetModified = createAction( + AASActionType.RESET_MODIFIED, + props<{ document: AASDocument }>()); + +export const setSearch = createAction( + AASActionType.SET_SEARCH, + props<{ search: string }>()); \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.component.html b/projects/aas-portal/src/app/aas/aas.component.html new file mode 100644 index 00000000..1078a109 --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.component.html @@ -0,0 +1,37 @@ + + +
+
+
+
+ +
+
+
+
LABEL_ENDPOINT
+
LABEL_AAS_ID_SHORT
+
LABEL_AAS_ID
+
LABEL_VERSION
+
LABEL_ASSET_ID
+
+
+
{{endpoint}}
+
{{idShort}}
+
{{id}}
+
{{version}}
+
{{assetId}}
+
+
+
+
+
+ + +
+
\ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.component.scss b/projects/aas-portal/src/app/aas/aas.component.scss new file mode 100644 index 00000000..53a42160 --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.component.scss @@ -0,0 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +.hyperlink{ + color: blue; + text-decoration: underline; + cursor: pointer; +} + +.aasComponentClickButtons:focus, .aasComponentClickButtons:active{ + box-shadow: none; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.component.ts b/projects/aas-portal/src/app/aas/aas.component.ts new file mode 100644 index 00000000..b857eecd --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.component.ts @@ -0,0 +1,451 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { head } from 'lodash-es'; +import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { BehaviorSubject, EMPTY, map, mergeMap, Observable, Subscription, first } from 'rxjs'; +import * as lib from 'aas-lib'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { Store } from '@ngrx/store'; +import { ProjectService } from '../project/project.service'; + +import { CommandHandlerService } from 'src/app/aas/command-handler.service'; +import { EditElementFormComponent } from './edit-element-form/edit-element-form.component'; +import { UpdateElementCommand } from './commands/update-element-command'; +import { DeleteCommand } from './commands/delete-command'; +import { NewElementCommand } from './commands/new-element-command'; +import { AASApiService } from './aas-api.service'; +import { NewElementFormComponent, NewElementResult } from './new-element-form/new-element-form.component'; +import { DashboardService } from '../dashboard/dashboard.service'; +import * as AASActions from './aas.actions'; +import * as AASSelectors from './aas.selectors'; +import { State } from './aas.state'; +import { DashboardChartType } from '../dashboard/dashboard.state'; +import { DashboardQuery } from 'src/app/types/dashboard-query-params'; +import { getEndpointType } from 'src/app/configuration'; +import { + AASDocument, + equalDocument, + TemplateDescriptor, + aas, isProperty, + isNumberType, + isBlob, + AASEndpointType +} from 'common'; + +@Component({ + selector: 'fhg-aas', + templateUrl: './aas.component.html', + styleUrls: ['./aas.component.scss'] +}) +export class AASComponent implements OnInit, OnDestroy, AfterViewInit { + private readonly store: Store; + private readonly $state = new BehaviorSubject('offline'); + private readonly subscription = new Subscription(); + private templates: TemplateDescriptor[] = []; + private dashboardName = ''; + private selectedElements: aas.Referable[] = []; + + constructor( + store: Store, + private readonly router: Router, + private readonly route: ActivatedRoute, + private readonly modal: NgbModal, + private readonly project: ProjectService, + private readonly notify: lib.NotifyService, + private readonly dashboard: DashboardService, + private readonly api: AASApiService, + private readonly download: lib.DownloadService, + private readonly commandHandler: CommandHandlerService, + private readonly toolbar: lib.ToolbarService, + private readonly auth: lib.AuthService, + private readonly clipboard: lib.ClipboardService + ) { + this.store = store as Store; + this.state = this.$state.asObservable(); + this.search = this.store.select(AASSelectors.selectSearch); + } + + @ViewChild('aasTree') + public aasTree: lib.AASTree | null = null; + + public document: AASDocument | null = null; + + public readonly state: Observable; + + public readonly search: Observable; + + public get endpoint(): string { + return this.document?.endpoint.address ?? ''; + } + + public get idShort(): string { + return this.document?.idShort ?? ''; + } + + public get id(): string { + return this.document?.id ?? '-' + } + + public get assetId(): string { + return head(this.document?.content?.assetAdministrationShells)?.assetInformation.globalAssetId ?? '-'; + } + + public get thumbnail(): string { + if (this.document) { + const url = lib.encodeBase64Url(this.document?.container); + const id = lib.encodeBase64Url(this.document?.id); + return `/api/v1/containers/${url}/documents/${id}/thumbnail`; + } + + return 'assets/resources/aas.svg' + } + + public get version(): string { + return this.versionToString(head(this.document?.content?.assetAdministrationShells)?.administration); + } + + public get onlineReady(): boolean { + return this.document?.onlineReady ?? false; + } + + public get readonly(): boolean { + return this.document?.readonly ?? true; + } + + public ngOnInit(): void { + const params = this.route.snapshot.queryParams as lib.AASQueryParams; + let query: lib.AASQuery | undefined; + if (params.format) { + query = this.clipboard.get(params.format); + } else if (params.id) { + query = { + id: params.id + }; + } + + if (query?.search) { + this.store.dispatch(AASActions.setSearch({ search: query.search })); + } + + this.toolbar.setToolbar(this.createToolbar()); + + if (query) { + let document: Observable | undefined; + if (query.url) { + document = this.project.getDocument(query.id, query.url); + } else { + document = this.project.getDocument(query.id); + } + + document?.pipe(first()).subscribe(value => this.store.dispatch(AASActions.setDocument({ document: value }))); + } + + this.subscription.add(this.store.select(AASSelectors.selectDocument).pipe() + .subscribe((value) => { + if (!equalDocument(this.document, value)) { + this.commandHandler.clear(); + } + + this.document = value; + })); + + this.subscription.add(this.store.select(AASSelectors.selectTemplateStorage).pipe( + mergeMap(templateStorage => { + if (templateStorage.timestamp === 0) { + return this.api.getTemplates().pipe( + map(templates => this.store.dispatch(AASActions.setTemplateStorage({ templates }))) + ); + } else { + return EMPTY; + } + }) + ).subscribe({ + error: error => this.notify.error(error) + })); + + this.subscription.add(this.store.select(AASSelectors.selectTemplates).pipe() + .subscribe(templates => { + this.templates = templates; + })); + + this.subscription.add(this.dashboard.name.subscribe(name => { + this.dashboardName = name; + })); + } + + public ngAfterViewInit(): void { + if (this.aasTree) { + this.subscription.add(this.aasTree.selectedElements.subscribe(values => this.selectedElements = values)); + } + } + + public ngOnDestroy(): void { + this.toolbar.setToolbar(); + this.subscription.unsubscribe(); + } + + public play(): void { + if (this.onlineReady && this.$state.value === 'offline') { + this.$state.next('online'); + } + } + + public stop(): void { + this.$state.next('offline'); + } + + public canAddToDashboard(): boolean { + const selectedElements = this.selectedElements; + return this.dashboardName != null && this.document != null && + selectedElements.length > 0 && + selectedElements.every(element => this.isNumberProperty(element) || this.isTimeSeries(element)); + } + + public async addToDashboard(chartType: DashboardChartType): Promise { + if (this.document) { + try { + this.dashboard.add(this.dashboardName, this.document, this.selectedElements, chartType); + this.clipboard.set('DashboardQuery', { page: this.dashboardName } as DashboardQuery); + return await this.router.navigateByUrl('/dashboard?format=DashboardQuery'); + } catch (error) { + this.notify.error(error); + } + } + + return false; + } + + public canSynchronize(): boolean { + return this.document != null && !this.document.readonly && this.document.modified ? this.document.modified : false; + } + + public async synchronize(): Promise { + try { + await this.auth.ensureAuthorizedAsync('editor'); + if (this.canSynchronize() && this.document) { + const messages = await this.api.putDocumentAsync(this.document); + if (messages && messages.length > 0) { + this.notify.info(messages.join('\r\n')); + } + + this.store.dispatch(AASActions.resetModified({ document: this.document })); + } + } catch (error) { + this.notify.error(error); + } + } + + public canUndo(): boolean { + return !this.readonly && this.commandHandler.canUndo; + } + + public undo(): void { + if (this.canUndo()) { + this.commandHandler.undo(); + } + } + + public canRedo(): boolean { + return !this.readonly && this.commandHandler.canRedo; + } + + public redo(): void { + if (this.canRedo()) { + this.commandHandler.redo(); + } + } + + public canNewElement(): boolean { + return this.selectedElements.length === 1; + } + + public async newElement(): Promise { + await this.auth.ensureAuthorizedAsync('editor'); + if (this.document?.content && this.selectedElements.length === 1) { + const modalRef = this.modal.open(NewElementFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.initialize(this.document.content, this.selectedElements[0], this.templates); + const result: NewElementResult = await modalRef.result; + if (result.element) { + try { + this.commandHandler.execute(new NewElementCommand( + this.store, + this.document, + this.selectedElements[0], + result.element)); + } catch (error) { + this.notify.error(error); + } + } + } + } + + public canEditElement(): boolean { + return this.selectedElements.length === 1; + } + + public async editElement(): Promise { + await this.auth.ensureAuthorizedAsync('editor'); + if (this.document && this.selectedElements.length === 1) { + const modalRef = this.modal.open(EditElementFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.initialize(this.selectedElements[0]); + const result: aas.SubmodelElement = await modalRef.result; + if (result) { + try { + this.commandHandler.execute(new UpdateElementCommand( + this.store, + this.document, + this.selectedElements[0], + result)); + } catch (error) { + this.notify.error(error); + } + } + } + } + + public canDeleteElement(): boolean { + return this.selectedElements.length > 0 && + this.selectedElements.every(item => item.modelType !== 'AssetAdministrationShell'); + } + + public async deleteElement(): Promise { + await this.auth.ensureAuthorizedAsync('editor'); + if (this.document && this.selectedElements.length > 0) { + try { + this.commandHandler.execute(new DeleteCommand(this.store, this.document, this.selectedElements)); + } catch (error) { + this.notify.error(error); + } + } + } + + public canDownloadDocument(): boolean { + let type: AASEndpointType | undefined; + if (this.document) { + type = getEndpointType(this.document.container); + } + + return type === 'AasxDirectory' || type === 'AasxServer'; + } + + public async downloadDocument(): Promise { + try { + await this.download.downloadDocumentAsync( + this.document!.idShort + '.aasx', + this.document!.id, + this.document!.container); + } catch (error) { + this.notify.error(error); + } + } + + private versionToString(administration?: aas.AdministrativeInformation): string { + let version: string = administration?.version ?? ''; + const revision: string = administration?.revision ?? ''; + if (revision.length > 0) { + if (version.length > 0) { + version += ' (' + revision + ')'; + } else { + version = revision; + } + } + + if (version.length === 0) { + version = '-'; + } + + return version; + } + + private isNumberProperty(element: aas.Referable): boolean { + if (isProperty(element)) { + return isNumberType(element.valueType); + } + + return false; + } + + // Hack, Hack + private isTimeSeries(element: aas.Referable): boolean { + return isBlob(element) && + element.value != null && + element.idShort === 'TimeSeriesHistory' && + element.contentType === 'application/json'; + } + + private createToolbar(): lib.Toolbar { + return { + groups: [ + this.toolbar.createGroup( + [ + this.toolbar.createButton( + 'bi bi-play-fill', + () => this.play(), + () => this.$state.getValue() === 'offline'), + this.toolbar.createButton( + 'bi bi-stop-fill', + () => this.stop(), + () => this.$state.getValue() === 'online') + ], + this.store.select(AASSelectors.selectOnlineReady)), + this.toolbar.createGroup( + [ + this.toolbar.createSelect( + this.dashboard.pages.pipe(map(pages => pages.map(page => this.toolbar.createOption( + page.name, + page.name)))), + this.dashboard.name, + (page) => this.dashboard.setPageName(page)), + this.toolbar.createButton( + 'bi bi-graph-up', + () => this.addToDashboard(DashboardChartType.Line), + () => this.canAddToDashboard()), + this.toolbar.createButton( + 'bi bi-bar-chart-line-fill', + () => this.addToDashboard(DashboardChartType.BarVertical), + () => this.canAddToDashboard()) + + ]), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-arrow-repeat', () => this.synchronize(), () => this.canSynchronize()), + ], + this.store.select(AASSelectors.selectEditable)), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-download', () => this.downloadDocument(), () => this.canDownloadDocument()) + ]), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-arrow-90deg-left', () => this.undo(), () => this.canUndo()), + this.toolbar.createButton('bi bi-arrow-90deg-right', () => this.redo(), () => this.canRedo()), + ], + this.store.select(AASSelectors.selectEditable)), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-plus-lg', () => this.newElement(), () => this.canNewElement()), + this.toolbar.createButton('bi bi-pencil', () => this.editElement(), () => this.canEditElement()), + this.toolbar.createButton('bi bi-trash', () => this.deleteElement(), () => this.canDeleteElement()), + ], + this.store.select(AASSelectors.selectEditable)), + this.toolbar.createGroup( + [ + this.toolbar.createTextInput( + 'bi bi-search', + this.search.pipe(first()), + 'PLACEHOLDER_SEARCH', + (text: string) => this.store.dispatch(AASActions.setSearch({ search: text }))), + this.toolbar.createButton('bi bi-chevron-down', () => this.aasTree?.findNext()), + this.toolbar.createButton('bi bi-chevron-up', () => this.aasTree?.findPrevious()), + ]) + ] + } + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.reducer.ts b/projects/aas-portal/src/app/aas/aas.reducer.ts new file mode 100644 index 00000000..482a6ece --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.reducer.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from "@ngrx/store"; +import { AASDocument, TemplateDescriptor } from "common"; +import * as AASActions from "./aas.actions"; +import { AASState, initialState } from "./aas.state"; + +export const aasReducer = createReducer(initialState, + on( + AASActions.applyDocument, + (state, { document }) => applyDocument(state, document) + ), + on( + AASActions.resetModified, + (state, { document }) => resetModified(state, document) + ), + on( + AASActions.setDocument, + (state, { document }) => setDocument(state, document) + ), + on( + AASActions.setSearch, + (state, { search }) => setSearch(state, search) + ), + on( + AASActions.setTemplateStorage, + (state, { templates }) => setTemplateStorage(state, templates) + ) +); + +function setTemplateStorage(state: AASState, templates: TemplateDescriptor[]): AASState { + return { ...state, templateStorage: { templates, timestamp: Date.now() }, error: null }; +} + +function setDocument(state: AASState, document: AASDocument | null): AASState { + return { ...state, document, error: null }; +} + +function applyDocument(state: AASState, document: AASDocument): AASState { + return { ...state, document: { ...document, modified: true }, error: null }; +} + +function resetModified(state: AASState, document: AASDocument): AASState { + return { ...state, document: { ...document, modified: false }, error: null }; +} + +function setSearch(state: AASState, search: string): AASState { + return { ...state, search }; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.selectors.ts b/projects/aas-portal/src/app/aas/aas.selectors.ts new file mode 100644 index 00000000..a027d918 --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.selectors.ts @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from "@ngrx/store"; +import { State } from "./aas.state"; + +const getReadOnly = (state: State) => state.aas.document?.readonly ?? true; +const getOnlineReady = (state: State) => state.aas.document?.onlineReady ?? false; +const getSearch = (state: State) => state.aas.search; +const getDocument = (state: State) => state.aas.document; +const getTemplateStorage = (state: State) => state.aas.templateStorage; +const getTemplates = (state: State) => state.aas.templateStorage.templates; + +export const selectOnlineReady = createSelector(getOnlineReady, onlineReady => onlineReady); + +export const selectReadOnly = createSelector(getReadOnly, readOnly => readOnly); + +export const selectEditable = createSelector(getReadOnly, readonly => !readonly); + +export const selectSearch = createSelector(getSearch, search => search); + +export const selectDocument = createSelector(getDocument, document => document); + +export const selectHasDocument = createSelector(getDocument, document => document != null); + +export const selectTemplateStorage = createSelector(getTemplateStorage, templateStorage => templateStorage); + +export const selectTemplates = createSelector(getTemplates, templates => templates); \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/aas.state.ts b/projects/aas-portal/src/app/aas/aas.state.ts new file mode 100644 index 00000000..550f5e0f --- /dev/null +++ b/projects/aas-portal/src/app/aas/aas.state.ts @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, TemplateDescriptor } from "common"; + +export interface TemplateStorage { + timestamp: number; + templates: TemplateDescriptor[]; +} + +export interface AASState { + document: AASDocument | null; + search: string; + templateStorage: TemplateStorage; + error: Error | null; +} + +export const initialState: AASState = { + document: null, + search: '', + templateStorage: { + timestamp: 0, + templates: [] + }, + error: null +}; + +export interface State { + aas: AASState; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/can-activate-aas.guard.ts b/projects/aas-portal/src/app/aas/can-activate-aas.guard.ts new file mode 100644 index 00000000..605c0434 --- /dev/null +++ b/projects/aas-portal/src/app/aas/can-activate-aas.guard.ts @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from "@angular/core"; +import { ActivatedRouteSnapshot, UrlTree } from "@angular/router"; +import { Store } from "@ngrx/store"; +import { Observable } from "rxjs"; +import { AASQueryParams } from "aas-lib"; +import * as AASSelectors from './aas.selectors'; +import { State } from './aas.state'; + +@Injectable() +export class CanActivateAAS { + private readonly store: Store; + constructor(store: Store) { + this.store = store as Store; + } + + public canActivate(route: ActivatedRouteSnapshot): boolean | UrlTree | Observable | Promise { + const params: AASQueryParams = route.queryParams; + if (params.id || params.format) { + return true; + } + + return this.store.select(AASSelectors.selectHasDocument); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/command-handler.service.ts b/projects/aas-portal/src/app/aas/command-handler.service.ts new file mode 100644 index 00000000..02695e1d --- /dev/null +++ b/projects/aas-portal/src/app/aas/command-handler.service.ts @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from "@angular/core"; +import { NotifyService } from "aas-lib"; +import { Command } from "../types/command"; + +@Injectable({ + providedIn: 'root' +}) +export class CommandHandlerService { + private commands: Array = []; + private position = -1; + + constructor(private notify: NotifyService) { + } + + public execute(command: Command): void { + if (!command) { + throw new Error("Argument command is undefined."); + } + + try { + command.execute(); + + if (this.commands.length > 0 && this.position < this.commands.length - 1) { + this.commands.splice(this.position + 1); + } + + this.commands.push(command); + ++this.position; + } catch (error) { + command.abort(); + throw error; + } + } + + public get canUndo(): boolean { + return this.position >= 0; + } + + public get canRedo(): boolean { + return this.position + 1 < this.commands.length + } + + public undo(): void { + try { + this.commands[this.position].undo(); + --this.position; + } + catch (error) { + this.notify.error(error); + } + } + + public redo(): void { + try { + ++this.position; + this.commands[this.position].redo(); + } + catch (error) { + this.notify.error(error); + } + } + + public clear(): void { + this.commands = []; + this.position = -1; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/commands/delete-command.ts b/projects/aas-portal/src/app/aas/commands/delete-command.ts new file mode 100644 index 00000000..093ed145 --- /dev/null +++ b/projects/aas-portal/src/app/aas/commands/delete-command.ts @@ -0,0 +1,107 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, AASDocument, getChildren, getParent, isAssetAdministrationShell, isSubmodel, normalize, selectSubmodel } from "common"; +import { cloneDeep, noop } from "lodash-es"; +import { Command } from "src/app/types/command"; +import { Store } from "@ngrx/store"; +import { State } from '../aas.state'; +import * as AASActions from '../aas.actions'; + +export class DeleteCommand extends Command { + private readonly store: Store; + private readonly elements: aas.Referable[]; + private readonly memento: AASDocument; + private document: AASDocument; + + constructor(store: Store, document: AASDocument, elements: aas.Referable | aas.Referable[]) { + super("Delete"); + + if (!document.content) { + throw new Error("Document content is undefined.") + } + + this.store = store; + this.memento = document; + this.document = { + ...document, + content: { + ...document.content!, + assetAdministrationShells: [...document.content!.assetAdministrationShells], + submodels: [...document.content!.submodels] + } + }; + + this.elements = Array.isArray(elements) + ? normalize(document.content, elements, item => item) + : [elements]; + } + + protected onExecute(): void { + const env = this.document.content!; + const map = new Map(); + for (const element of this.elements) { + if (isAssetAdministrationShell(element)) { + throw new Error('Invalid operation.'); + } else if (isSubmodel(element)) { + const index = env.submodels.indexOf(element); + env.submodels.splice(index, 1); + this.deleteFromShells(element); + } else { + const submodel = selectSubmodel(env, element)!; + let list = map.get(submodel); + if (!list) { + list = []; + map.set(submodel, list); + } + + list.push(element); + } + } + + for (const item of map) { + const submodel = item[0]; + const index = env.submodels.indexOf(submodel); + env.submodels[index] = cloneDeep(submodel); + for (const element of item[1]) { + const parent = getParent(env, element)!; + const children = getChildren(parent); + const index = children.findIndex(child => child.idShort === element.idShort); + children.splice(index, 1); + } + } + + this.store.dispatch(AASActions.applyDocument({ document: this.document })); + } + + private deleteFromShells(element: aas.Submodel) { + const env = this.document.content!; + env.assetAdministrationShells.forEach((shell, i) => { + if (shell.submodels) { + const j = shell.submodels.findIndex(r => r.keys[0].value === element.id); + if (j >= 0) { + shell = { ...env.assetAdministrationShells[i] }; + env.assetAdministrationShells[i] = shell; + shell.submodels = shell.submodels?.filter((_, k) => k !== j); + } + } + }); + } + + protected onUndo(): void { + this.store.dispatch(AASActions.applyDocument({ document: this.memento })); + } + + protected onRedo(): void { + this.store.dispatch(AASActions.applyDocument({ document: this.document })); + } + + protected onAbort(): void { + noop(); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/commands/new-element-command.ts b/projects/aas-portal/src/app/aas/commands/new-element-command.ts new file mode 100644 index 00000000..7c25673e --- /dev/null +++ b/projects/aas-portal/src/app/aas/commands/new-element-command.ts @@ -0,0 +1,159 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { cloneDeep, noop } from 'lodash-es'; +import { Command } from 'src/app/types/command'; +import { Store } from '@ngrx/store'; +import { + aas, + AASDocument, + getChildren, + isAssetAdministrationShell, + isSubmodel, + isSubmodelElement, + isSubmodelElementCollection +} from 'common'; + +import { AASState } from '../aas.state'; +import * as AASActions from '../aas.actions'; + +export class NewElementCommand extends Command { + private readonly store: Store<{ aas: AASState }>; + private readonly parent: aas.Referable; + private readonly element: aas.Referable; + private readonly memento: AASDocument; + private document: AASDocument; + + constructor( + store: Store<{ aas: AASState }>, + document: AASDocument, + parent: aas.Referable, + element: aas.Referable) { + super('New Element'); + + if (!document || !document.content) { + throw new Error('Invalid document.'); + } + + const children = getChildren(parent, document.content); + if (!children) { + throw new Error('Argument parent is invalid.') + } + + this.store = store; + this.memento = document; + this.document = { + ...document, + content: { + ...document.content!, + assetAdministrationShells: [...document.content!.assetAdministrationShells], + submodels: [...document.content!.submodels] + } + }; + + this.parent = parent; + this.element = element; + } + + protected onExecute(): void { + if (isSubmodel(this.element) && isAssetAdministrationShell(this.parent)) { + this.insertSubmodel(this.element); + } else if (isSubmodelElement(this.element)) { + this.insertSubmodelElement(this.element); + } else { + throw new Error('Invalid operation.'); + } + + this.store.dispatch(AASActions.applyDocument({ document: this.document })); + } + + protected onUndo(): void { + this.store.dispatch(AASActions.applyDocument({ document: this.memento })); + } + + protected onRedo(): void { + this.store.dispatch(AASActions.applyDocument({ document: this.document })); + } + + protected onAbort(): void { + noop(); + } + + private insertSubmodel(submodel: aas.Submodel): void { + const children = this.document.content!.submodels; + children.push(submodel); + + let shell = this.document.content!.assetAdministrationShells[0]; + const submodels = shell.submodels ? [...shell.submodels] : []; + submodels.push({ + type: 'ModelReference', + keys: [{ + type: 'Submodel', + value: submodel.id, + }] + }); + + shell = { ...shell, submodels }; + this.document.content!.assetAdministrationShells[0] = shell; + } + + private insertSubmodelElement(element: aas.SubmodelElement) { + const sourceSubmodel = this.getSubmodel(this.parent); + const parentReference = this.createReference(this.parent); + const index = this.document.content!.submodels.indexOf(sourceSubmodel); + const targetSubmodel = cloneDeep(sourceSubmodel); + this.document.content!.submodels[index] = targetSubmodel; + const children = this.getTargetChildren(targetSubmodel, parentReference); + element.parent = parentReference; + children.push(element); + } + + private getSubmodel(referable: aas.Referable): aas.Submodel { + let submodel: aas.Submodel | undefined; + if (isSubmodel(referable)) { + submodel = referable; + } else { + if (!referable.parent || referable.parent.keys[0].type !== 'Submodel') { + throw new Error('Invalid argument referable.'); + } + + const id = referable.parent.keys[0].value; + submodel = this.document.content?.submodels.find(item => item.id === id); + } + + if (!submodel) { + throw new Error('Invalid argument referable.'); + } + + return submodel; + } + + private getTargetChildren(submodel: aas.Submodel, target: aas.Reference): aas.SubmodelElementCollection[] { + let referable: aas.Referable | undefined = submodel; + if (!submodel.submodelElements) { + submodel.submodelElements = []; + } + + let children: aas.SubmodelElement[] | undefined = submodel.submodelElements; + for (let i = 1, n = target.keys.length; i < n; i++) { + const key = target.keys[i]; + referable = children?.find(item => item.idShort === key.value); + if (isSubmodelElementCollection(referable)) { + if (!referable.value) { + referable.value = []; + } + + children = referable.value; + } else { + throw new Error('Invalid operation.'); + } + } + + return children; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/commands/update-element-command.ts b/projects/aas-portal/src/app/aas/commands/update-element-command.ts new file mode 100644 index 00000000..428db25c --- /dev/null +++ b/projects/aas-portal/src/app/aas/commands/update-element-command.ts @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, AASDocument, selectReferable } from 'common'; +import { cloneDeep, noop } from 'lodash-es'; +import { Command } from 'src/app/types/command'; +import { Store } from '@ngrx/store'; +import { State } from '../aas.state'; +import * as AASActions from '../aas.actions'; + +export class UpdateElementCommand extends Command { + private readonly store: Store; + private readonly origin: aas.SubmodelElement; + private readonly element: aas.SubmodelElement; + private readonly memento: AASDocument; + private document: AASDocument; + + constructor( + store: Store, + document: AASDocument, + origin: aas.SubmodelElement, + element: aas.SubmodelElement) { + super('SetValue'); + + this.store = store; + this.document = this.memento = document; + this.origin = origin; + this.element = element; + } + + protected onExecute(): void { + this.document = cloneDeep(this.memento); + const sourceCollection = this.getChildren(this.memento, this.origin); + const targetCollection = this.getChildren(this.document, this.origin); + const index = sourceCollection.indexOf(this.origin); + targetCollection[index] = this.element; + this.store.dispatch(AASActions.applyDocument({ document: this.document })); + } + + protected onUndo(): void { + this.store.dispatch(AASActions.applyDocument({ document: this.memento })); + } + + protected onRedo(): void { + this.store.dispatch(AASActions.applyDocument({ document: this.document })); + } + + protected onAbort(): void { + noop(); + } + + private getChildren(document: AASDocument, element: aas.SubmodelElement): aas.SubmodelElementCollection[] { + if (!element.parent) { + throw new Error(`${element.idShort} is not referable.`); + } + + const parent = selectReferable(document.content!, element.parent); + if (!parent) { + throw new Error(`Invalid parent reference.`); + } + + let children: aas.SubmodelElement[] | undefined; + if (parent.modelType === 'Submodel') { + children = (parent as aas.Submodel).submodelElements; + } else if (parent.modelType === 'SubmodelElementCollection') { + children = (parent as aas.SubmodelElementCollection).value; + } + + if (!children) { + throw new Error(`Invalid operation.`); + } + + return children; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.html b/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.html new file mode 100644 index 00000000..f4505893 --- /dev/null +++ b/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.html @@ -0,0 +1,134 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.scss b/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.ts b/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.ts new file mode 100644 index 00000000..ee8b4c4b --- /dev/null +++ b/projects/aas-portal/src/app/aas/edit-element-form/edit-element-form.component.ts @@ -0,0 +1,306 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { convertBlobToBase64Async, extension, extensionToMimeType } from 'aas-lib'; +import { aas, toInvariant, toLocale } from 'common'; +import { noop } from 'lodash-es'; + +export interface LangStringRow extends aas.LangString { + index: number; + selected: boolean; +} + +@Component({ + selector: 'fhg-edit-element', + templateUrl: './edit-element-form.component.html', + styleUrls: ['./edit-element-form.component.scss'] +}) +export class EditElementFormComponent { + private element?: aas.Referable; + + constructor(private modal: NgbActiveModal, private translate: TranslateService) { } + + public modelType!: aas.ModelType; + + public idShort = ''; + + public semanticId = ''; + + public categories: string[] = ['-', 'CONSTANT', 'PARAMETER', 'VARIABLE']; + + public category = '-'; + + public valueType: aas.DataTypeDefXsd | null = null; + + public valueTypes: aas.DataTypeDefXsd[] = [ + 'xs:anyURI', + 'xs:base64Binary', + 'xs:boolean', + 'xs:byte', + 'xs:date', + 'xs:dateTime', + 'xs:decimal', + 'xs:double', + 'xs:duration', + 'xs:float', + 'xs:gDay', + 'xs:gMonth', + 'xs:gMonthDay', + 'xs:gYear', + 'xs:gYearMonth', + 'xs:hexBinary', + 'xs:int', + 'xs:integer', + 'xs:long', + 'xs:negativeInteger', + 'xs:nonNegativeInteger', + 'xs:nonPositiveInteger', + 'xs:positiveInteger', + 'xs:short', + 'xs:string', + 'xs:time', + 'xs:unsignedByte', + 'xs:unsignedInt', + 'xs:unsignedLong', + 'xs:unsignedShort' + ]; + + public value?: string; + + public min?: string; + + public max?: string; + + public langStrings: LangStringRow[] = []; + + public contentType?: string; + + public files?: string[]; + + public messages: string[] = []; + + public initialize(element: aas.SubmodelElement) { + this.element = { ...element }; + this.modelType = element.modelType; + this.semanticId = this.referenceToString(element.semanticId); + this.category = element.category ?? '-'; + this.idShort = element.idShort; + + switch (this.modelType) { + case 'Property': + this.initProperty(); + break; + case 'MultiLanguageProperty': + this.initMultiLanguageProperty(); + break; + case 'Range': + this.initRange(); + break; + case 'Blob': + this.initBlob(); + break; + } + } + + public submit() { + if (this.element && this.submitElement()) { + this.modal.close(this.element); + } + } + + public cancel() { + this.modal.close(); + } + + public select(item: LangStringRow): void { + this.langStrings.forEach((langString) => { + if (item === langString && langString.index >= 0) { + langString.selected = !langString.selected; + } else { + langString.selected = false; + } + }); + } + + public addLangString(): void { + this.clearMessages(); + const last = this.langStrings[this.langStrings.length - 1]; + last.index = this.langStrings.length - 1; + this.langStrings.forEach(item => item.selected = false); + last.selected = true; + this.langStrings.push({ language: '', text: '', selected: false, index: -1 }); + } + + public removeLangString(item: LangStringRow) { + this.clearMessages(); + if (item.index >= 0) { + this.langStrings = this.langStrings.filter(langString => langString !== item); + this.langStrings.forEach((langString, index) => langString.index = index); + this.langStrings[this.langStrings.length - 1].index = -1; + } + } + + public setLanguage(langString: LangStringRow, value: string): void { + try { + langString.language = Intl.getCanonicalLocales(value)[0]; + } catch (err) { + this.pushMessage(`${value} is an invalid locale ID.`); + } + } + + public setText(langString: LangStringRow, value: string): void { + langString.text = value; + } + + public readFile(files: FileList | null): void { + if (files && files.length === 1) { + const ext = extension(files[0].name); + if (ext) { + const temp = this.value; + this.value = undefined; + this.contentType = extensionToMimeType(ext); + convertBlobToBase64Async(files[0]).then( + value => this.value = value + ).catch(error => { + this.value = temp; + this.pushMessage('Unable to read file.'); + }) + } + } + } + + private initProperty(): void { + const property = this.element as aas.Property; + this.value = toLocale(property.value, property.valueType, this.translate.currentLang); + this.valueType = property.valueType ?? null; + } + + private initMultiLanguageProperty(): void { + const multiLangProperty = this.element as aas.MultiLanguageProperty; + this.langStrings = multiLangProperty.value.map( + (item, index) => ({ ...item, selected: false, index } as LangStringRow)); + + this.langStrings.push({ language: '', text: '', selected: false, index: -1 }); + } + + private initRange(): void { + const range = this.element as aas.Range; + this.min = toLocale(range.min, range.valueType, this.translate.currentLang); + this.max = toLocale(range.max, range.valueType, this.translate.currentLang); + this.valueType = range.valueType ?? null; + } + + private initBlob(): void { + const blob = this.element as aas.Blob; + this.contentType = blob.contentType; + this.value = blob.value; + } + + private submitElement(): boolean { + if (this.category !== '-') { + this.element!.category = this.category; + } else { + delete this.element!.category; + } + + switch (this.modelType) { + case 'Property': + return this.submitProperty(); + case 'MultiLanguageProperty': + return this.submitMultiLanguageProperty(); + case 'Range': + return this.submitRange(); + case 'Blob': + return this.submitBlob(); + default: + return false; + } + } + + private submitProperty(): boolean { + if (this.valueType && this.element) { + const property = this.element as aas.Property; + property.valueType = this.valueType; + + if (this.value) { + const value = toInvariant(this.value, this.valueType, this.translate.currentLang); + if (value) { + property.value = value; + return true; + } else { + this.pushMessage(`"${this.value}"cannot be converted to type "${this.valueType}".`); + } + } else { + return true; + } + } + + return false; + } + + private submitMultiLanguageProperty(): boolean { + if (this.element) { + const multiLangProperty = this.element as aas.MultiLanguageProperty; + multiLangProperty.value = this.langStrings.filter(item => item.language && item.text && item.index >= 0) + .map(item => ({ language: item.language, text: item.text })); + + return true; + } + + return false; + } + + private submitRange(): boolean { + if (this.valueType && this.element) { + const range = this.element as aas.Range; + range.valueType = this.valueType; + + if (this.min && this.max) { + const min = toInvariant(this.min, this.valueType, this.translate.currentLang); + const max = toInvariant(this.max, this.valueType, this.translate.currentLang); + if (min && max) { + range.min = min; + range.max = max; + return true; + } else { + this.pushMessage(`"${this.min}...${this.max}"cannot be converted to type "${this.valueType}".`); + } + } else { + return true; + } + } + + return false; + } + + private submitBlob(): boolean { + if (this.value && this.element && this.contentType) { + const blob = this.element as aas.Blob; + blob.contentType = this.contentType; + blob.value = this.value; + return true; + } + + return false; + } + + private referenceToString(reference?: aas.Reference): string { + return reference ? reference.keys.map(key => key.value).join('/') : '-'; + } + + private pushMessage(message: string): void { + this.messages = [message]; + } + + private clearMessages() { + this.messages = []; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.html b/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.html new file mode 100644 index 00000000..05fcc437 --- /dev/null +++ b/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.html @@ -0,0 +1,45 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.scss b/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.ts b/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.ts new file mode 100644 index 00000000..c27515cd --- /dev/null +++ b/projects/aas-portal/src/app/aas/new-element-form/new-element-form.component.ts @@ -0,0 +1,136 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TemplateDescriptor, aas, getChildren, isSubmodel } from 'common'; +import { cloneDeep, head } from 'lodash-es'; + +export interface NewElementResult { + index?: number; + element: aas.Referable; +} + +@Component({ + selector: 'fhg-new-element', + templateUrl: './new-element-form.component.html', + styleUrls: ['./new-element-form.component.scss'] +}) +export class NewElementFormComponent { + private env?: aas.Environment; + private parent?: aas.Referable; + private _templates: TemplateDescriptor[] = []; + private _modelType?: aas.ModelType; + private _template?: TemplateDescriptor; + + constructor(private readonly modal: NgbActiveModal) { } + + public modelTypes: aas.ModelType[] = []; + + public get modelType(): aas.ModelType | undefined { + return this._modelType; + } + + public set modelType(value: aas.ModelType | undefined) { + this._modelType = value; + this.template = head(this.templates); + } + + public get templates(): TemplateDescriptor[] { + return this.modelType + ? this._templates.filter(item => item.template?.modelType === this.modelType) + : this._templates; + } + + public get template(): TemplateDescriptor | undefined { + return this._template; + } + + public set template(value: TemplateDescriptor | undefined) { + this._template = value; + this.idShort = value?.template?.idShort ?? ''; + } + + public idShort = ''; + + public messages: string[] = []; + + public cancel() { + this.modal.close(); + } + + public initialize(env: aas.Environment, parent: aas.Referable, templates: TemplateDescriptor[]): void { + this.env = env; + this.parent = parent; + this.templates.push({ name: '-' }, ...templates); + + switch (this.parent.modelType) { + case 'AssetAdministrationShell': + this.modelTypes.push('Submodel'); + this.modelType = 'Submodel'; + break; + case 'Submodel': + this.modelTypes.push('MultiLanguageProperty', 'Property', 'SubmodelElementCollection', 'SubmodelElementList'); + this.modelType = 'Property'; + break; + case 'SubmodelElementCollection': + this.modelTypes.push('MultiLanguageProperty', 'Property', 'SubmodelElementCollection', 'SubmodelElementList'); + this.modelType = 'SubmodelElementCollection'; + break; + case 'SubmodelElementList': + this.modelTypes.push('MultiLanguageProperty', 'Property', 'SubmodelElementCollection', 'SubmodelElementList'); + this.modelType = 'SubmodelElementList'; + } + } + + public submit(): void { + this.clearMessages(); + if (this.validate()) { + this.modal.close({ + element: this.createElement() + } as NewElementResult); + } + } + + private createElement(): aas.Referable { + const element = cloneDeep(this.template!.template!); + element.idShort = this.idShort; + return element; + } + + private validate(): boolean { + if (!this.idShort || !this.parent || !this.env || !this.template?.template) { + this.pushMessage(`Invalid name.`); + return false; + } + + const children = getChildren(this.parent, this.env); + if (children.some(child => child.idShort === this.idShort)) { + this.pushMessage(`A ${this.modelType} with the name "${this.idShort}" already exists.`); + return false; + } + + if (isSubmodel(this.template.template)) { + const id = this.template.template.id; + if (this.env.submodels.some(child => child.id === id)) { + this.pushMessage(`A ${this.modelType} with the identification "${id}" already exists.`); + return false; + } + } + + return true; + } + + private pushMessage(message: string): void { + this.messages = [message]; + } + + private clearMessages(): void { + this.messages = []; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/about/about.component.html b/projects/aas-portal/src/app/about/about.component.html new file mode 100644 index 00000000..bb512379 --- /dev/null +++ b/projects/aas-portal/src/app/about/about.component.html @@ -0,0 +1,28 @@ + + +
+

AASPortal

+

The AASPortal is a web portal for the visualization and management of Asset Administration Shells (AAS) licensed under the Apache License 2.0.

+

The implementation uses the concepts of the document "Details of the Asset Administration Shell" published on www.plattform-i40.de which is licensed under Creative Commons CC BY 4.0.

+

Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft +zur Foerderung der angewandten Forschung e.V.

+

+ Internet: {{homepage}}
+

+

AASPortal

+

Version: {{version}}

+

AAS-Server

+

Version: {{serverVersion}}

+

Third-party Libraries

+

The application is based on some third-party libraries for which specific copyright statements and licenses + apply.

+ +

Server Messages

+ +
diff --git a/projects/aas-portal/src/app/about/about.component.scss b/projects/aas-portal/src/app/about/about.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/about/about.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/about/about.component.ts b/projects/aas-portal/src/app/about/about.component.ts new file mode 100644 index 00000000..b2f3dc16 --- /dev/null +++ b/projects/aas-portal/src/app/about/about.component.ts @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, OnInit } from '@angular/core'; +import { Library, Message } from 'common'; +import { ServerApiService } from './server-api.service'; +import pkg from '../../../../../package.json'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'about', + templateUrl: './about.component.html', + styleUrls: ['./about.component.scss'] +}) +export class AboutComponent implements OnInit { + constructor(private serverApi: ServerApiService, private translate: TranslateService) { + this.author = pkg.author; + this.version = pkg.version; + this.homepage = pkg.homepage; + } + + public version = ''; + + public serverVersion = '' + + public author = ''; + + public homepage = ''; + + public libraries: Library[] = []; + + public messages: Message[] = []; + + public ngOnInit(): void { + + this.serverApi.getInfo().subscribe(info => { + this.serverVersion = info.version; + this.libraries = info.libraries ?? []; + }); + + this.serverApi.getMessages().subscribe(messages => this.messages = messages); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/about/server-api.service.ts b/projects/aas-portal/src/app/about/server-api.service.ts new file mode 100644 index 00000000..c3e18d55 --- /dev/null +++ b/projects/aas-portal/src/app/about/server-api.service.ts @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClient } from "@angular/common/http"; +import { Injectable } from "@angular/core"; +import { PackageInfo, Message } from "common"; +import { Observable } from "rxjs"; + +/** Realizes the IServer service. */ +@Injectable({ + providedIn: 'root' +}) +export class ServerApiService { + constructor( + private readonly http: HttpClient, + ) { + } + + public getInfo(): Observable { + return this.http.get('/api/v1/app/info'); + } + + public getMessages(): Observable { + return this.http.get('/api/v1/app/messages'); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/app-routing.module.ts b/projects/aas-portal/src/app/app-routing.module.ts new file mode 100644 index 00000000..d8000f66 --- /dev/null +++ b/projects/aas-portal/src/app/app-routing.module.ts @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { AASComponent } from './aas/aas.component'; +import { CanActivateAAS } from './aas/can-activate-aas.guard'; +import { AboutComponent } from './about/about.component'; +import { DashboardComponent } from './dashboard/dashboard.component'; +import { StartComponent } from './start/start.component'; +import { ViewComponent } from './view/view.component'; + +const routes: Routes = [ + { path: 'start', component: StartComponent }, + { path: 'aas', component: AASComponent, canActivate: [CanActivateAAS]}, + { path: 'view', component: ViewComponent }, + { path: 'dashboard', component: DashboardComponent }, + { path: 'about', component: AboutComponent }, + { path: '', pathMatch: 'full', redirectTo: 'start' } +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule], + providers: [CanActivateAAS] +}) +export class AppRoutingModule { } \ No newline at end of file diff --git a/projects/aas-portal/src/app/app.component.html b/projects/aas-portal/src/app/app.component.html new file mode 100644 index 00000000..e01eea50 --- /dev/null +++ b/projects/aas-portal/src/app/app.component.html @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/projects/aas-portal/src/app/app.component.scss b/projects/aas-portal/src/app/app.component.scss new file mode 100644 index 00000000..d9a40aa2 --- /dev/null +++ b/projects/aas-portal/src/app/app.component.scss @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +#main{ + height: 100%; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/app.component.ts b/projects/aas-portal/src/app/app.component.ts new file mode 100644 index 00000000..490d969a --- /dev/null +++ b/projects/aas-portal/src/app/app.component.ts @@ -0,0 +1,18 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from '@angular/core'; + +@Component({ + selector: 'fhg-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + public title = 'AASPortal'; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/app.module.ts b/projects/aas-portal/src/app/app.module.ts new file mode 100644 index 00000000..6d464f52 --- /dev/null +++ b/projects/aas-portal/src/app/app.module.ts @@ -0,0 +1,87 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { StoreModule } from '@ngrx/store'; +import { NgbModule, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap' +import { HttpClientModule, HttpClient } from '@angular/common/http'; +import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; +import { AASLibModule } from 'aas-lib'; +import { EffectsModule } from '@ngrx/effects'; +import { FormsModule } from '@angular/forms'; + +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { MainComponent } from './main/main.component'; +import { AboutComponent } from './about/about.component'; +import { DashboardComponent } from './dashboard/dashboard.component'; +import { AASComponent } from './aas/aas.component'; +import { StartComponent } from './start/start.component'; +import { startReducer } from './start/start.reducer'; +import { NewElementFormComponent } from './aas/new-element-form/new-element-form.component'; +import { EditElementFormComponent } from './aas/edit-element-form/edit-element-form.component'; +import { aasReducer } from './aas/aas.reducer'; +import { RemoveEndpointFormComponent } from './start/remove-endpoint-form/remove-endpoint-form.component'; +import { dashboardReducer } from './dashboard/dashboard.reducer'; +import { UploadFormComponent } from './start/upload-form/upload-form.component'; +import { ViewComponent } from './view/view.component'; +import { viewReducer } from './view/view.reducer'; +import { AddEndpointFormComponent } from './start/add-endpoint-form/add-endpoint-form.component'; +import { projectReducer } from './project/project.reducer'; +import { ProjectEffects } from './project/project.effects'; +import { HttpLoaderFactory } from './http-loader-factory'; +import { httpInterceptorProviders } from './index'; + +@NgModule({ + declarations: [ + AppComponent, + MainComponent, + AboutComponent, + DashboardComponent, + AASComponent, + StartComponent, + AddEndpointFormComponent, + RemoveEndpointFormComponent, + NewElementFormComponent, + EditElementFormComponent, + UploadFormComponent, + ViewComponent + ], + imports: [ + BrowserModule, + AppRoutingModule, + HttpClientModule, + FormsModule, + StoreModule.forRoot( + { + start: startReducer, + aas: aasReducer, + view: viewReducer, + dashboard: dashboardReducer, + project: projectReducer + }), + EffectsModule.forRoot([ProjectEffects]), + NgbModule, + NgbTypeaheadModule, + TranslateModule.forRoot({ + defaultLanguage: 'en-us', + loader: { + provide: TranslateLoader, + useFactory: HttpLoaderFactory, + deps: [HttpClient] + } + }), + AASLibModule, + ], + providers: [ + httpInterceptorProviders + ], + bootstrap: [AppComponent] +}) +export class AppModule { } \ No newline at end of file diff --git a/projects/aas-portal/src/app/configuration.ts b/projects/aas-portal/src/app/configuration.ts new file mode 100644 index 00000000..4f081b2b --- /dev/null +++ b/projects/aas-portal/src/app/configuration.ts @@ -0,0 +1,117 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASEndpointType } from 'common'; + +/** + * Gets the endpoint name from the specified URL. + * @param url The endpoint URL. + * @returns The name. + */ +export function getEndpointName(url: string | URL): string { + if (typeof url === 'string') { + url = new URL(url); + } + + return url.searchParams.get('name') ?? url.href.split('?')[0]; +} + +/** + * Gets the endpoint type from the specified URL. + * @param url The URL. + * @returns The endpoint type. + */ +export function getEndpointType(url: string | URL): AASEndpointType { + if (typeof url === 'string') { + url = new URL(url); + } + + switch (url.protocol) { + case 'file:': + return 'AasxDirectory'; + case 'http:': + case 'https:': + return url.searchParams.get('type') as AASEndpointType ?? 'AasxServer'; + case 'opc.tcp:': + return 'OpcuaServer'; + default: + throw new Error(`Protocol "${url.protocol}" is not supported.`); + } +} + +/** + * Creates an AAS container endpoint URL with required search parameters. + * @param address The URL. + * @param options The container endpoint options or names. + * @returns The endpoint URL. + */ +export function createEndpointURL( + address: string | URL, + options?: string | { name?: string, type?: AASEndpointType, params?: [string, string][] }): URL { + const endpoint = typeof address === 'string' ? new URL(address) : address; + let name: string | undefined; + let type: AASEndpointType | undefined; + const params: [string, string][] = []; + endpoint.searchParams.forEach((value, key) => params.push([key, value])); + params.forEach(param => endpoint.searchParams.delete(param[0])); + if (typeof options === 'string') { + name = options; + } else if (options) { + name = options.name; + type = options.type; + if (options.params) { + params.push(...options.params); + } + } + + if (!name) { + const tuple = params.find(item => item[0] === 'name'); + if (tuple) { + name = tuple[1]; + } + } + + if (!type) { + const tuple = params.find(item => item[0] === 'type'); + if (tuple) { + type = tuple[1] as AASEndpointType; + } + } + + if (type !== 'AASRegistry' || (endpoint.protocol !== 'http:' && endpoint.protocol !== 'https:')) { + type = undefined; + } + + if (name) { + endpoint.searchParams.append('name', name); + } + + if (type) { + endpoint.searchParams.append('type', type); + } + + params?.forEach(item => { + if (item[0] !== 'type' && item[1] !== 'name') { + endpoint.searchParams.append(item[0], item[1]); + } + }); + + return endpoint; +} + +/** + * Creates an AAS container endpoint URL with required search parameters. + * @param address The AAS container endpoint address (URL). + * @param options The container endpoint options or name. + * @returns The endpoint URL as string. + */ +export function createEndpoint( + address: string | URL, + options?: string | { name?: string, type?: AASEndpointType, params?: [string, string][] }): string { + return createEndpointURL(address, options).href; +} diff --git a/projects/aas-portal/src/app/dashboard/commands/add-new-page-command.ts b/projects/aas-portal/src/app/dashboard/commands/add-new-page-command.ts new file mode 100644 index 00000000..ffe6b459 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/add-new-page-command.ts @@ -0,0 +1,24 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class AddNewPageCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private pageName?: string) { + super('Add new page', store); + } + + protected executing(): void { + this.dashboard.addNew(this.pageName); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/dashboard-command.ts b/projects/aas-portal/src/app/dashboard/commands/dashboard-command.ts new file mode 100644 index 00000000..aec0b60d --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/dashboard-command.ts @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from '@ngrx/store'; +import { first } from 'rxjs'; +import { Command } from 'src/app/types/command'; +import * as DashboardSelectors from '../dashboard.selectors'; +import * as DashboardActions from '../dashboard.actions'; +import { DashboardChart, DashboardItem, DashboardItemType, DashboardRow, DashboardState, State } from '../dashboard.state'; + +export abstract class DashboardCommand extends Command { + private preState!: DashboardState; + private postState!: DashboardState; + + constructor(name: string, store: Store) { + super(name); + + this.store = store as Store; + } + + protected store: Store + + protected onExecute(): void { + this.store.select(DashboardSelectors.selectState).pipe(first()).subscribe(state => this.preState = state); + this.executing(); + this.store.select(DashboardSelectors.selectState).pipe(first()).subscribe(state => this.postState = state); + } + + protected abstract executing(): void; + + protected onUndo(): void { + this.store.dispatch(DashboardActions.setState({ state: this.preState })); + } + + protected onRedo(): void { + this.store.dispatch(DashboardActions.setState({ state: this.postState })); + } + + protected onAbort(): void { + this.store.dispatch(DashboardActions.setState({ state: this.preState })); + } + + protected isChart(item: DashboardItem): item is DashboardChart { + return item.type === DashboardItemType.Chart; + } + + protected getRows(grid: DashboardItem[][]): DashboardRow[] { + return grid.map(row => ({ + columns: row.map(item => ({ + id: item.id, + item: item, + itemType: item.type + })) + })); + } + + protected validateItems(grid: DashboardItem[][]): DashboardItem[][] { + grid.forEach((row, y) => { + row.forEach((item, x) => item.positions[0].x = x); + row.forEach(item => item.positions[0].y = y); + }); + + return grid; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/delete-item-command.ts b/projects/aas-portal/src/app/dashboard/commands/delete-item-command.ts new file mode 100644 index 00000000..c9a98cef --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/delete-item-command.ts @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; +import { DashboardPage, DashboardItem } from "../dashboard.state"; + +export class DeleteItemCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private items: DashboardItem[]) { + super('Delete item', store); + } + + protected executing(): void { + const page = cloneDeep(this.page); + page.items = page.items.filter(item => this.items.find(i => i.id === item.id) == null); + const grid = this.dashboard.getGrid(page); + this.validateItems(grid); + this.dashboard.update(page, this.getRows(grid)); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/delete-page-command.ts b/projects/aas-portal/src/app/dashboard/commands/delete-page-command.ts new file mode 100644 index 00000000..3be71bd2 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/delete-page-command.ts @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { DashboardPage } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class DeletePageCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage) { + super('Delete page', store); + } + + protected executing(): void { + this.dashboard.delete(this.page); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/move-down-command.ts b/projects/aas-portal/src/app/dashboard/commands/move-down-command.ts new file mode 100644 index 00000000..1ea3efbd --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/move-down-command.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardItem, DashboardPage, DashboardRow } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class MoveDownCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private item: DashboardItem) { + super('Move down', store); + } + + protected executing(): void { + if (!this.dashboard.canMoveDown(this.page, this.item)) { + throw new Error(`Item can not be moved down.`) + } + + let rows: DashboardRow[] | undefined; + const page = cloneDeep(this.page); + const item = page.items[this.page.items.indexOf(this.item)]; + const y = item.positions[0].y; + const grid = this.dashboard.getGrid(page); + const sourceRow = grid[y]; + if (y < grid.length - 1) { + const targetRow = grid[y + 1]; + if (targetRow.length < 12) { + sourceRow.splice(item.positions[0].x, 1); + targetRow.push(item); + if (sourceRow.length === 0) { + grid.splice(y, 1); + } + } + + rows = this.getRows(this.validateItems(grid)); + } else if (sourceRow.length > 1) { + sourceRow.splice(item.positions[0].x, 1); + const targetRow: DashboardItem[] = [item]; + grid.push(targetRow); + rows = this.getRows(this.validateItems(grid)); + } + + this.dashboard.update(page, rows); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/move-left-command.ts b/projects/aas-portal/src/app/dashboard/commands/move-left-command.ts new file mode 100644 index 00000000..76ce70d0 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/move-left-command.ts @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardItem, DashboardPage, DashboardRow } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class MoveLeftCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private item: DashboardItem) { + super('Move left', store); + } + + protected executing(): void { + if (!this.dashboard.canMoveLeft(this.page, this.item)) { + throw new Error(`Item can not be moved to the left.`) + } + + let rows: DashboardRow[] | undefined; + const page = cloneDeep(this.page); + const item = page.items[this.page.items.indexOf(this.item)]; + const grid = this.dashboard.getGrid(page); + const row = grid[item.positions[0].y]; + const index = row.indexOf(item); + if (index > 0) { + row.splice(index, 1); + row.splice(index - 1, 0, item); + rows = this.getRows(this.validateItems(grid)); + } + + this.dashboard.update(page, rows); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/move-right-command.ts b/projects/aas-portal/src/app/dashboard/commands/move-right-command.ts new file mode 100644 index 00000000..b150157f --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/move-right-command.ts @@ -0,0 +1,43 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardItem, DashboardPage, DashboardRow } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class MoveRightCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private item: DashboardItem) { + super('Move right', store); + } + + protected executing(): void { + if (!this.dashboard.canMoveRight(this.page, this.item)) { + throw new Error(`Item can not be moved to the right.`) + } + + let rows: DashboardRow[] | undefined; + const page = cloneDeep(this.page); + const item = page.items[this.page.items.indexOf(this.item)]; + const grid = this.dashboard.getGrid(page); + const row = grid[item.positions[0].y]; + const index = row.indexOf(item); + if (index < row.length - 1) { + row.splice(index, 1); + row.splice(index + 1, 0, item); + rows = this.getRows(this.validateItems(grid)); + } + + this.dashboard.update(page, rows); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/move-up-command.ts b/projects/aas-portal/src/app/dashboard/commands/move-up-command.ts new file mode 100644 index 00000000..4fe724be --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/move-up-command.ts @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardItem, DashboardPage, DashboardRow } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class MoveUpCommand extends DashboardCommand { + + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private item: DashboardItem) { + super('Move up', store); + } + + protected executing(): void { + if (!this.dashboard.canMoveUp(this.page, this.item)) { + throw new Error(`Item can not be moved up.`) + } + + let rows: DashboardRow[] | undefined; + const page = cloneDeep(this.page); + const item = page.items[this.page.items.indexOf(this.item)]; + const y = item.positions[0].y; + const grid = this.dashboard.getGrid(page); + const sourceRow = grid[y]; + if (y > 0) { + const targetRow = grid[y - 1]; + if (targetRow.length < 12) { + sourceRow.splice(item.positions[0].x, 1); + targetRow.push(item); + if (sourceRow.length === 0) { + grid.splice(y, 1); + } + } + + rows = this.getRows(this.validateItems(grid)); + } else if (sourceRow.length > 1) { + sourceRow.splice(item.positions[0].x, 1); + const targetRow: DashboardItem[] = [item]; + grid.splice(0, 0, targetRow); + rows = this.getRows(this.validateItems(grid)); + } + + this.dashboard.update(page, rows); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/rename-page-command.ts b/projects/aas-portal/src/app/dashboard/commands/rename-page-command.ts new file mode 100644 index 00000000..d3776bbb --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/rename-page-command.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { DashboardPage } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class RenamePageCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private newName: string) { + super('Delete page', store); + } + + protected executing(): void { + this.dashboard.rename(this.page, this.newName); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/set-chart-type-command.ts b/projects/aas-portal/src/app/dashboard/commands/set-chart-type-command.ts new file mode 100644 index 00000000..9d28e333 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/set-chart-type-command.ts @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + + import { Store } from "@ngrx/store"; + import { cloneDeep } from "lodash-es"; + import { DashboardChart, DashboardChartType, DashboardItem, DashboardPage } from "../dashboard.state"; + import { DashboardService } from "../dashboard.service"; + import { DashboardCommand } from "./dashboard-command"; + + export class SetChartTypeCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private item: DashboardItem, + private chartType: DashboardChartType) { + super('Set chart type', store); + } + + protected executing(): void { + const page = cloneDeep(this.page); + const item = page.items[this.page.items.indexOf(this.item)] as DashboardChart; + + if (this.isChart(item)) { + item.chartType = this.chartType; + this.dashboard.update(page); + } else { + throw new Error('Not implemented.'); + } + } + } \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/set-color-command.ts b/projects/aas-portal/src/app/dashboard/commands/set-color-command.ts new file mode 100644 index 00000000..ba1550cd --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/set-color-command.ts @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardItem, DashboardPage } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class SetColorCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private item: DashboardItem, + private index: number, + private color: string) { + super('Set color', store); + } + + protected executing(): void { + const page = cloneDeep(this.page); + const item = page.items[this.page.items.indexOf(this.item)]; + + if (this.isChart(item)) { + item.sources[this.index].color = this.color; + this.dashboard.update(page); + } else { + throw new Error('Not implemented.'); + } + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/commands/set-min-max-command.ts b/projects/aas-portal/src/app/dashboard/commands/set-min-max-command.ts new file mode 100644 index 00000000..92cfe369 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/commands/set-min-max-command.ts @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Store } from "@ngrx/store"; +import { cloneDeep } from "lodash-es"; +import { DashboardChart, DashboardPage } from "../dashboard.state"; +import { DashboardService } from "../dashboard.service"; +import { DashboardCommand } from "./dashboard-command"; + +export class SetMinMaxCommand extends DashboardCommand { + constructor( + store: Store, + private dashboard: DashboardService, + private page: DashboardPage, + private chart: DashboardChart, + private min?: number, + private max?: number) { + super('Set min/max', store); + } + + protected executing(): void { + const page = cloneDeep(this.page); + const chart = page.items[this.page.items.indexOf(this.chart)] as DashboardChart; + if (typeof this.min === 'number') { + chart.min = Number.isNaN(this.min) ? undefined : this.min; + } + + if (typeof this.max === 'number') { + chart.max = Number.isNaN(this.max) ? undefined : this.max; + } + + this.dashboard.update(page); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard-api.service.ts b/projects/aas-portal/src/app/dashboard/dashboard-api.service.ts new file mode 100644 index 00000000..322fce9c --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard-api.service.ts @@ -0,0 +1,24 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class DashboardApiService { + constructor( + private readonly http: HttpClient + ) { } + + public getBlobValue(url: string): Observable { + return this.http.get(url); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard.actions.ts b/projects/aas-portal/src/app/dashboard/dashboard.actions.ts new file mode 100644 index 00000000..8a570ef3 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.actions.ts @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from "@ngrx/store"; +import { DashboardPage, DashboardRow, DashboardState } from "./dashboard.state"; + +export enum DashboardActionType { + UPDATE_ROWS = '[Dashboard] update rows', + TOGGLE_EDIT_MODE = '[Dashboard] toggle edit mode', + SET_PAGE_NAME = '[Dashboard] set page name', + SET_PAGES = '[Dashboard] set pages', + ADD_NEW_PAGE = '[Dashboard] add new page', + UPDATE_PAGE = '[Dashboard] update page', + DELETE_PAGE = '[Dashboard] delete page', + RENAME_PAGE = '[Dashboard] rename page', + SET_STATE = '[Dashboard] set state' +} + +export const updateRows = createAction( + DashboardActionType.UPDATE_ROWS, + props<{ rows: DashboardRow[] }>()); + +export const toggleEditMode = createAction( + DashboardActionType.TOGGLE_EDIT_MODE); + +export const setPageName = createAction( + DashboardActionType.SET_PAGE_NAME, + props<{ name: string }>()); + +export const setPages = createAction( + DashboardActionType.SET_PAGES, + props<{ pages: DashboardPage[] }>()); + +export const updatePage = createAction( + DashboardActionType.UPDATE_PAGE, + props<{ page: DashboardPage; rows?: DashboardRow[] }>()); + +export const addNewPage = createAction( + DashboardActionType.ADD_NEW_PAGE, + props<{ name?: string }>()); + +export const deletePage = createAction( + DashboardActionType.DELETE_PAGE, + props<{ page: DashboardPage }>()); + +export const renamePage = createAction( + DashboardActionType.RENAME_PAGE, + props<{ page: DashboardPage; name: string }>()); + +export const setState = createAction( + DashboardActionType.SET_STATE, + props<{ state: DashboardState }>()); \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard.component.html b/projects/aas-portal/src/app/dashboard/dashboard.component.html new file mode 100644 index 00000000..2f404956 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.component.html @@ -0,0 +1,67 @@ + + +
+
+
+ + + + +
+
+
LABEL_NAME
+
+ +
+
+
+
LABEL_COLOR
+
+ +
+
+
+
LABEL_CHART_TYPE
+
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+
+
\ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard.component.scss b/projects/aas-portal/src/app/dashboard/dashboard.component.scss new file mode 100644 index 00000000..59dbed31 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.component.scss @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +canvas.fhg-chart { + border: 1px gray; + width: 150px; + height: 100px; + } + +div.fhg-chart-container { + position: relative; + margin: auto; + height: auto; + width: auto; + } \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard.component.ts b/projects/aas-portal/src/app/dashboard/dashboard.component.ts new file mode 100644 index 00000000..9cc1ab8f --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.component.ts @@ -0,0 +1,865 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import "chart.js/auto"; +import { AfterViewChecked, Component, ElementRef, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { isNumber } from 'lodash-es'; +import { Chart, ChartConfiguration, ChartDataset, ChartType } from 'chart.js'; +import { aas, convertToString, LiveNode, LiveRequest, parseNumber, WebSocketData } from 'common'; +import * as lib from "aas-lib"; +import { WebSocketSubject } from 'rxjs/webSocket'; +import { map, Subscription } from "rxjs"; +import { ActivatedRoute } from "@angular/router"; +import { Store } from "@ngrx/store"; + +import { DashboardService } from './dashboard.service'; +import { SelectionMode } from '../types/selection-mode'; +import { TranslateService } from "@ngx-translate/core"; +import { CommandHandlerService } from "../aas/command-handler.service"; +import { MoveLeftCommand } from "./commands/move-left-command"; +import { MoveRightCommand } from "./commands/move-right-command"; +import { MoveUpCommand } from "./commands/move-up-command"; +import { MoveDownCommand } from "./commands/move-down-command"; +import { SetColorCommand } from "./commands/set-color-command"; +import { DeletePageCommand } from "./commands/delete-page-command"; +import { RenamePageCommand } from "./commands/rename-page-command"; +import { AddNewPageCommand } from "./commands/add-new-page-command"; +import { DeleteItemCommand } from "./commands/delete-item-command"; +import { SetChartTypeCommand } from "./commands/set-chart-type-command"; +import { selectEditMode, selectName, selectPage, selectPages, selectRows, selectSelectionMode } from "./dashboard.selectors"; +import { SetMinMaxCommand } from "./commands/set-min-max-command"; +import { DashboardQuery, DashboardQueryParams } from "src/app/types/dashboard-query-params"; +import * as DashboardActions from './dashboard.actions'; +import { + DashboardItem, + DashboardItemType, + DashboardChart, + DashboardPage, + DashboardChartType, + DashboardRow, + DashboardColumn, + State +} from './dashboard.state'; +import { DashboardApiService } from "./dashboard-api.service"; + +interface UpdateTuple { + item: DashboardChart; + dataset: ChartDataset; +} + +interface ChartConfigurationTuple { + chart: Chart; + configuration: ChartConfiguration; +} + +interface TimeSeries { + value: string[]; + timestamp: string[]; +} + +@Component({ + selector: 'fhg-dashboard', + templateUrl: './dashboard.component.html', + styleUrls: ['./dashboard.component.scss'] +}) +export class DashboardComponent implements OnInit, OnDestroy, AfterViewChecked { + private readonly store: Store; + private readonly map = new Map(); + private readonly charts = new Map(); + private readonly subscription = new Subscription(); + private webSocketSubject: WebSocketSubject | null = null; + private reset = false; + private selections = new Set(); + private selectedSources = new Map(); + + constructor( + store: Store, + private readonly api: DashboardApiService, + private readonly activeRoute: ActivatedRoute, + private readonly auth: lib.AuthService, + private readonly translate: TranslateService, + private readonly webServiceFactory: lib.WebSocketFactoryService, + private readonly dashboard: DashboardService, + private readonly notify: lib.NotifyService, + private readonly toolbar: lib.ToolbarService, + private readonly commandHandler: CommandHandlerService, + private readonly window: lib.WindowService, + private readonly clipboard: lib.ClipboardService + ) { + this.store = store as Store; + this.page = this.dashboard.defaultPage ?? { name: '-', items: [], requests: [] }; + + this.subscription.add(this.store.select(selectPage).pipe() + .subscribe(value => this.updatePage(value))); + + this.subscription.add(this.store.select(selectEditMode).pipe() + .subscribe(editMode => this.updateEditMode(editMode))); + + this.subscription.add(this.store.select(selectSelectionMode).pipe() + .subscribe(selectionMode => this.selectionMode = selectionMode)); + + this.subscription.add(this.store.select(selectRows).pipe() + .subscribe(rows => this.rows = rows)); + } + + @ViewChildren('chart') + public chartContainers: QueryList> | null = null; + + public page: DashboardPage; + + public editMode = false; + + public rows: DashboardRow[] = [] + + public get selectedItem(): DashboardItem | null { + if (this.selections.size === 1) { + return this.findItem(this.selections.values().next().value) ?? null; + } + + return null; + } + + public get selectedItems(): DashboardItem[] { + const selectedItems: DashboardItem[] = []; + for (const id of this.selections) { + const item = this.findItem(id); + if (item) { + selectedItems.push(item); + } + } + + return selectedItems; + } + + public selectionMode: SelectionMode = SelectionMode.Single; + + public ngOnInit(): void { + this.toolbar.setToolbar(this.createToolbar()); + this.commandHandler.clear(); + + let query: DashboardQuery | undefined; + const params = this.activeRoute.snapshot.queryParams as DashboardQueryParams; + if (params.format) { + query = this.clipboard.get(params.format); + } + + const name = query ? query.page : this.auth.getCookie('.DashboardName'); + if (name) { + this.setPage(name); + } + } + + public ngOnDestroy(): void { + if (this.page) { + this.auth.setCookie('.DashboardName', this.page.name); + } else if (this.auth.checkCookie('.DashboardName')) { + this.auth.deleteCookie('.DashboardName'); + } + + this.dashboard.save(); + + this.toolbar.setToolbar(); + this.closeWebSocket(); + this.charts.forEach(item => item.chart.destroy()); + this.subscription.unsubscribe(); + } + + public ngAfterViewChecked(): void { + if (this.reset) { + try { + this.openWebSocket(); + if (this.chartContainers) { + this.createCharts(this.chartContainers); + this.play(); + } + } catch (error) { + this.notify.error(error); + } finally { + this.reset = false; + } + } + } + + public toggleSelection(column: DashboardColumn): void { + if (this.selections.has(column.id)) { + this.selections.delete(column.id); + } else { + if (this.selectionMode === SelectionMode.Single) { + this.selections.clear(); + } + + this.selections.add(column.id); + } + } + + public selected(column: DashboardColumn): boolean { + return this.selections.has(column.id); + } + + public getSources(column: DashboardColumn): string[] { + const item = column.item; + if (this.isChart(item)) { + return item.sources.map(source => source.label); + } + + return []; + } + + public changeSource(column: DashboardColumn, label: string): void { + const item = column.item; + if (this.isChart(item)) { + this.selectedSources.set(item.id, item.sources.findIndex(source => source.label === label)); + } + } + + public getChartType(column: DashboardColumn): DashboardChartType | undefined { + const item = column.item; + if (this.isChart(item)) { + return item.chartType; + } + + return undefined; + } + + public addNew(): void { + try { + this.commandHandler.execute(new AddNewPageCommand(this.store, this.dashboard)); + } catch (error) { + this.notify.error(error); + } + } + + public rename(): void { + try { + const name = this.window.prompt(this.translate.instant('PROMPT_DASHBOARD_NAME')); + if (name) { + this.commandHandler.execute(new RenamePageCommand(this.store, this.dashboard, this.page, name)); + } + } catch (error) { + this.notify.error(error); + } + } + + public delete(): void { + try { + if (this.selectedItems.length > 0) { + this.commandHandler.execute( + new DeleteItemCommand(this.store, this.dashboard, this.page, this.selectedItems)); + + this.selectedItems.forEach(item => { + this.selections.delete(item.id); + this.selectedSources.delete(item.id); + }); + } else { + this.commandHandler.execute(new DeletePageCommand(this.store, this.dashboard, this.page)); + this.selections.clear(); + this.selectedSources.clear(); + } + } catch (error) { + this.notify.error(error); + } + } + + public toggleEditMode(): void { + this.store.dispatch(DashboardActions.toggleEditMode()); + } + + public canMoveLeft(): boolean { + const selectedItem = this.selectedItem; + return this.editMode && selectedItem != null && this.dashboard.canMoveLeft(this.page, selectedItem); + } + + public moveLeft(): void { + try { + this.commandHandler.execute(new MoveLeftCommand(this.store, this.dashboard, this.page, this.selectedItem!)); + } catch (error) { + this.notify.error(error); + } + } + + public canMoveRight(): boolean { + const selectedItem = this.selectedItem; + return this.editMode && selectedItem != null && this.dashboard.canMoveRight(this.page, selectedItem); + } + + public moveRight(): void { + try { + this.commandHandler.execute(new MoveRightCommand(this.store, this.dashboard, this.page, this.selectedItem!)); + } catch (error) { + this.notify.error(error); + } + } + + public canMoveUp(): boolean { + const selectedItem = this.selectedItem; + return this.editMode && selectedItem != null && this.dashboard.canMoveUp(this.page, selectedItem); + } + + public moveUp(): void { + try { + this.commandHandler.execute(new MoveUpCommand(this.store, this.dashboard, this.page, this.selectedItem!)); + } catch (error) { + this.notify.error(error); + } + } + + public canMoveDown(): boolean { + const selectedItem = this.selectedItem; + return this.editMode && selectedItem != null && this.dashboard.canMoveDown(this.page, selectedItem); + } + + public moveDown(): void { + try { + this.commandHandler.execute(new MoveDownCommand(this.store, this.dashboard, this.page, this.selectedItem!)); + } catch (error) { + this.notify.error(error); + } + } + + public getColor(column: DashboardColumn) { + let color: string | undefined; + + try { + const item = column.item; + if (this.isChart(item)) { + const value = item.sources[this.selectedSources.get(column.id) ?? 0].color; + if (typeof value === 'string') { + color = value; + } + } + } catch (error) { + this.notify.log(lib.LogType.Error, error); + } + + return color ?? '#ffffff'; + } + + public changeColor(column: DashboardColumn, color: string): void { + try { + this.commandHandler.execute(new SetColorCommand( + this.store, + this.dashboard, + this.page, + column.item, + this.selectedSources.get(column.id) ?? 0, + color)); + } catch (error) { + this.notify.error(error); + } + } + + public changeChartType(column: DashboardColumn, value: string): void { + try { + this.commandHandler.execute(new SetChartTypeCommand( + this.store, + this.dashboard, + this.page, + column.item, + value as DashboardChartType)); + } catch (error) { + this.notify.error(error); + } + } + + public getMin(column: DashboardColumn): string { + const item = column.item; + if (this.isChart(item)) { + return typeof item.min === 'number' && !Number.isNaN(item.min) + ? convertToString(item.min, this.translate.currentLang) + : '-'; + } + + return '-' + } + + public changeMin(column: DashboardColumn, value: string): void { + try { + this.commandHandler.execute(new SetMinMaxCommand( + this.store, + this.dashboard, + this.page, + column.item as DashboardChart, + Number(value), + undefined)); + } catch (error) { + this.notify.error(error); + } + } + + public getMax(column: DashboardColumn): string { + const item = column.item; + if (this.isChart(item)) { + return typeof item.max === 'number' && item.max && !Number.isNaN(item.max) + ? convertToString(item.max, this.translate.currentLang) + : '-'; + } + + return '-' + } + + public changeMax(column: DashboardColumn, value: string): void { + try { + this.commandHandler.execute(new SetMinMaxCommand( + this.store, + this.dashboard, + this.page, + column.item as DashboardChart, + undefined, + Number(value))); + } catch (error) { + this.notify.error(error); + } + } + + public canUndo(): boolean { + return this.editMode && this.commandHandler.canUndo; + } + + public undo(): void { + if (this.canUndo()) { + this.commandHandler.undo(); + } + } + + public canRedo(): boolean { + return this.editMode && this.commandHandler.canRedo; + } + + public redo(): void { + if (this.canRedo()) { + this.commandHandler.redo(); + } + } + + private findItem(id: string): DashboardItem | undefined { + return this.page.items.find(item => item.id === id); + } + + private updatePage(page?: DashboardPage): void { + if (this.editMode) { + this.reset = false; + } else { + this.closeWebSocket(); + this.charts.forEach(item => item.chart.destroy()); + this.map.clear(); + this.reset = true; + } + + this.selections.clear(); + this.selectedSources.clear(); + + if (page) { + this.page = page; + this.store.dispatch(DashboardActions.updateRows({ rows: this.dashboard.getRows(this.page) })); + } + } + + private setPage(name: string): void { + if (this.page.name !== name && this.dashboard.find(name)) { + this.store.dispatch(DashboardActions.setPageName({ name })); + } + } + + private updateEditMode(value: boolean): void { + this.editMode = value; + if (this.editMode) { + this.closeWebSocket(); + this.map.clear(); + this.charts.forEach(item => item.chart.destroy()); + } else { + this.reset = true; + } + } + + private openWebSocket(): void { + if (this.page && this.page.requests && this.page.requests.length > 0) { + this.webSocketSubject = this.webServiceFactory.create(); + this.webSocketSubject.subscribe({ + next: this.socketOnMessage, + error: this.socketOnError + }); + } + } + + private closeWebSocket(): void { + if (this.webSocketSubject) { + this.webSocketSubject.unsubscribe(); + this.webSocketSubject = null; + } + } + + private createCharts(query: QueryList>): void { + this.charts.clear(); + this.page.items.forEach(item => { + if (this.isChart(item)) { + const canvas = query.find(element => element.nativeElement.id === item.id); + if (canvas) { + this.createChart(item, canvas.nativeElement); + } + } + }); + } + + private play(): void { + if (this.webSocketSubject) { + for (const request of this.page.requests) { + this.webSocketSubject.next(this.createMessage(request)); + } + } + } + + private createChart(item: DashboardChart, canvas: HTMLCanvasElement): void { + let tuple = this.charts.get(item.id); + switch (item.chartType) { + case DashboardChartType.Line: + tuple = this.createLineChart(item, canvas); + break; + case DashboardChartType.BarVertical: + tuple = this.createVerticalBarChart(item, canvas); + break; + case DashboardChartType.BarHorizontal: + tuple = this.createHorizontalBarChart(item, canvas); + break; + case DashboardChartType.TimeSeries: + tuple = this.createTimeSeriesChart(item, canvas); + break; + default: + throw new Error(`Chart type "${item.chartType}" is not supported.`); + } + + this.charts.set(item.id, tuple); + } + + private createLineChart(item: DashboardChart, canvas: HTMLCanvasElement): ChartConfigurationTuple { + const configuration: ChartConfiguration = { + type: 'line', + data: { + labels: [], + datasets: [] + }, + options: { + scales: { + 'y': { + min: item.min, + max: item.max + } + } + } + }; + + let length = 0; + for (const source of item.sources) { + const dataset: ChartDataset = { + type: 'line', + label: source.label, + backgroundColor: source.color, + borderColor: source.color, + borderWidth: 1, + data: [], + }; + + configuration.data.datasets.push(dataset); + if (source.node) { + this.map.set(source.node.nodeId, { item, dataset }); + } + + dataset.data = this.getInitialLineChartData(source.element as aas.Property); + length = Math.max(length, dataset.data.length); + } + + for (let i = 0; i < length; i++) { + configuration.data.labels!.push(i.toLocaleString()); + } + + return { chart: new Chart(canvas, configuration), configuration }; + } + + private createVerticalBarChart(item: DashboardChart, canvas: HTMLCanvasElement): ChartConfigurationTuple { + const configuration: ChartConfiguration = { + type: 'bar', + data: { + labels: [item.label], + datasets: [] + }, + options: { + indexAxis: 'x', + scales: { + y: { + min: item.min, + max: item.max + } + } + } + }; + + for (const source of item.sources) { + const dataset: ChartDataset = { + type: 'bar', + label: source.label, + backgroundColor: source.color, + borderColor: source.color, + borderWidth: 1, + data: [0], + }; + + configuration.data.datasets.push(dataset); + if (source.node) { + this.map.set(source.node.nodeId, { item, dataset }); + } + + dataset.data[0] = this.getInitialBarChartData(source.element as aas.Property) + } + + return { chart: new Chart(canvas, configuration), configuration }; + } + + private createHorizontalBarChart(item: DashboardChart, canvas: HTMLCanvasElement): ChartConfigurationTuple { + const configuration: ChartConfiguration = { + type: 'bar', + data: { + labels: [item.label], + datasets: [] + }, + options: { + indexAxis: 'y', + scales: { + x: { + min: item.min, + max: item.max + } + } + } + }; + + for (const source of item.sources) { + const dataset: ChartDataset = { + type: 'bar', + label: source.label, + backgroundColor: source.color, + borderColor: source.color, + borderWidth: 1, + data: [0], + }; + + configuration.data.datasets.push(dataset); + if (source.node) { + this.map.set(source.node.nodeId, { item, dataset }); + } + + dataset.data[0] = this.getInitialBarChartData(source.element as aas.Property) + } + + return { chart: new Chart(canvas, configuration), configuration }; + } + + private createTimeSeriesChart(item: DashboardChart, canvas: HTMLCanvasElement): ChartConfigurationTuple { + const configuration: ChartConfiguration = { + type: 'line', + data: { + labels: [], + datasets: [] + }, + options: { + scales: { + y: { + min: item.min, + max: item.max + } + }, + plugins: { + decimation: { + enabled: true, + algorithm: 'min-max' + }, + } + } + }; + + for (const source of item.sources) { + if (source.url) { + const dataset: ChartDataset = { + type: 'line', + label: source.label, + backgroundColor: source.color, + borderColor: source.color, + borderWidth: 1, + data: [], + animation: false, + pointRadius: 0 + }; + + configuration.data.datasets.push(dataset); + if (source.node) { + this.map.set(source.node.nodeId, { item, dataset }); + } + + this.getTimeSeriesData(source.url, dataset.data, configuration.data.labels!); + } + } + + return { chart: new Chart(canvas, configuration), configuration }; + } + + private getInitialLineChartData(property: aas.Property): number[] { + return [property.value ? parseNumber(property.value) : 0]; + } + + private getInitialBarChartData(property: aas.Property): number { + return property.value ? parseNumber(property.value) : 0; + } + + private getTimeSeriesData(url: string, data: number[], labels: string[]): void { + this.api.getBlobValue(url).subscribe({ + next: (value) => { + const timeSeries: TimeSeries = JSON.parse(window.atob(value)); + if (timeSeries.timestamp && timeSeries.value) { + const n = Math.min(timeSeries.value.length, timeSeries.timestamp.length); + for (let i = 0; i < n; i++) { + data.push(parseNumber(timeSeries.value[i])); + labels.push(timeSeries.timestamp[i]); + } + } + }, + error: (error) => this.notify.error(error) + }); + } + + private createMessage(request: LiveRequest): WebSocketData { + return { + type: 'LiveRequest', + data: request + } + } + + private socketOnMessage = (data: WebSocketData): void => { + if (data.type === 'LiveNode[]') { + this.updateCharts(data.data as LiveNode[]) + } + } + + private socketOnError = (error: unknown): void => { + this.notify.error(error); + } + + private updateCharts(nodes: LiveNode[]): void { + for (const node of nodes) { + const tuple = this.map.get(node.nodeId); + if (tuple) { + switch (tuple.item.chartType) { + case DashboardChartType.Line: + this.updateLineChart(tuple.item, tuple.dataset, node); + break; + case DashboardChartType.BarHorizontal: + case DashboardChartType.BarVertical: + this.updateBarChart(tuple.item, tuple.dataset, node); + break; + } + } + } + } + + private updateLineChart(item: DashboardChart, dataset: ChartDataset, node: LiveNode) { + const tuple = this.charts.get(item.id); + if (tuple) { + const data = dataset.data as number[]; + const labels = tuple.configuration.data.labels!; + + if (data.length > 100) { + data.shift(); + labels.shift(); + } + + let y = 0; + if (isNumber(node.value)) { + y = node.value; + } else if (this.isBigInt(node.value)) { + y = this.toNumber(node.value); + } + + data.push(y); + + if (labels.length < data.length) { + const x = new Date(node.timeStamp as number).toLocaleTimeString() ?? new Date().toLocaleTimeString(); + labels.push(x); + } + + tuple.chart.update(); + } + } + + private updateBarChart(item: DashboardChart, dataset: ChartDataset, node: LiveNode) { + const tuple = this.charts.get(item.id); + if (tuple) { + const data = dataset.data as number[]; + let y = 0; + if (isNumber(node.value)) { + y = node.value; + } else if (this.isBigInt(node.value)) { + y = this.toNumber(node.value); + } + + data[0] = y; + + tuple.chart.update(); + } + } + + private isBigInt(y: unknown): boolean { + return Array.isArray(y) && y.length === 2 && isNumber(y[0]) && isNumber(y[1]); + } + + private toNumber(value: number[]): number { + return value[0] === 0 ? value[1] : value[0] * 4294967296 + value[1]; + } + + private isChart(value?: DashboardItem | null): value is DashboardChart { + return value?.type === DashboardItemType.Chart; + } + + private createToolbar(): lib.Toolbar { + const $editMode = this.store.select(selectEditMode); + return { + groups: [ + this.toolbar.createGroup( + [ + this.toolbar.createSelect( + this.store.select(selectPages) + .pipe(map(pages => pages.map(page => this.toolbar.createOption( + page.name, + page.name)))), + this.store.select(selectName), + (name) => this.setPage(name)), + this.toolbar.createButton('bi bi-plus', () => this.addNew(), () => this.editMode), + this.toolbar.createButton('bi bi-pen', () => this.rename(), () => this.editMode), + this.toolbar.createButton('bi bi-trash', () => this.delete(), () => this.editMode) + ]), + this.toolbar.createGroup( + [ + this.toolbar.createSwitch( + 'Edit mode', + $editMode, + () => this.toggleEditMode()) + ]), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-arrow-90deg-left', () => this.undo(), () => this.canUndo()), + this.toolbar.createButton('bi bi-arrow-90deg-right', () => this.redo(), () => this.canRedo()), + ], + $editMode), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-box-arrow-left', () => this.moveLeft(), () => this.canMoveLeft()), + this.toolbar.createButton('bi bi-box-arrow-up', () => this.moveUp(), () => this.canMoveUp()), + this.toolbar.createButton('bi bi-box-arrow-down', () => this.moveDown(), () => this.canMoveDown()), + this.toolbar.createButton('bi bi-box-arrow-right', () => this.moveRight(), () => this.canMoveRight()) + ], + $editMode), + ] + }; + } +} diff --git a/projects/aas-portal/src/app/dashboard/dashboard.reducer.ts b/projects/aas-portal/src/app/dashboard/dashboard.reducer.ts new file mode 100644 index 00000000..2a352de4 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.reducer.ts @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from '@ngrx/store'; +import * as DashboardActions from './dashboard.actions'; +import { DashboardPage, DashboardRow, DashboardState } from './dashboard.state'; +import { SelectionMode } from '../types/selection-mode'; + +export function createPageName(pages: DashboardPage[] = []): string { + let name = ''; + for (let i = 1; i < Number.MAX_SAFE_INTEGER; i++) { + name = 'Dashboard ' + i; + if (!pages.find(page => page.name === name)) { + return name; + } + } + + throw new Error('Unable to create unique name.'); +} + +export const initialState: DashboardState = { + name: createPageName(), + pages: [], + editMode: false, + selectionMode: SelectionMode.Single, + rows: [] +}; + +export const dashboardReducer = createReducer(initialState, + on( + DashboardActions.addNewPage, + (state, { name }) => addNewPage(state, name) + ), + on( + DashboardActions.deletePage, + (state, { page }) => deletePage(state, page) + ), + on( + DashboardActions.renamePage, + (state, { page, name }) => renamePage(state, page, name) + ), + on( + DashboardActions.setPageName, + (state, { name }) => setPageName(state, name) + ), + on( + DashboardActions.setPages, + (state, { pages }) => setPages(state, pages) + ), + on( + DashboardActions.setState, + (_, { state }) => setState(state) + ), + on( + DashboardActions.toggleEditMode, + (state) => toggleEditMode(state) + ), + on( + DashboardActions.updatePage, + (state, { page, rows }) => updatePage(state, page, rows) + ), + on( + DashboardActions.updateRows, + (state, { rows }) => updateRows(state, rows) + )); + +function updateRows(state: DashboardState, rows: DashboardRow[]): DashboardState { + return { ...state, rows }; +} + +function toggleEditMode(state: DashboardState): DashboardState { + return { ...state, editMode: !state.editMode }; +} + +function setPageName(state: DashboardState, name: string): DashboardState { + return { ...state, name }; +} + +function setPages(state: DashboardState, pages: DashboardPage[]): DashboardState { + let name = state.name; + if (!pages.find(page => page.name === state.name)) { + name = pages[0].name; + } + + return { ...state, pages, name }; +} + +function updatePage(state: DashboardState, page: DashboardPage, rows?: DashboardRow[]): DashboardState { + const pages = [...state.pages]; + const index = pages.findIndex(item => item.name === page.name); + pages[index] = page; + + return rows ? { ...state, pages, rows } : { ...state, pages }; +} + +function deletePage(state: DashboardState, page: DashboardPage): DashboardState { + const pages = [...state.pages]; + const index = pages.indexOf(page); + if (index < 0) { + return state; + } + + pages.splice(index, 1); + if (pages.length === 0) { + pages.push({ name: createPageName(pages), items: [], requests: [] }); + } + + return { ...state, pages, name: pages[Math.min(pages.length - 1, index)].name }; +} + +function renamePage(state: DashboardState, page: DashboardPage, name: string): DashboardState { + const index = state.pages.indexOf(page) + if (index < 0) { + return state; + } + + const pages = [...state.pages] + pages[index] = { ...page, name }; + return state.name === page.name ? { ...state, pages, name } : { ...state, pages }; +} + +function addNewPage(state: DashboardState, name?: string): DashboardState { + name = name?.trim() ?? createPageName(state.pages); + const page: DashboardPage = { + name: name, + items: [], + requests: [] + }; + + const pages = [...state.pages, page]; + return { ...state, pages, name }; +} + +function setState(state: DashboardState): DashboardState { + return state; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard.selectors.ts b/projects/aas-portal/src/app/dashboard/dashboard.selectors.ts new file mode 100644 index 00000000..a47603de --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.selectors.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from "@ngrx/store"; +import { State } from "./dashboard.state"; + +const getName = (state: State) => state.dashboard.name; +const getPages = (state: State) => state.dashboard.pages; +const getEditMode = (state: State) => state.dashboard.editMode; +const getSelectionMode = (state: State) => state.dashboard.selectionMode; +const getRows = (state: State) => state.dashboard.rows; +const getState = (state: State) => state.dashboard; + +export const selectName = createSelector(getName, (name) => name); + +export const selectPages = createSelector(getPages, (pages) => pages); + +export const selectEditMode = createSelector(getEditMode, (editMode) => editMode); + +export const selectSelectionMode = createSelector(getSelectionMode, (selectionMode) => selectionMode); + +export const selectRows = createSelector(getRows, (rows) => rows); + +export const selectPage = createSelector( + getName, + getPages, + (name, pages) => pages.find(page => page.name === name)); + +export const selectState = createSelector(getState, (state) => state); diff --git a/projects/aas-portal/src/app/dashboard/dashboard.service.ts b/projects/aas-portal/src/app/dashboard/dashboard.service.ts new file mode 100644 index 00000000..5edab452 --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.service.ts @@ -0,0 +1,404 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { v4 as uuid } from 'uuid'; +import { aas, AASDocument, ApplicationError, getIdShortPath, getUnit, LiveNode } from 'common'; +import { cloneDeep } from 'lodash-es'; +import { ERRORS } from 'src/app/types/errors'; +import { Observable } from 'rxjs'; +import { Store } from '@ngrx/store'; +import { encodeBase64Url, AuthService } from 'aas-lib'; +import * as DashboardSelectors from './dashboard.selectors'; +import * as DashboardActions from './dashboard.actions'; +import { createPageName } from './dashboard.reducer'; +import { + DashboardItemType, + DashboardChart, + DashboardPage, + DashboardChartType, + DashboardItem, + DashboardRow, + State +} from './dashboard.state'; + +@Injectable({ + providedIn: 'root' +}) +export class DashboardService { + private readonly store: Store; + private _pages: DashboardPage[] = []; + private _name = ''; + private modified = false; + + constructor( + store: Store, + private auth: AuthService + ) { + this.store = store as Store; + + this.store.dispatch(DashboardActions.setPages({ pages: this.read() })); + this.pages = this.store.select(DashboardSelectors.selectPages); + this.name = this.store.select(DashboardSelectors.selectName); + + this.pages.subscribe(pages => this._pages = pages); + this.name.subscribe(name => this._name = name); + } + + public get defaultPage(): DashboardPage { + return this._pages.length > 0 ? this._pages[0] : { name: '-', items: [], requests: [] }; + } + + public readonly name: Observable; + + public readonly pages: Observable; + + public find(name: string): DashboardPage | undefined { + return this._pages.find(item => item.name === name); + } + + public setPageName(name: string) { + if (this._name !== name) { + if (!this.find(name)) { + throw new Error(`A dashboard with the name "${name}" does not exist.`); + } + + this.store.dispatch(DashboardActions.setPageName({ name })); + } + } + + public add(name: string, document: AASDocument, elements: aas.SubmodelElement[], chartType: DashboardChartType): void { + const pages = this._pages; + const i = pages.findIndex(item => item.name === name); + if (i < 0) { + throw new Error(`A dashboard with the name "${name}" does not exist.`); + } + + const page = cloneDeep(pages[i]); + const properties = elements.filter(item => item.modelType === 'Property') + .map(item => item as aas.Property); + + const blobs = elements.filter(item => item.modelType === 'Blob') + .map(item => item as aas.Blob); + + const nodes = this.getNodes(page, document); + if (properties.length > 0) { + switch (chartType) { + case DashboardChartType.Line: + this.addLineCharts(page, document.content!, properties, nodes); + break; + case DashboardChartType.BarVertical: + this.addBarChart(page, properties, nodes); + break; + default: + throw new Error(`Not implemented`); + } + + this.modified = true; + } + + if (blobs.length > 0) { + this.addScatterChart(document, page, blobs); + this.modified = true; + } + + if (this.modified) { + this.store.dispatch(DashboardActions.updatePage({ page })); + } + } + + public addNew(name?: string): void { + name = name?.trim(); + if (!name && this._pages.some(item => item.name === name)) { + throw new ApplicationError( + `A page withe name "${name}" already exists.`, + ERRORS.DASHBOARD_PAGE_ALREADY_EXISTS, + name); + } + + this.store.dispatch(DashboardActions.addNewPage({ name })); + this.modified = true; + } + + public rename(page: DashboardPage, name: string) { + name = name?.trim(); + if (!name) { + throw new Error('Valid page name expected.'); + } + + if (this._pages.some(item => item.name === name)) { + throw new ApplicationError( + `A page withe name "${name}" already exists.`, + ERRORS.DASHBOARD_PAGE_ALREADY_EXISTS, + name); + } + + this.store.dispatch(DashboardActions.renamePage({ page, name })); + this.modified = true; + } + + public getGrid(page: DashboardPage): DashboardItem[][] { + const map = new Map(); + page.items.forEach(item => { + const y = item.positions[0].y + let row = map.get(y); + if (!row) { + row = []; + map.set(y, row); + } + + row.push(item); + }); + + const grid: DashboardItem[][] = []; + let y = 0; + for (let i = 0; i < map.size;) { + const row = map.get(y); + if (row) { + row.sort((a, b) => a.positions[0].x - b.positions[0].x); + grid.push(row); + ++i; + } + + ++y; + } + + return grid; + } + + public getRows(page: DashboardPage): DashboardRow[] { + return this.getGrid(page).map(row => ({ + columns: row.map(item => ({ + id: item.id, + item: item, + itemType: item.type + })) + })); + } + + public canMoveLeft(page: DashboardPage, item: DashboardItem): boolean { + return item.positions[0].x > 0 + } + + public canMoveRight(page: DashboardPage, item: DashboardItem): boolean { + const row = this.getRow(page, item); + return item.positions[0].x < row.length - 1; + } + + public canMoveUp(page: DashboardPage, item: DashboardItem): boolean { + const grid = this.getGrid(page); + const y = item.positions[0].y; + if (y > 0) { + if (grid[y - 1].length < 12) { + return true + } + } else if (grid[y].length > 1) { + return true; + } + + return false; + } + + public canMoveDown(page: DashboardPage, item: DashboardItem): boolean { + const grid = this.getGrid(page); + const y = item.positions[0].y; + if (y < grid.length - 1) { + if (grid[y + 1].length < 12) { + return true; + } + } else if (grid[y].length > 1) { + return true; + } + + return false; + } + + public update(page: DashboardPage, rows?: DashboardRow[]): void { + this.store.dispatch(DashboardActions.updatePage({ page, rows })); + this.modified = true; + } + + public delete(page: DashboardPage): void { + this.store.dispatch(DashboardActions.deletePage({ page })); + this.modified = true; + } + + public save(): void { + if (this.modified) { + this.write(); + this.modified = false; + } + } + + private addLineCharts( + page: DashboardPage, + env: aas.Environment, + properties: aas.Property[], + nodes: LiveNode[] | null): void { + let columnIndex = 0; + let rowIndex = page.items.length > 0 ? Math.max(...page.items.map(item => item.positions[0].y)) + 1 : 0; + for (const property of properties) { + let node: LiveNode | null = null; + if (nodes != null && property.nodeId && !this.containsNode(nodes, property.nodeId)) { + node = { nodeId: property.nodeId, valueType: property.valueType ?? 'undefined' }; + nodes.push(node); + } + + let label = property.idShort; + const unit = getUnit(env, property); + if (unit) { + label += ' ' + unit; + } + + const item: DashboardChart = { + label: label, + id: uuid(), + type: DashboardItemType.Chart, + chartType: DashboardChartType.Line, + positions: [{ x: columnIndex, y: rowIndex }], + sources: [{ + label: property.idShort, + color: this.createRandomColor(), + element: property, + node: node, + }] + }; + + page.items.push(item); + ++rowIndex; + columnIndex = 0; + } + } + + private addBarChart(page: DashboardPage, properties: aas.Property[], nodes: LiveNode[] | null): void { + const rowIndex = page.items.length > 0 ? Math.max(...page.items.map(item => item.positions[0].y)) + 1 : 0; + const item: DashboardChart = { + label: '', + id: uuid(), + type: DashboardItemType.Chart, + chartType: DashboardChartType.BarVertical, + positions: [{ x: 0, y: rowIndex }], + sources: [] + }; + + for (const property of properties) { + let node: LiveNode | null = null; + if (nodes != null && property.nodeId && !this.containsNode(nodes, property.nodeId)) { + node = { nodeId: property.nodeId, valueType: property.valueType ?? 'undefined' }; + nodes.push(node); + } + + item.sources.push({ + label: property.idShort, + color: this.createRandomColor(), + element: property, + node: node, + }); + } + + page.items.push(item); + } + + private addScatterChart(document: AASDocument, page: DashboardPage, blobs: aas.Blob[]): void { + let columnIndex = 0; + let rowIndex = page.items.length > 0 ? Math.max(...page.items.map(item => item.positions[0].y)) + 1 : 0; + for (const blob of blobs) { + if (blob.parent) { + const label = blob.idShort; + const container = encodeBase64Url(document.container); + const id = encodeBase64Url(document.id); + const smId = encodeBase64Url(blob.parent.keys[0].value); + const path = getIdShortPath(blob); + const item: DashboardChart = { + label: label, + id: uuid(), + type: DashboardItemType.Chart, + chartType: DashboardChartType.TimeSeries, + positions: [{ x: columnIndex, y: rowIndex }], + sources: [{ + label: blob.idShort, + color: this.createRandomColor(), + element: blob, + node: null, + url: `/api/v1/containers/${container}/documents/${id}/submodels/${smId}/blobs/${path}/value` + }] + }; + + page.items.push(item); + ++rowIndex; + columnIndex = 0; + } + } + } + + private getNodes(page: DashboardPage, document: AASDocument): LiveNode[] | null { + let nodes: LiveNode[] | null = null; + if (document.onlineReady) { + const index = this.indexOfRequest(page, document); + if (index >= 0) { + const request = page.requests[index]; + nodes = [...request.nodes]; + page.requests[index] = { ...request, nodes }; + } else { + nodes = []; + page.requests.push({ + type: document.endpoint.type, + url: document.container, + id: document.id, + nodes: nodes + }); + } + } + + return nodes; + } + + private getRow(page: DashboardPage, item: DashboardItem): DashboardItem[] { + const y = item.positions[0].y; + const row = page.items.filter(item => item.positions[0].y === y); + row.sort((a, b) => a.positions[0].x - b.positions[0].x); + return row; + } + + private indexOfRequest(page: DashboardPage, document: AASDocument): number { + const container = document.container; + const type = document.endpoint.type; + const id = document.id; + return page.requests.findIndex(item => { + return item.url === container && (type === 'opc' || item.id === id); + }); + } + + private containsNode(nodes: LiveNode[], nodeId: string): boolean { + return nodes.some(node => node.nodeId === nodeId); + } + + private write(): void { + if (this._pages.length > 0) { + this.auth.setCookie('.Dashboard', JSON.stringify(this._pages)); + } else { + this.auth.deleteCookie('.Dashboard'); + } + } + + private read(): DashboardPage[] { + const value = this.auth.getCookie('.Dashboard'); + if (value) { + return JSON.parse(value); + } + + return [{ name: createPageName(), items: [], requests: [] }]; + } + + private createRandomColor(): string { + const red = Math.trunc(Math.random() * 255).toString(16); + const green = Math.trunc(Math.random() * 255).toString(16); + const blue = Math.trunc(Math.random() * 255).toString(16); + return '#' + red + green + blue; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/dashboard/dashboard.state.ts b/projects/aas-portal/src/app/dashboard/dashboard.state.ts new file mode 100644 index 00000000..4748b77a --- /dev/null +++ b/projects/aas-portal/src/app/dashboard/dashboard.state.ts @@ -0,0 +1,90 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { LiveNode, LiveRequest, aas } from 'common'; +import { SelectionMode } from '../types/selection-mode'; + +export type DashboardColor = string; + +export enum DashboardItemType { + Chart = 'Chart', + Grid = 'Grid' +} + +export enum DashboardChartType { + Line = 'Line', + BarVertical = 'BarVertical', + BarHorizontal = 'BarHorizontal', + TimeSeries = 'TimeSeries' +} + +export interface DashboardSource { + label: string; + color: DashboardColor; + element: aas.Property | aas.Blob; + node: LiveNode | null; + url?: string; +} + +export interface DashboardItemPosition { + x: number; + y: number; +} + +export interface DashboardSelectable { + selected: boolean; + column: DashboardItem; +} + +export interface DashboardItem { + type: DashboardItemType; + id: string; + positions: DashboardItemPosition[]; +} + +export interface DashboardChart extends DashboardItem { + label: string; + type: DashboardItemType.Chart; + chartType: DashboardChartType; + sources: DashboardSource[]; + min?: number; + max?: number; +} + +export interface DashboardGrid extends DashboardItem { + type: DashboardItemType.Grid; + items: DashboardItem[]; +} + +export interface DashboardPage { + name: string; + items: DashboardItem[]; + requests: LiveRequest[]; +} + +export interface DashboardColumn { + id: string; + item: DashboardItem; + itemType: DashboardItemType; +} + +export interface DashboardRow { + columns: DashboardColumn[] +} + +export interface DashboardState { + name: string; + pages: DashboardPage[]; + editMode: boolean; + selectionMode: SelectionMode; + rows: DashboardRow[] +} + +export interface State { + dashboard: DashboardState; +} diff --git a/projects/aas-portal/src/app/http-loader-factory.ts b/projects/aas-portal/src/app/http-loader-factory.ts new file mode 100644 index 00000000..84533c09 --- /dev/null +++ b/projects/aas-portal/src/app/http-loader-factory.ts @@ -0,0 +1,14 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClient } from '@angular/common/http'; +import { TranslateHttpLoader } from '@ngx-translate/http-loader'; + +export function HttpLoaderFactory(http: HttpClient) { + return new TranslateHttpLoader(http, './assets/i18n/', '.json'); +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/index.ts b/projects/aas-portal/src/app/index.ts new file mode 100644 index 00000000..d60cae5c --- /dev/null +++ b/projects/aas-portal/src/app/index.ts @@ -0,0 +1,14 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HTTP_INTERCEPTORS } from '@angular/common/http'; +import { AuthInterceptor } from 'aas-lib'; + +export const httpInterceptorProviders = [ + { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, +]; \ No newline at end of file diff --git a/projects/aas-portal/src/app/main/main.component.html b/projects/aas-portal/src/app/main/main.component.html new file mode 100644 index 00000000..4fc7a926 --- /dev/null +++ b/projects/aas-portal/src/app/main/main.component.html @@ -0,0 +1,37 @@ + + +
+ +
+ + +
+
+ \ No newline at end of file diff --git a/projects/aas-portal/src/app/main/main.component.scss b/projects/aas-portal/src/app/main/main.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/main/main.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/main/main.component.ts b/projects/aas-portal/src/app/main/main.component.ts new file mode 100644 index 00000000..8cc9c77c --- /dev/null +++ b/projects/aas-portal/src/app/main/main.component.ts @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Router } from '@angular/router'; +import { Subscription, first } from 'rxjs'; +import { ClipboardService, WindowService, AASQuery } from 'aas-lib'; +import { ProjectService } from '../project/project.service'; + +export enum LinkId { + START = 0, + AAS = 1, + VIEW = 2, + DASHBOARD = 3, + ABOUT = 4 +} + +export interface LinkDescriptor { + id: LinkId; + name: string; + url: string; +} + +@Component({ + selector: 'fhg-main', + templateUrl: './main.component.html', + styleUrls: ['./main.component.scss'] +}) +export class MainComponent implements OnInit, OnDestroy { + private readonly subscription = new Subscription(); + private readonly _links: LinkDescriptor[] = [ + { + id: LinkId.START, name: "CAPTION_START", url: "/start" + }, + { + id: LinkId.AAS, name: "CAPTION_AAS", url: '/aas' + }, + { + id: LinkId.VIEW, name: "CAPTION_VIEW", url: '/view' + }, + { + id: LinkId.DASHBOARD, name: "CAPTION_DASHBOARD", url: '/dashboard' + }, + { + id: LinkId.ABOUT, name: "CAPTION_ABOUT", url: "/about" + } + ]; + + constructor( + private readonly router: Router, + private readonly window: WindowService, + private readonly project: ProjectService, + private readonly clipboard: ClipboardService) { + } + + public activeId = LinkId.START; + + public get links(): LinkDescriptor[] { + return this._links; + } + + public ngOnInit(): void { + const params = this.window.getQueryParams(); + const id = params.get('id'); + if (id) { + this.project.findDocument(id).pipe(first()).subscribe(document => { + if (document) { + this.clipboard.set('AASQuery', { id: document.id } as AASQuery); + this.router.navigateByUrl('/aas?format=AASQuery'); + } else { + this.router.navigateByUrl('/start'); + }}); + } else { + this.router.navigateByUrl('/start'); + } + } + + public ngOnDestroy(): void { + this.subscription.unsubscribe(); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/project/project-api.service.ts b/projects/aas-portal/src/app/project/project-api.service.ts new file mode 100644 index 00000000..c44b0463 --- /dev/null +++ b/projects/aas-portal/src/app/project/project-api.service.ts @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { HttpClient, } from '@angular/common/http'; +import { AASDocument, AASWorkspace, aas } from 'common'; +import { Observable } from 'rxjs'; +import { encodeBase64Url } from 'aas-lib'; + +/** The client side AAS provider service. */ +@Injectable({ + providedIn: 'root' +}) +export class ProjectAPIService { + constructor( + private readonly http: HttpClient, + ) {} + + /** + * Returns the basic data of all available AAS containers. + * @returns An array of `AASContainer`. + */ + public getWorkspaces(): Observable { + return this.http.get('/api/v1/workspaces'); + } + + /** + * Returns all documents contained in the container with the specified URL. + * @param url The container URL. + * @returns The documents of the specified container. + */ + public getDocuments(url: string): Observable { + return this.http.get(`/api/v1/containers/${encodeBase64Url(url)}/documents`); + } + + /** + * Gets the referenced AAS document. + * @param id The identification or name of the document. + * @param url The URL of the container. + * @returns The AAS document. + */ + public getDocument(id: string, url?: string): Observable { + return this.http.get( + url ? `/api/v1/containers/${encodeBase64Url(url)}/documents/${encodeBase64Url(id)}` + : `/api/v1/documents/${encodeBase64Url(id)}`); + } + + /** + * Loads the element structure of the specified document. + * @param id The identification of the AAS document. + * @param url The URL of the container. + * @returns The root of the element structure. + */ + public getContent(id: string, url: string): Observable { + return this.http.get( + `/api/v1/containers/${encodeBase64Url(url)}/documents/${encodeBase64Url(id)}/content`); + } + + /** + * Adds a new endpoint to the AASServer configuration. + * @param endpoint The registry. + */ + public addEndpoint(name: string, url: string): Observable { + return this.http.post(`/api/v1/endpoints/${name}`, { url }); + } + + /** + * Removes the specified endpoint from the AASServer configuration. + * @param name The name of the endpoint. + */ + public removeEndpoint(name: string): Observable { + return this.http.delete(`/api/v1/endpoints/${name}`); + } + + /** + * Restores the default workspace/container configuration. + */ + public reset(): Observable { + return this.http.delete('/api/v1/containers/reset'); + } + + /** + * Delete the specified AAS document from the corresponding AAS container. + * @param id The identification of the AAS document to delete. + * @param url The URL of the AAS container. + * @returns An observable. + */ + public deleteDocument(id: string, url: string): Observable { + return this.http.delete( + `/api/v1/containers/${encodeBase64Url(url)}/documents/${encodeBase64Url(id)}`); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/project/project.actions.ts b/projects/aas-portal/src/app/project/project.actions.ts new file mode 100644 index 00000000..6ef050e3 --- /dev/null +++ b/projects/aas-portal/src/app/project/project.actions.ts @@ -0,0 +1,130 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from '@ngrx/store'; +import { TypedAction } from '@ngrx/store/src/models'; +import { aas, AASContainer, AASDocument, AASWorkspace } from 'common'; + +export enum ProjectActionType { + INITIALIZE = '[Project] initialize', + SET_STATE = '[Project] set state', + ADD_DOCUMENT = '[Project] add document', + REMOVE_DOCUMENT = '[Project] remove document', + APPLY_DOCUMENT = '[Project] apply document', + SET_DOCUMENT = '[Project] set document', + SET_ACTIVE_WORKSPACE = '[Project] set active workspace', + SET_WORKSPACE = '[Project] set workspace', + DOCUMENT_ADDED = '[Project] document added', + DOCUMENT_UPDATED = '[Project] document updated', + ADD_WORKSPACE = '[Project] add workspace', + REMOVE_WORKSPACE = '[Project] remove workspace', + ENDPOINT_ADDED = '[Project] endpoint added', + ENDPOINT_REMOVED = '[Project] endpoint removed', + CONTAINER_ADDED = '[Project] container added', + ADD_CONTAINER = '[Project] add container', + REMOVE_CONTAINER = '[Project] remove container', + CREATE_WORKSPACE = '[Project] create workspace', + DELETE_WORKSPACE = '[Project] delete workspace', + UPDATE_WORKSPACE = '[Project] update workspace', + SET_ERROR = '[Project] set error' +} + +export const initialize = createAction( + ProjectActionType.INITIALIZE); + +export const setState = createAction( + ProjectActionType.SET_STATE, + props<{ workspaces: AASWorkspace[]; workspace: AASWorkspace | null }>()); + +export const addDocument = createAction( + ProjectActionType.ADD_DOCUMENT, + props<{ document: AASDocument; content?: aas.Environment }>()); + +export const removeDocument = createAction( + ProjectActionType.REMOVE_DOCUMENT, + props<{ document: AASDocument }>()); + +export const applyDocument = createAction( + ProjectActionType.APPLY_DOCUMENT, + props<{ document: AASDocument }>()); + +export const setDocument = createAction( + ProjectActionType.SET_DOCUMENT, + props<{ index: number; document: AASDocument; content?: aas.Environment }>()); + +export const setActiveWorkspace = createAction( + ProjectActionType.SET_ACTIVE_WORKSPACE, + props<{ name: string }>()); + +export const setWorkspace = createAction( + ProjectActionType.SET_WORKSPACE, + props<{ workspace: AASWorkspace | null }>()); + +export const documentAdded = createAction( + ProjectActionType.DOCUMENT_ADDED, + props<{ document: AASDocument }>()); + +export const documentUpdated = createAction( + ProjectActionType.DOCUMENT_UPDATED, + props<{ document: AASDocument }>()); + +export const addWorkspace = createAction( + ProjectActionType.ADD_WORKSPACE, + props<{ workspace: AASWorkspace }>()); + +export const removeWorkspace = createAction( + ProjectActionType.REMOVE_WORKSPACE, + props<{ workspace: AASWorkspace }>()); + +export const endpointAdded = createAction( + ProjectActionType.ENDPOINT_ADDED, + props<{ endpoint: string }>()); + +export const endpointRemoved = createAction( + ProjectActionType.ENDPOINT_REMOVED, + props<{ endpoint: string }>()); + +export const addContainer = createAction( + ProjectActionType.ADD_CONTAINER, + props<{ name: string; container: AASContainer }>()); + +export const removeContainer = createAction( + ProjectActionType.REMOVE_CONTAINER, + props<{ name: string; container: AASContainer }>()); + +export const setError = createAction( + ProjectActionType.SET_ERROR, + props<{error: Error}>()); + +export interface ApplyDocumentAction extends TypedAction { + document: AASDocument; +} + +export interface EndpointRemovedAction extends TypedAction { + endpoint: string +} + +export interface SetActiveWorkspaceAction extends TypedAction { + name: string; +} + +export interface DocumentAddedAction extends TypedAction { + document: AASDocument; +} + +export interface DocumentUpdatedAction extends TypedAction { + document: AASDocument; +} + +export interface EndpointAddedAction extends TypedAction { + endpoint: string; +} + +export interface EndpointRemovedAction extends TypedAction { + endpoint: string; +} diff --git a/projects/aas-portal/src/app/project/project.effects.ts b/projects/aas-portal/src/app/project/project.effects.ts new file mode 100644 index 00000000..9c144946 --- /dev/null +++ b/projects/aas-portal/src/app/project/project.effects.ts @@ -0,0 +1,224 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { Store } from '@ngrx/store'; +import { AASWorkspace } from 'common'; +import { AuthService } from 'aas-lib'; +import { catchError, EMPTY, exhaustMap, from, map, merge, mergeMap, Observable, of, zip } from 'rxjs'; + +import { ProjectAPIService } from './project-api.service'; +import { getEndpointName } from '../configuration'; +import * as ProjectSelectors from './project.selectors'; +import * as ProjectActions from './project.actions'; +import { TypedAction } from '@ngrx/store/src/models'; +import { State } from './project.state'; + +@Injectable() +export class ProjectEffects { + private readonly store: Store; + + constructor( + private readonly actions: Actions, + store: Store, + private readonly auth: AuthService, + private readonly api: ProjectAPIService + ) { + this.store = store as Store; + } + + public initialize = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.INITIALIZE), + exhaustMap(() => this.api.getWorkspaces().pipe( + mergeMap(items => { + const workspaces = this.initializeWorkspaces(items); + const workspace = this.initializeWorkspace(workspaces); + if (workspace) { + return merge( + of(ProjectActions.setState({ workspaces, workspace })), + this.loadDocuments(workspace)); + } + + return of(ProjectActions.setState({ workspaces, workspace })); + })))); + }); + + public setActiveWorkspace = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.SET_ACTIVE_WORKSPACE), + exhaustMap(action => zip(of(action.name), this.store.select(ProjectSelectors.selectWorkspace(action.name)))), + mergeMap(tuple => { + const workspace = tuple[1]; + if (!workspace) { + return of(ProjectActions.setError({ + error: new Error(`A workspace with the name ${tuple[0]} does not exist`) + })); + } + + this.auth.setCookie('.workspace', workspace.name); + return merge(of(ProjectActions.setWorkspace({ workspace })), this.loadDocuments(workspace)); + })); + }); + + public documentAdded = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.DOCUMENT_ADDED), + exhaustMap(action => zip(of(action.document), this.store.select(ProjectSelectors.selectCurrentWorkspace))), + mergeMap(tuple => { + const workspace = tuple[1]; + const document = tuple[0]; + if (workspace) { + if (workspace.containers.some(item => item.url === document.container)) { + if (document.content === null) { + return this.api.getContent(document.id, document.container).pipe( + map(content => ProjectActions.addDocument({ document, content }))); + } else { + return of(ProjectActions.addDocument({ document })); + } + } + } + + return EMPTY; + })) + }); + + public documentUpdated = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.DOCUMENT_UPDATED), + exhaustMap(action => zip(of(action.document), this.store.select(ProjectSelectors.selectDocuments))), + mergeMap(tuple => { + const documents = tuple[1]; + const document = tuple[0]; + const index = documents.findIndex(item => + item.container === document.container && item.id === document.id); + + if (index >= 0) { + return this.api.getContent(document.id, document.container).pipe( + map(content => ProjectActions.setDocument({ index, document, content }))); + } + + return EMPTY; + })) + }); + + public applyDocument = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.APPLY_DOCUMENT), + exhaustMap(action => zip(of(action.document), this.store.select(ProjectSelectors.selectDocuments))), + mergeMap(tuple => { + const document = tuple[0]; + const index = tuple[1].findIndex(item => item.id == document.id && + item.container === document.container); + + if (index >= 0) { + return of(ProjectActions.setDocument({ index, document })); + } else { + return EMPTY; + } + })) + }); + + public endpointAdded = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.ENDPOINT_ADDED), + exhaustMap(action => zip(of(action.endpoint), this.store.select(ProjectSelectors.selectWorkspaces))), + mergeMap(tuple => { + const url = new URL(tuple[0]); + const workspace: AASWorkspace = { + name: getEndpointName(url), + containers: [] + }; + + if (tuple[1].length === 0) { + return of( + ProjectActions.addWorkspace({ workspace }), + ProjectActions.setActiveWorkspace({ name: workspace.name })); + } else { + return of(ProjectActions.addWorkspace({ workspace })); + } + })) + }); + + public endpointRemoved = createEffect(() => { + return this.actions.pipe( + ofType(ProjectActions.ProjectActionType.ENDPOINT_REMOVED), + exhaustMap(action => zip( + of(getEndpointName(action.endpoint)), + this.store.select(ProjectSelectors.selectProject))), + mergeMap(tuple => { + const workspaces = tuple[1].workspaces; + const workspace = tuple[1].workspace; + const name = tuple[0]; + if (workspace) { + let index = workspaces.findIndex(item => item.name === name); + if (index >= 0) { + if (workspaces.length >= 2) { + ++index; + if (index >= workspaces.length) { + index = length - 2; + } + + const next = workspaces[index]; + return of( + ProjectActions.removeWorkspace({ workspace }), + ProjectActions.setActiveWorkspace({ name: next.name })); + } + + return of(ProjectActions.removeWorkspace({ workspace })); + } + } + + return EMPTY; + })) + }); + + private initializeWorkspaces(workspaces: AASWorkspace[]): AASWorkspace[] { + const value = this.auth.getCookie('.workspaces'); + if (value) { + workspaces = [...workspaces, ...JSON.parse(value) as AASWorkspace[]]; + } + + workspaces.sort((a, b) => this.compareWorkspaces(a, b)); + return workspaces; + } + + private initializeWorkspace(workspaces: AASWorkspace[]): AASWorkspace | null { + let workspace: AASWorkspace | undefined; + if (this.auth.checkCookie('.workspace')) { + const name = this.auth.getCookie('.workspace'); + workspace = workspaces.find((item) => item.name === name); + } + + if (workspace == null && workspaces.length > 0) { + workspace = workspaces[0]; + } + + return workspace ?? null; + } + + private loadDocuments(workspace: AASWorkspace): Observable> { + return from(workspace.containers).pipe( + catchError(() => EMPTY), + mergeMap(container => this.api.getDocuments(container.url)), + mergeMap(documents => from(documents)), + mergeMap(document => { + if (document.content === null) { + return this.api.getContent(document.id, document.container).pipe( + map(content => ProjectActions.addDocument({ document, content }))); + } + + return of(ProjectActions.addDocument({ document })); + })); + } + + private compareWorkspaces(a: AASWorkspace, b: AASWorkspace): number { + return a.name.localeCompare(b.name); + } +} diff --git a/projects/aas-portal/src/app/project/project.reducer.ts b/projects/aas-portal/src/app/project/project.reducer.ts new file mode 100644 index 00000000..4f042092 --- /dev/null +++ b/projects/aas-portal/src/app/project/project.reducer.ts @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from '@ngrx/store'; +import { aas, AASContainer, AASDocument, AASWorkspace } from 'common'; +import * as ProjectActions from './project.actions'; +import { initialState, ProjectState } from './project.state'; + +export const projectReducer = createReducer(initialState, + on( + ProjectActions.setState, + (state, { workspaces, workspace }) => setState(state, workspaces, workspace) + ), + on( + ProjectActions.addContainer, + (state, { name, container }) => addContainer(state, name, container) + ), + on( + ProjectActions.addDocument, + (state, { document, content }) => addDocument(state, document, content) + ), + on( + ProjectActions.addWorkspace, + (state, { workspace }) => addWorkspace(state, workspace) + ), + on( + ProjectActions.removeContainer, + (state, { name, container }) => removeContainer(state, name, container) + ), + on( + ProjectActions.removeDocument, + (state, { document }) => removeDocument(state, document) + ), + on( + ProjectActions.removeWorkspace, + (state, { workspace }) => removeWorkspace(state, workspace) + ), + on( + ProjectActions.setDocument, + (state, { index, document, content }) => setDocument(state, index, document, content) + ), + on( + ProjectActions.setWorkspace, + (state, { workspace }) => setWorkspace(state, workspace) + ), + on( + ProjectActions.setError, + (state, { error }) => setError(state, error) + ) +); + +function setState(state: ProjectState, workspaces: AASWorkspace[], workspace: AASWorkspace | null): ProjectState { + try { + return { ...state, workspaces, workspace }; + } catch (error) { + return { ...state, error }; + } +} + +function addDocument( + state: ProjectState, + document: AASDocument, + content?: aas.Environment): ProjectState { + try { + if (content) { + document = { ...document, content }; + } + + return { ...state, documents: [...state.documents, document] } + } catch (error) { + return { ...state, error }; + } +} + +function removeDocument(state: ProjectState, document: AASDocument): ProjectState { + try { + const documents = state.documents.filter(item => item.container !== document.container || item.id !== document.id); + return { ...state, documents }; + } catch (error) { + return { ...state, error }; + } +} + +function setDocument( + state: ProjectState, + index: number, + document: AASDocument, + content?: aas.Environment): ProjectState { + try { + const documents = [...state.documents]; + if (content) { + document = { ...document, content }; + } + + documents[index] = document; + return { ...state, documents }; + } catch (error) { + return { ...state, error }; + } +} + +function addWorkspace(state: ProjectState, workspace: AASWorkspace): ProjectState { + try { + const workspaces = [...state.workspaces, workspace]; + workspaces.sort((a, b) => compareWorkspaces(a, b)); + return { ...state, workspaces }; + } catch (error) { + return { ...state, error }; + } + + function compareWorkspaces(a: AASWorkspace, b: AASWorkspace): number { + return a.name.localeCompare(b.name); + } +} + +function removeWorkspace(state: ProjectState, workspace: AASWorkspace): ProjectState { + try { + const workspaces = state.workspaces.filter(item => item !== workspace); + return workspaces.length < 0 ? { ...state, workspaces } : { ...state, workspaces, workspace: null, documents: [] }; + } catch (error) { + return { ...state, error }; + } +} + +function addContainer(state: ProjectState, name: string, container: AASContainer): ProjectState { + try { + const workspaces = [...state.workspaces]; + const index = workspaces.findIndex(item => item.name === name); + if (index >= 0) { + let workspace = workspaces[index]; + workspace = { ...workspace, containers: [...workspace.containers, container] }; + workspaces[index] = workspace; + if (state.workspace?.name === workspace.name) { + return { ...state, workspaces, workspace }; + } else { + return { ...state, workspaces }; + } + } + + return state; + } catch (error) { + return { ...state, error }; + } +} + +function removeContainer(state: ProjectState, name: string, container: AASContainer): ProjectState { + try { + const workspaces = [...state.workspaces]; + const i = workspaces.findIndex(item => item.name === name); + const j = workspaces[i].containers.findIndex(item => item.url === container.url); + let workspace = workspaces[i]; + workspace = { ...workspace, containers: workspace.containers.filter((_, index) => index !== j) }; + workspaces[i] = workspace; + + if (state.workspace?.name === name) { + const documents = state.documents.filter(item => item.container != container.url); + return { ...state, workspaces, workspace, documents }; + } else { + return { ...state, workspaces }; + } + } catch (error) { + return { ...state, error }; + } +} + +function setWorkspace(state: ProjectState, workspace: AASWorkspace | null): ProjectState { + try { + return { ...state, workspace, documents: [] } + } catch (error) { + return { ...state, error }; + } +} + +function setError(state: ProjectState, error: Error): ProjectState { + return { ...state, error }; +} + diff --git a/projects/aas-portal/src/app/project/project.selectors.ts b/projects/aas-portal/src/app/project/project.selectors.ts new file mode 100644 index 00000000..886ebee6 --- /dev/null +++ b/projects/aas-portal/src/app/project/project.selectors.ts @@ -0,0 +1,64 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from "@ngrx/store"; +import { AASContainer, AASDocument, AASWorkspace, equalUrls, isUrlSafeBase64 } from "common"; +import { State } from "./project.state"; +import { noop } from "rxjs"; +import { decodeBase64Url } from "aas-lib"; + +const getWorkspaces = (state: State) => state.project.workspaces; +const getDocuments = (state: State) => state.project.documents; +const getWorkspace = (state: State) => state.project.workspace; +const getError = (state: State) => state.project.error; +const getProject = (state: State) => state.project; + +export const selectProject = createSelector(getProject, (project) => project); + +export const selectCurrentWorkspace = createSelector(getWorkspace, (workspace) => workspace); + +export const selectWorkspaces = createSelector(getWorkspaces, (workspaces) => workspaces); + +export const selectDocuments = createSelector(getDocuments, (documents) => documents); + +export const selectError = createSelector(getError, (error) => error); + +export const selectContainers = createSelector( + getWorkspaces, + (workspaces: AASWorkspace[]): AASContainer[] => { + const set = new Set(); + return workspaces.flatMap(item => item.containers).filter(container => { + if (!set.has(container.url)) { + set.add(container.url); + return true; + } + + return false; + }); + }); + +export const selectWorkspace = (name: string) => createSelector( + getWorkspaces, + (workspaces: AASWorkspace[]) => workspaces.find(workspace => workspace.name === name)); + +export const selectDocument = (id: string, url?: string) => createSelector( + getDocuments, + (documents: AASDocument[]) => { + let decodedId: string | undefined; + try { + if (isUrlSafeBase64(id)) { + decodedId = decodeBase64Url(id); + } + } catch (err) { + noop(); + } + + return documents.find(item => (item.id === id || item.idShort === id || item.id === decodedId) && + (url == null || equalUrls(item.container, url))); + } +); \ No newline at end of file diff --git a/projects/aas-portal/src/app/project/project.service.ts b/projects/aas-portal/src/app/project/project.service.ts new file mode 100644 index 00000000..9cff7f74 --- /dev/null +++ b/projects/aas-portal/src/app/project/project.service.ts @@ -0,0 +1,246 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { AASDocument, AASContainer, WebSocketData, AASServerMessage, AASWorkspace } from 'common'; +import { Observable, of, mergeMap, catchError, noop } from 'rxjs'; +import { WebSocketSubject } from 'rxjs/webSocket'; +import { Store } from '@ngrx/store'; +import { LogType, NotifyService, WebSocketFactoryService } from 'aas-lib'; + +import { ProjectAPIService } from './project-api.service'; +import { State } from './project.state'; +import * as ProjectSelectors from './project.selectors'; +import * as ProjectActions from './project.actions'; +import { getEndpointName } from '../configuration'; + +@Injectable({ + providedIn: 'root', +}) +export class ProjectService { + private readonly store: Store; + private webSocketSubject?: WebSocketSubject; + + constructor( + store: Store, + private readonly webSocketFactory: WebSocketFactoryService, + private readonly api: ProjectAPIService, + private readonly notify: NotifyService + ) { + this.store = store as Store; + + this.workspaces = this.store.select(ProjectSelectors.selectWorkspaces); + this.workspace = this.store.select(ProjectSelectors.selectCurrentWorkspace); + this.documents = this.store.select(ProjectSelectors.selectDocuments); + this.containers = this.store.select(ProjectSelectors.selectContainers); + this.store.select(ProjectSelectors.selectError).pipe().subscribe(error => this.notify.error(error)); + this.store.dispatch(ProjectActions.initialize()); + this.subscribeWorkspaceChanged(); + } + + /** All available AAS container. */ + public readonly containers: Observable + + /** Gets the available workspaces. */ + public readonly workspaces: Observable; + + /** Gets the current active workspace. */ + public readonly workspace: Observable; + + /** All available AAS documents of the current workspace. */ + public readonly documents: Observable; + + /** + * Sets the current active workspace. + * @param name The name of the new active workspace. + */ + public setWorkspace(name: string): void { + this.store.dispatch(ProjectActions.setActiveWorkspace({ name })); + } + + /** + * Determines whether an AAS with the specified identifier or name (idShort) exists. + * @param id The identifier or name of the AAS document. + * @param url The container URL. + * @returns The observable result. + */ + public findDocument(id: string, url?: string): Observable { + return this.store.select(ProjectSelectors.selectDocument(id, url)).pipe( + mergeMap(document => document ? of(document) : this.api.getDocument(id, url) + .pipe(mergeMap(d => of(d)), + catchError(() => of(undefined))))); + } + + /** + * Gets the AAS document with the specified identification or name. + * @param id The identification or name of the AAS document. + * @param url The container URL. + * @returns The requested AAS document. + */ + public getDocument(id: string, url?: string): Observable { + return this.store.select(ProjectSelectors.selectDocument(id, url)).pipe( + mergeMap(document => { + if (document) { + return of(document); + } + + return this.api.getDocument(id, url).pipe(mergeMap(d => { + if (d.content) { + return of(d); + } + + return this.api.getContent(d.id, d.container).pipe( + mergeMap(content => { + d.content = content; + return of(d); + })); + })); + })); + } + + /** + * Adds an endpoint to the AASServer configuration. + * @param name Name of the endpoint. + * @param url The endpoint URL + */ + public addEndpoint(name: string, url: string): Observable { + return this.api.addEndpoint(name, url); + } + + /** + * Removes the endpoint with the specified name from the AASServer configuration. + * @param name The endpoint name. + */ + public removeEndpoint(name: string): Observable { + return this.api.removeEndpoint(name); + } + + /** + * Resets the AAS-Server configuration to the default. + * @returns An observable. + */ + public reset(): Observable { + return this.api.reset(); + } + + /** + * Applies a modified document. + * @param document The modified document. + */ + public applyDocument(document: AASDocument): void { + this.store.dispatch(ProjectActions.applyDocument({ document })); + } + + /** + * Deletes the specified AAS document form the corresponding AAS container. + * @param document The document to delete. + * @returns An observable. + */ + public deleteDocument(document: AASDocument): Observable { + return this.api.deleteDocument(document.id, document.container); + } + + private subscribeWorkspaceChanged = (): void => { + this.webSocketSubject = this.webSocketFactory.create(); + this.webSocketSubject.subscribe({ + next: (data: WebSocketData): void => { + if (data.type === 'AASServerMessage') { + this.update(data.data as AASServerMessage); + } + }, + error: (): void => { + setTimeout(this.subscribeWorkspaceChanged, 2000); + } + }); + + this.webSocketSubject.next(this.createMessage()); + } + + private createMessage(): WebSocketData { + return { + type: 'WorkspaceChanged', + data: null, + } as WebSocketData; + } + + private update(data: AASServerMessage): void { + try { + switch (data.type) { + case 'Added': + this.documentAdded(data.document!); + break; + case 'Removed': + this.documentRemoved(data.document!); + break; + case 'Changed': + this.documentUpdated(data.document!); + break; + case 'Offline': + this.documentOffline(data.document!); + break; + case 'ContainerAdded': + this.containerAdded(data.endpoint!, data.container!); + break; + case 'ContainerRemoved': + this.containerRemoved(data.endpoint!, data.container!); + break; + case 'EndpointAdded': + this.endpointAdded(data.endpoint!); + break; + case 'EndpointRemoved': + this.endpointRemoved(data.endpoint!); + break; + case 'Reset': + this.store.dispatch(ProjectActions.initialize()); + break; + } + } catch (error) { + this.notify.log(LogType.Error, error); + } + } + + private documentAdded(document: AASDocument): void { + this.store.dispatch(ProjectActions.documentAdded({ document })); + } + + private documentRemoved(document: AASDocument): void { + this.store.dispatch(ProjectActions.removeDocument({ document })); + } + + private documentUpdated(document: AASDocument): void { + this.store.dispatch(ProjectActions.documentUpdated({ document })); + } + + private endpointAdded(endpoint: string): void { + this.store.dispatch(ProjectActions.endpointAdded({ endpoint })); + } + + private endpointRemoved(endpoint: string): void { + this.store.dispatch(ProjectActions.endpointRemoved({ endpoint })); + } + + private documentOffline(document: AASDocument): void { + noop(); + } + + private containerAdded(endpoint: string, container: AASContainer): void { + const url = new URL(endpoint); + const name = getEndpointName(url); + if (name) { + this.store.dispatch(ProjectActions.addContainer({ name, container })); + } + } + + private containerRemoved(endpoint: string, container: AASContainer): void { + const url = new URL(endpoint); + const name = getEndpointName(url); + if (name) { + this.store.dispatch(ProjectActions.removeContainer({ name, container })); + } + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/project/project.state.ts b/projects/aas-portal/src/app/project/project.state.ts new file mode 100644 index 00000000..5aee487b --- /dev/null +++ b/projects/aas-portal/src/app/project/project.state.ts @@ -0,0 +1,27 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, AASWorkspace } from "common"; + +export interface ProjectState { + workspace: AASWorkspace | null; + workspaces: AASWorkspace[]; + documents: AASDocument[]; + error: unknown; +} + +export const initialState: ProjectState = { + workspace: null, + workspaces: [], + documents: [], + error: null +} + +export interface State { + project: ProjectState; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.html b/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.html new file mode 100644 index 00000000..efd9cc70 --- /dev/null +++ b/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.html @@ -0,0 +1,43 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.scss b/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.scss new file mode 100644 index 00000000..a4fac893 --- /dev/null +++ b/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.scss @@ -0,0 +1,15 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +.start-3 { + left: 3%!important; +} + +.start-10 { + left: 10%!important; +} diff --git a/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.ts b/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.ts new file mode 100644 index 00000000..e2cee200 --- /dev/null +++ b/projects/aas-portal/src/app/start/add-endpoint-form/add-endpoint-form.component.ts @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateService } from '@ngx-translate/core'; +import { AASEndpointType, stringFormat } from 'common'; +import { createEndpoint } from 'src/app/configuration'; + +export interface EndpointItem { + name: string; + type: AASEndpointType; + value: string; +} + +@Component({ + selector: 'fhg-add-endpoint', + templateUrl: './add-endpoint-form.component.html', + styleUrls: ['./add-endpoint-form.component.scss'] +}) +export class AddEndpointFormComponent { + constructor( + private modal: NgbActiveModal, + private translate: TranslateService) { + this.items = [ + { + name: this.translate.instant('AASEndpointType.AasxServer'), + type: 'AasxServer', + value: 'http://' + }, + { + name: this.translate.instant('AASEndpointType.AASRegistry'), + type: 'AASRegistry', + value: 'http://' + }, + { + name: this.translate.instant('AASEndpointType.OpcuaServer'), + type: 'OpcuaServer', + value: 'opc.tcp://' + }, + { + name: this.translate.instant('AASEndpointType.AasxDirectory'), + type: 'AasxDirectory', + value: 'file:///' + }, + ]; + + this.item = this.items[0]; + } + + public endpoints: string[] = []; + + public messages: string[] = []; + + public name = ''; + + public readonly items: EndpointItem[]; + + public item: EndpointItem; + + public setItem(value: EndpointItem): void { + this.item = value; + this.clearMessages(); + } + + public inputValue(): void { + this.clearMessages(); + } + + public submit(): void { + this.clearMessages(); + const name = this.validateName(); + const url = this.validateUrl(this.item.value.trim()); + if (name && url) { + const type = this.item.type; + this.modal.close(createEndpoint(url, { name, type })); + } + } + + public cancel(): void { + this.modal.close(); + } + + private clearMessages(): void { + if (this.messages.length > 0) { + this.messages = []; + } + } + + private validateName(): string | undefined { + let name: string | undefined = this.name.trim(); + if (!name) { + this.messages.push(this.createMessage('ERROR_EMPTY_ENDPOINT_NAME')); + name = undefined; + } else { + + for (const workspace of this.endpoints) { + if (workspace.toLocaleLowerCase() === name.toLocaleLowerCase()) { + this.messages.push(this.createMessage('ERROR_ENDPOINT_ALREADY_EXIST', name)); + name = undefined; + break; + } + } + } + + return name; + } + + private validateUrl(value: string): URL | undefined { + try { + const url = new URL(value); + switch (url.protocol) { + case 'opc.tcp:': + if (url.pathname === '//') { + throw new Error('Empty pathname.'); + } + break; + case 'http:': + break; + case 'file:': + if (url.hostname !== '') { + throw new Error(`Invalid host name ${url.hostname}.`); + } + + if (url.pathname === '/') { + throw new Error('Empty pathname.'); + } + break; + } + + return url; + } catch (error) { + this.messages.push(this.createMessage('ERROR_INVALID_URL', this.item.value)); + return undefined; + } + } + + private createMessage(id: string, ...args: any[]): string { + return stringFormat(this.translate.instant(id), args); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.html b/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.html new file mode 100644 index 00000000..af82f770 --- /dev/null +++ b/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.html @@ -0,0 +1,38 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.scss b/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.ts b/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.ts new file mode 100644 index 00000000..57aa045a --- /dev/null +++ b/projects/aas-portal/src/app/start/remove-endpoint-form/remove-endpoint-form.component.ts @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, OnInit } from "@angular/core"; +import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; +import { TranslateService } from "@ngx-translate/core"; + +export interface EndpointSelect { + name: string; + url: string; + selected: boolean; +} + +@Component({ + selector: "fhg-remove-endpoint", + templateUrl: "./remove-endpoint-form.component.html", + styleUrls: ["./remove-endpoint-form.component.scss"], +}) +export class RemoveEndpointFormComponent { + constructor(private modal: NgbActiveModal, private translate: TranslateService) { + } + + public endpoints: EndpointSelect[] = []; + + public messages: string[] = []; + + public inputChange() { + this.clearMessages(); + } + + public submit(): void { + this.clearMessages(); + const result = this.endpoints.filter(item => item.selected).map(item => item.name); + + if (result.length > 0) { + this.modal.close(result); + } else { + this.messages.push(this.translate.instant('ERROR_NO_ELEMENT_SELECTED')); + } + } + + public cancel(): void { + this.modal.close(); + } + + private clearMessages(): void { + if (this.messages.length > 0) { + this.messages = []; + } + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/start.actions.ts b/projects/aas-portal/src/app/start/start.actions.ts new file mode 100644 index 00000000..7ae62b08 --- /dev/null +++ b/projects/aas-portal/src/app/start/start.actions.ts @@ -0,0 +1,28 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from '@ngrx/store'; +import { ViewMode } from 'aas-lib'; + +export enum StartActionType { + SET_VIEW_MODE = '[Start] Set View Mode', + SET_SHOW_ALL = '[Start] Set Show All', + SET_FILTER = '[Start] Set filter', +} + +export const setViewMode = createAction( + StartActionType.SET_VIEW_MODE, + props<{ viewMode: ViewMode }>()); + +export const setShowAll = createAction( + StartActionType.SET_SHOW_ALL, + props<{ showAll: boolean }>()); + +export const setFilter = createAction( + StartActionType.SET_FILTER, + props<{ filter: string }>()); \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/start.component.html b/projects/aas-portal/src/app/start/start.component.html new file mode 100644 index 00000000..016b0ccb --- /dev/null +++ b/projects/aas-portal/src/app/start/start.component.html @@ -0,0 +1,11 @@ + + +
+ +
\ No newline at end of file diff --git a/projects/aas-portal/src/app/start/start.component.scss b/projects/aas-portal/src/app/start/start.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/start/start.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/start/start.component.ts b/projects/aas-portal/src/app/start/start.component.ts new file mode 100644 index 00000000..f9e892e1 --- /dev/null +++ b/projects/aas-portal/src/app/start/start.component.ts @@ -0,0 +1,393 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Router } from '@angular/router'; +import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { Store } from '@ngrx/store'; +import { TranslateService } from '@ngx-translate/core'; +import { aas, AASContainer, AASDocument, AASWorkspace, stringFormat } from 'common'; +import * as lib from 'aas-lib'; +import { BehaviorSubject, first, from, map, mergeMap, noop, Observable, Subscription } from 'rxjs'; +import { ProjectService } from '../project/project.service'; + +import { AddEndpointFormComponent } from './add-endpoint-form/add-endpoint-form.component'; +import { EndpointSelect, RemoveEndpointFormComponent } from './remove-endpoint-form/remove-endpoint-form.component'; +import * as StartActions from './start.actions'; +import { State } from './start.state'; +import { UploadFormComponent } from './upload-form/upload-form.component'; +import { getEndpointType } from 'src/app/configuration'; +import { selectFilter, selectIsViewModeList, selectIsViewModeTree, selectShowAll, selectViewMode } from './start.selectors'; + +@Component({ + selector: 'fhg-start', + templateUrl: './start.component.html', + styleUrls: ['./start.component.scss'], +}) +export class StartComponent implements OnInit, OnDestroy, AfterViewInit { + private readonly store: Store + private readonly subscription = new Subscription(); + private readonly someSelectedDocuments = new BehaviorSubject(true); + private selectedDocuments: AASDocument[] = []; + + constructor( + store: Store, + private readonly router: Router, + private readonly modal: NgbModal, + private readonly translate: TranslateService, + private readonly window: lib.WindowService, + private readonly project: ProjectService, + private readonly notify: lib.NotifyService, + private readonly toolbar: lib.ToolbarService, + private readonly auth: lib.AuthService, + private readonly download: lib.DownloadService, + private readonly clipboard: lib.ClipboardService + ) { + this.store = store as Store; + this.filter = this.store.select(selectFilter); + this.documents = this.project.documents; + } + + @ViewChild('aasTable') + public aasTable: lib.AASTable | null = null; + + public viewMode: lib.ViewMode = lib.ViewMode.List; + + public showAll = false; + + public readonly filter: Observable; + + public documents: Observable; + + public workspaces: AASWorkspace[] = []; + + public workspace: AASWorkspace | null = null; + + public allAvailable = true; + + public ngOnInit(): void { + this.toolbar.setToolbar(this.createToolbar()); + + this.subscription.add( + this.store + .select(selectShowAll).pipe() + .subscribe((value) => { + this.showAll = value; + }) + ); + + this.subscription.add( + this.store + .select(selectViewMode).pipe() + .subscribe((value) => { + this.viewMode = value; + }) + ); + + this.subscription.add( + this.project.workspace.subscribe((value) => { + this.workspace = value; + }) + ); + + this.subscription.add( + this.project.workspaces.subscribe((value) => { + this.workspaces = value; + }) + ); + + this.subscription.add( + this.project.documents.subscribe( + (documents) => (this.allAvailable = documents.every((item) => item.content))) + ); + } + + public ngOnDestroy(): void { + this.toolbar.setToolbar(); + this.subscription.unsubscribe(); + } + + public ngAfterViewInit(): void { + this.subscription.add(this.aasTable?.selectedDocuments.subscribe( + selectedDocuments => { + this.selectedDocuments = selectedDocuments; + this.someSelectedDocuments.next(selectedDocuments.length > 0); + })); + } + + public setViewMode(viewMode: string | lib.ViewMode): void { + this.store.dispatch(StartActions.setViewMode({ viewMode: viewMode as lib.ViewMode })); + } + + public setShowAll(showAll: boolean): void { + this.store.dispatch(StartActions.setShowAll({ showAll })); + } + + public async addEndpoint(): Promise { + try { + await this.auth.ensureAuthorizedAsync('editor'); + const modalRef = this.modal.open(AddEndpointFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.workspaces = this.workspaces.map(item => item.name); + const result: string = await modalRef.result; + if (result) { + const url = new URL(result); + this.project + .addEndpoint(url.searchParams.get('name')!, result) + .pipe(first()) + .subscribe({ + error: (error) => this.notify.error(error), + }); + } + } catch (error) { + this.notify.error(error); + } + } + + public async removeEndpoint(): Promise { + if (this.workspaces.length > 0) { + try { + await this.auth.ensureAuthorizedAsync('editor'); + const modalRef = this.modal.open(RemoveEndpointFormComponent, { backdrop: 'static' }); + modalRef.componentInstance.endpoints = [...this.workspaces] + .sort((a, b) => a.name.localeCompare(b.name)) + .map(item => ({ + name: item.name, + url: item.containers.map((c, i) => i === 0 ? c.url.split('?')[0] : `${i + 1}`).join(', '), + selected: false + } as EndpointSelect)); + + const results: string[] = await modalRef.result; + if (results) { + from(results).pipe(mergeMap(result => this.project.removeEndpoint(result))).subscribe({ + error: (error) => this.notify.error(error), + }); + } + } catch (error) { + if (error) { + this.notify.error(error); + } + } + } + } + + public async reset(): Promise { + try { + await this.auth.ensureAuthorizedAsync('editor'); + if (this.window.confirm(this.translate.instant('CONFIRM_RESET_CONFIGURATION'))) { + this.project.reset().subscribe({ + error: (error) => this.notify.error(error), + }); + } + } catch (error) { + noop(); + } + } + + public setWorkspace(name: string): void { + this.project.setWorkspace(name); + } + + public canUploadDocument(): boolean { + return this.getUploadCapableEndpoints().length > 0; + } + + public async uploadDocument(): Promise { + try { + await this.auth.ensureAuthorizedAsync('editor'); + const modalRef = this.modal.open(UploadFormComponent, { backdrop: 'static' }); + const containers = this.getUploadCapableEndpoints(); + modalRef.componentInstance.containers = containers; + modalRef.componentInstance.container = containers[0]; + const name = await modalRef.result; + if (typeof name === 'string') { + this.notify.info('INFO_UPLOAD_AASX_FILE_SUCCESS', name); + } + } catch (error) { + this.notify.error(error); + } + } + + public canDownloadDocument(): boolean { + return this.aasTable && this.selectedDocuments.length > 0 ? true : false; + } + + public async downloadDocument(): Promise { + if (this.aasTable) { + for (const document of this.selectedDocuments) { + try { + await this.download.downloadDocumentAsync( + document.idShort + '.aasx', + document.id, + document.container); + } catch (error) { + this.notify.error(error); + } + } + } + } + + public canDeleteDocument(): boolean { + return this.aasTable != null && this.selectedDocuments.length > 0 && + this.selectedDocuments.every( + item => getEndpointType(item.container) === 'AasxDirectory'); + } + + public async deleteDocument(): Promise { + try { + await this.auth.ensureAuthorizedAsync('editor'); + if (this.aasTable) { + if (this.window.confirm(stringFormat( + this.translate.instant('CONFIRM_DELETE_DOCUMENT'), + this.selectedDocuments.map(item => item.idShort).join(', ')))) { + from(this.selectedDocuments).pipe(mergeMap(document => this.project.deleteDocument(document))) + .subscribe({ + error: (error) => this.notify.error(error) + }); + } + } + } catch (error) { + this.notify.error(error); + } + } + + public canViewUserFeedback(): boolean { + return this.selectedDocuments.some(document => this.selectSubmodels(document, lib.CustomerFeedback).length === 1); + } + + public viewUserFeedback(): void { + const descriptor: lib.SubmodelViewDescriptor = { + template: lib.supportedSubmodelTemplates.get(lib.CustomerFeedback), + submodels: [] + }; + + for (const document of this.selectedDocuments) { + const submodels = this.selectSubmodels(document, lib.CustomerFeedback); + if (submodels.length === 1) { + descriptor.submodels.push({ + id: document.id, + url: document.container, + idShort: submodels[0].idShort + }); + } + } + + if (descriptor.submodels.length > 0) { + this.clipboard.set('ViewQuery', { descriptor } as lib.ViewQuery) + this.router.navigateByUrl('/view?format=ViewQuery'); + } + } + + public canViewNameplate(): boolean { + return this.selectedDocuments.some(document => this.selectSubmodels(document, lib.ZVEINameplate).length === 1); + } + + public viewNameplate(): void { + const descriptor: lib.SubmodelViewDescriptor = { + template: lib.supportedSubmodelTemplates.get(lib.ZVEINameplate), + submodels: [] + }; + + for (const document of this.selectedDocuments) { + const submodels = this.selectSubmodels(document, lib.ZVEINameplate); + if (submodels.length === 1) { + descriptor.submodels.push({ + id: document.id, + url: document.container, + idShort: submodels[0].idShort + }); + } + } + + if (descriptor.submodels.length > 0) { + this.clipboard.set('ViewQuery', { descriptor } as lib.ViewQuery) + this.router.navigateByUrl('/view?format=ViewQuery'); + } + } + + private selectSubmodels(document: AASDocument, semanticId: string): aas.Submodel[] { + return document.content?.submodels.filter(submodel => lib.resolveSemanticId(submodel) === semanticId) ?? []; + } + + private getUploadCapableEndpoints(): AASContainer[] { + return this.workspace?.containers.filter(item => { + const type = getEndpointType(item.url); + return type === 'AasxDirectory' || type === 'AasxServer'; + }) ?? []; + } + + private createToolbar(): lib.Toolbar { + return { + groups: [ + this.toolbar.createGroup( + [ + this.toolbar.createDropDown( + 'bi bi-stack-overflow', + this.createMenu(), + this.project.workspace.pipe(map(item => item?.name ?? '-')) + ), + this.toolbar.createDropDown( + 'bi bi-gear', + [ + this.toolbar.createMenuItem('CMD_ADD_ENDPOINT', () => this.addEndpoint()), + this.toolbar.createMenuItem('CMD_REMOVE_ENDPOINT', () => this.removeEndpoint()), + this.toolbar.createMenuItem('CMD_RESET_CONFIGURATION', () => this.reset()), + ]) + ]), + this.toolbar.createGroup( + [ + this.toolbar.createButton('bi bi-upload', () => this.uploadDocument(), () => this.canUploadDocument()), + this.toolbar.createButton('bi bi-download', () => this.downloadDocument(), () => this.canDownloadDocument()), + this.toolbar.createButton('bi bi-trash', () => this.deleteDocument(), () => this.canDeleteDocument()) + ] + ), + this.toolbar.createGroup( + [ + this.toolbar.createRadio( + 'bi bi-list', + 'list', + this.store.select(selectIsViewModeList), + () => this.setViewMode('list')), + this.toolbar.createRadio( + 'bi bi-diagram-3', + 'tree', + this.store.select(selectIsViewModeTree), + () => this.setViewMode('tree')) + ]), + this.toolbar.createGroup( + [ + this.toolbar.createDropDown( + '', + [ + this.toolbar.createMenuItem( + 'CMD_VIEW_USER_FEEDBACK', + () => this.viewUserFeedback(), + () => this.canViewUserFeedback()), + this.toolbar.createMenuItem( + 'CMD_VIEW_NAMEPLATE', + () => this.viewNameplate(), + () => this.canViewNameplate()) + ], + 'LABEL_VIEWS', + this.someSelectedDocuments.asObservable()) + ]), + this.toolbar.createGroup( + [ + this.toolbar.createTextInput( + 'bi bi-filter', + this.store.select(selectFilter).pipe(first()), + 'PLACEHOLDER_FILTER', + (filter: string) => this.store.dispatch(StartActions.setFilter({ filter }))) + ])] + } as lib.Toolbar; + } + + private createMenu(): Observable { + return this.project.workspaces.pipe(map(items => items.map( + item => this.toolbar.createMenuItem(item.name, () => this.setWorkspace(item.name))))); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/start.reducer.ts b/projects/aas-portal/src/app/start/start.reducer.ts new file mode 100644 index 00000000..07e8721c --- /dev/null +++ b/projects/aas-portal/src/app/start/start.reducer.ts @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from '@ngrx/store'; +import { ViewMode } from 'aas-lib'; +import * as StartActions from './start.actions'; +import { StartState } from './start.state'; + +const initialState: StartState = { + viewMode: ViewMode.List, + reverse: false, + column: null, + filter: '', + showAll: false +}; + +export const startReducer = createReducer( + initialState, + on( + StartActions.setFilter, + (state, { filter }) => setFilter(state, filter) + ), + on( + StartActions.setShowAll, + (state, { showAll }) => setShowAll(state, showAll) + ), + on( + StartActions.setViewMode, + (state, { viewMode }) => setViewMode(state, viewMode) + ) +) + +function setViewMode(state: StartState, viewMode: ViewMode): StartState { + return { ...state, viewMode }; +} + +function setShowAll(state: StartState, showAll: boolean): StartState { + return { ...state, showAll }; +} + +function setFilter(state: StartState, filter: string): StartState { + return { ...state, filter }; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/start.selectors.ts b/projects/aas-portal/src/app/start/start.selectors.ts new file mode 100644 index 00000000..cee6442e --- /dev/null +++ b/projects/aas-portal/src/app/start/start.selectors.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from '@ngrx/store'; +import { State } from './start.state' +import { ViewMode } from 'aas-lib'; + + +const getShowAll = (state: State) => state.start.showAll; +const getFilter = (state: State) => state.start.filter; +const getViewMode = (state: State) => state.start.viewMode; + +export const selectShowAll = createSelector(getShowAll, showAll => showAll); + +export const selectFilter = createSelector(getFilter, filter => filter); + +export const selectViewMode = createSelector(getViewMode, viewMode => viewMode); + +export const selectIsViewModeList = createSelector(getViewMode, viewMode => viewMode === ViewMode.List); + +export const selectIsViewModeTree = createSelector(getViewMode, viewMode => viewMode === ViewMode.Tree); \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/start.state.ts b/projects/aas-portal/src/app/start/start.state.ts new file mode 100644 index 00000000..8fcf0280 --- /dev/null +++ b/projects/aas-portal/src/app/start/start.state.ts @@ -0,0 +1,21 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ViewMode } from 'aas-lib'; + +export interface StartState { + viewMode: ViewMode; + reverse: boolean; + column: string | null; + filter: string; + showAll: boolean; +} + +export interface State { + start: StartState; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/upload-form/upload-form.component.html b/projects/aas-portal/src/app/start/upload-form/upload-form.component.html new file mode 100644 index 00000000..fa7fe15c --- /dev/null +++ b/projects/aas-portal/src/app/start/upload-form/upload-form.component.html @@ -0,0 +1,37 @@ + + +
+ + + +
\ No newline at end of file diff --git a/projects/aas-portal/src/app/start/upload-form/upload-form.component.scss b/projects/aas-portal/src/app/start/upload-form/upload-form.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/start/upload-form/upload-form.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/start/upload-form/upload-form.component.ts b/projects/aas-portal/src/app/start/upload-form/upload-form.component.ts new file mode 100644 index 00000000..fc705054 --- /dev/null +++ b/projects/aas-portal/src/app/start/upload-form/upload-form.component.ts @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpEvent, HttpEventType } from '@angular/common/http'; +import { Component, ElementRef, ViewChild } from '@angular/core'; +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; +import { DownloadService } from 'aas-lib'; +import { AASContainer } from 'common'; + +@Component({ + selector: 'fhg-upload-form', + templateUrl: './upload-form.component.html', + styleUrls: ['./upload-form.component.scss'] +}) +export class UploadFormComponent { + private uploading = false; + + constructor( + private readonly modal: NgbActiveModal, + private readonly download: DownloadService) { } + + @ViewChild('fileInput') + public fileInput: ElementRef | null = null; + + public files: string | string[] | null = null; + + public container: AASContainer | null = null; + + public containers: AASContainer[] = []; + + public progress = 0; + + public canSubmit(): boolean { + return this.fileInput?.nativeElement?.files != null && + this.fileInput.nativeElement.files.length > 0 && + this.container != null; + } + + public submit(): void { + if (!this.uploading && this.container?.url) { + this.uploading = true; + const file = this.fileInput!.nativeElement!.files![0]; + this.download.uploadDocuments(this.container.url, [file]) + .subscribe({ + next: (event: HttpEvent) => { + switch (event.type) { + case HttpEventType.Sent: + break; + case HttpEventType.ResponseHeader: + break; + case HttpEventType.UploadProgress: + this.progress = Math.round(event.loaded / event.total! * 100); + break; + case HttpEventType.Response: + break; + } + }, + complete: () => this.modal.close(file.name), + error: (error) => this.modal.dismiss(error) + }); + } + } + + public cancel(): void { + if (!this.uploading) { + this.modal.close(); + } + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/start/workspace-select.ts b/projects/aas-portal/src/app/start/workspace-select.ts new file mode 100644 index 00000000..ae57165a --- /dev/null +++ b/projects/aas-portal/src/app/start/workspace-select.ts @@ -0,0 +1,13 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASWorkspace } from "common"; + +export interface WorkspaceSelect extends AASWorkspace { + selected: boolean; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/action-base.ts b/projects/aas-portal/src/app/types/action-base.ts new file mode 100644 index 00000000..3166213b --- /dev/null +++ b/projects/aas-portal/src/app/types/action-base.ts @@ -0,0 +1,21 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Action } from "@ngrx/store"; + +export abstract class ActionBase implements Action { + constructor(type: string) { + this.type = type; + } + + /** The action type. */ + public readonly type: string; + + /** The error when the action fails. */ + public error: any = null; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/command.ts b/projects/aas-portal/src/app/types/command.ts new file mode 100644 index 00000000..11fa45d1 --- /dev/null +++ b/projects/aas-portal/src/app/types/command.ts @@ -0,0 +1,96 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, isIdentifiable } from "common"; + +enum CommandState { + Idle, + Executed, + Aborted +} + +/** Abstract base implementation of a command. */ +export abstract class Command { + private state: CommandState = CommandState.Idle; + + /** + * @param name The command name. + */ + constructor(public readonly name: string) { + } + + public execute(): void { + if (this.state !== CommandState.Idle) { + throw new Error("Invalid command state."); + } + + this.onExecute(); + this.state = CommandState.Executed; + } + + public undo(): void { + if (this.state !== CommandState.Executed) { + throw new Error("Invalid command state."); + } + + this.onUndo(); + } + + public redo(): void { + if (this.state !== CommandState.Executed) { + throw new Error("Invalid command state."); + } + + this.onRedo(); + } + + public abort() { + if (this.state !== CommandState.Idle) { + throw new Error("Invalid command state."); + } + + this.onAbort(); + } + + protected abstract onExecute(): void; + + protected abstract onUndo(): void; + + protected abstract onRedo(): void; + + protected abstract onAbort(): void; + + protected createReference(referable: aas.Referable): aas.Reference { + let reference: aas.Reference | undefined; + if (isIdentifiable(referable)) { + reference = { + type: 'ModelReference', + keys: [{ + value: referable.id, + type: referable.modelType as aas.KeyTypes, + }] + }; + } else if (referable.parent) { + reference = { + type: 'ModelReference', + keys: [ + ...referable.parent.keys.map(key => ({ ...key })), + { + type: referable.modelType as aas.KeyTypes, + value: referable.idShort, + }] + }; + } + + if (!reference) { + throw new Error(`${referable.idShort} is not referable.`); + } + + return reference; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/dashboard-query-params.ts b/projects/aas-portal/src/app/types/dashboard-query-params.ts new file mode 100644 index 00000000..435c22c0 --- /dev/null +++ b/projects/aas-portal/src/app/types/dashboard-query-params.ts @@ -0,0 +1,15 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface DashboardQueryParams { + format: string, +} + +export interface DashboardQuery { + page: string; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/doc-ref.ts b/projects/aas-portal/src/app/types/doc-ref.ts new file mode 100644 index 00000000..04229a03 --- /dev/null +++ b/projects/aas-portal/src/app/types/doc-ref.ts @@ -0,0 +1,14 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export interface DocRef { + /** The name of the AAS document. */ + id: string; + /** The URL of the container that contains the AAS document. */ + url: string; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/errors.ts b/projects/aas-portal/src/app/types/errors.ts new file mode 100644 index 00000000..21d2b06c --- /dev/null +++ b/projects/aas-portal/src/app/types/errors.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export const ERRORS = { + WORKSPACE_NAME_ALREADY_EXISTS: 'ERROR_WORKSPACE_NAME_ALREADY_EXISTS', + INVALID_OPERATION_VARIABLE_EXPRESSION: 'ERROR_INVALID_OPERATION_VARIABLE_EXPRESSION', + UNKNOWN_VARIABLE_VALUE_TYPE: 'ERROR_UNKNOWN_VARIABLE_VALUE_TYPE', + EMAIL_REQUIRED: 'ERROR_EMAIL_REQUIRED', + INVALID_EMAIL: 'ERROR_INVALID_EMAIL', + PASSWORD_REQUIRED: 'ERROR_PASSWORD_REQUIRED', + INVALID_PASSWORD: 'ERROR_INVALID_PASSWORD', + PASSWORDS_NOT_EQUAL: 'ERROR_PASSWORDS_NOT_EQUAL', + DASHBOARD_PAGE_ALREADY_EXISTS: 'ERROR_DASHBOARD_PAGE_ALREADY_EXISTS', + UNAUTHORIZED_ACCESS: 'ERROR_UNAUTHORIZED_ACCESS', +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/info.ts b/projects/aas-portal/src/app/types/info.ts new file mode 100644 index 00000000..e0a980b0 --- /dev/null +++ b/projects/aas-portal/src/app/types/info.ts @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export const INFO = { + NEW_PASSWORD_SENT: 'INFO_NEW_PASSWORD_SENT' +}; \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/intl.d.ts b/projects/aas-portal/src/app/types/intl.d.ts new file mode 100644 index 00000000..00269ea4 --- /dev/null +++ b/projects/aas-portal/src/app/types/intl.d.ts @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +declare namespace Intl { + function getCanonicalLocales(locales: string | string[]): string[]; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/types/selection-mode.ts b/projects/aas-portal/src/app/types/selection-mode.ts new file mode 100644 index 00000000..7f24c692 --- /dev/null +++ b/projects/aas-portal/src/app/types/selection-mode.ts @@ -0,0 +1,12 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export enum SelectionMode { + Single = 'Single', + Multiple = 'Multiple' +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/view/view.actions.ts b/projects/aas-portal/src/app/view/view.actions.ts new file mode 100644 index 00000000..7d8ad056 --- /dev/null +++ b/projects/aas-portal/src/app/view/view.actions.ts @@ -0,0 +1,28 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createAction, props } from "@ngrx/store"; +import { TypedAction } from '@ngrx/store/src/models'; +import { DocumentSubmodelPair, SubmodelViewDescriptor } from 'aas-lib' + +export enum ViewActionType { + SET_SUBMODELS = '[Submodel] set submodels', + INIT_VIEW = '[Submodel] init view' +} + +export const setSubmodels = createAction( + ViewActionType.SET_SUBMODELS, + props<{ descriptor: SubmodelViewDescriptor }>()); + +export const initView = createAction( + ViewActionType.INIT_VIEW, + props<{ submodels: DocumentSubmodelPair[]; template?: string }>()); + +export interface SetSubmodelsAction extends TypedAction { + descriptor: SubmodelViewDescriptor; +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/view/view.component.html b/projects/aas-portal/src/app/view/view.component.html new file mode 100644 index 00000000..b05f2a92 --- /dev/null +++ b/projects/aas-portal/src/app/view/view.component.html @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/projects/aas-portal/src/app/view/view.component.scss b/projects/aas-portal/src/app/view/view.component.scss new file mode 100644 index 00000000..c57d4b61 --- /dev/null +++ b/projects/aas-portal/src/app/view/view.component.scss @@ -0,0 +1,7 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ diff --git a/projects/aas-portal/src/app/view/view.component.ts b/projects/aas-portal/src/app/view/view.component.ts new file mode 100644 index 00000000..8c58155d --- /dev/null +++ b/projects/aas-portal/src/app/view/view.component.ts @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Component, OnDestroy, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { Store } from '@ngrx/store'; +import { EMPTY, from, mergeMap, of, Subscription, toArray, zip } from 'rxjs'; +import * as lib from 'aas-lib'; + +import { State } from './view.state'; +import * as ViewActions from './view.actions'; +import * as ViewSelectors from './view.selectors'; +import { ProjectService } from '../project/project.service'; + +@Component({ + selector: 'fhg-view', + templateUrl: './view.component.html', + styleUrls: ['./view.component.scss'] +}) +export class ViewComponent implements OnInit, OnDestroy { + private readonly store: Store; + private readonly subscription = new Subscription(); + + constructor( + store: Store, + private readonly route: ActivatedRoute, + private readonly project: ProjectService, + private readonly clipboard: lib.ClipboardService + ) { + this.store = store as Store; + this.subscription.add(this.store.select(ViewSelectors.selectSubmodels) + .pipe().subscribe(submodels => { + this.submodels = submodels; + })); + + this.subscription.add(this.store.select(ViewSelectors.selectTemplate) + .pipe().subscribe(template => { + this.template = template; + })); + } + + public template?: string; + + public submodels: lib.DocumentSubmodelPair[] = []; + + public ngOnInit(): void { + let query: lib.ViewQuery | undefined; + const params = this.route.snapshot.queryParams as lib.ViewQueryParams; + if (params.format) { + query = this.clipboard.get(params.format); + } + + if (query?.descriptor) { + const descriptor: lib.SubmodelViewDescriptor = query.descriptor; + zip(of(descriptor.template), from(descriptor.submodels).pipe( + mergeMap(item => zip(this.project.getDocument(item.id, item.url), of(item.idShort))), + mergeMap(tuple => { + const submodel = tuple[0].content?.submodels.find(item => item.idShort === tuple[1]); + if (submodel?.modelType === 'Submodel') { + return of({ document: tuple[0], submodel } as lib.DocumentSubmodelPair); + } + + return EMPTY; + }), + toArray() + )).subscribe(tuple => this.store.dispatch( + ViewActions.initView({ submodels: tuple[1], template: tuple[0] }))); + } + } + + public ngOnDestroy(): void { + this.subscription.unsubscribe(); + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/view/view.effects.ts b/projects/aas-portal/src/app/view/view.effects.ts new file mode 100644 index 00000000..b2c28412 --- /dev/null +++ b/projects/aas-portal/src/app/view/view.effects.ts @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Injectable } from '@angular/core'; +import { Actions, createEffect, ofType } from '@ngrx/effects'; +import { exhaustMap, mergeMap, from, zip, of, EMPTY, toArray, map } from 'rxjs'; +import { DocumentSubmodelPair } from 'aas-lib'; +import * as ViewActions from './view.actions'; +import { ProjectService } from '../project/project.service'; + +/** Currently not used. Does not work with ProjectService */ +@Injectable() +export class ViewEffects { + constructor( + private readonly actions: Actions, + private readonly project: ProjectService + ) { } + + public setSubmodels = createEffect(() => { + return this.actions.pipe( + ofType(ViewActions.ViewActionType.SET_SUBMODELS), + exhaustMap(action => from(action.descriptor.submodels)), + mergeMap(item => { + return zip(this.project.getDocument(item.id, item.url), of(item.idShort)) + }), + mergeMap(tuple => { + const submodel = tuple[0].content?.submodels.find(item => item.idShort === tuple[1]); + if (submodel?.modelType === 'Submodel') { + return of({ document: tuple[0], submodel } as DocumentSubmodelPair); + } + + return EMPTY; + }), + toArray(), + map(submodels => ViewActions.initView({ submodels }))); + }); +} \ No newline at end of file diff --git a/projects/aas-portal/src/app/view/view.reducer.ts b/projects/aas-portal/src/app/view/view.reducer.ts new file mode 100644 index 00000000..9f4d2d6c --- /dev/null +++ b/projects/aas-portal/src/app/view/view.reducer.ts @@ -0,0 +1,28 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createReducer, on } from "@ngrx/store"; +import { DocumentSubmodelPair } from 'aas-lib'; +import * as ViewActions from "./view.actions"; +import { ViewState } from "./view.state"; + +const initialState: ViewState = { + submodels: [] +}; + +export const viewReducer = createReducer( + initialState, + on( + ViewActions.initView, + (state, { submodels, template }) => initView(state, submodels, template) + ) +); + +function initView(state: ViewState, submodels: DocumentSubmodelPair[], template: string | undefined): ViewState { + return { ...state, submodels, template }; +} diff --git a/projects/aas-portal/src/app/view/view.selectors.ts b/projects/aas-portal/src/app/view/view.selectors.ts new file mode 100644 index 00000000..30a1eac4 --- /dev/null +++ b/projects/aas-portal/src/app/view/view.selectors.ts @@ -0,0 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createSelector } from '@ngrx/store'; +import { State } from './view.state'; + +const getSubmodels = (state: State) => state.view.submodels; +const getTemplate = (state: State) => state.view.template; + +export const selectSubmodels = createSelector(getSubmodels, submodels => submodels); + +export const selectTemplate = createSelector(getTemplate, template => template); \ No newline at end of file diff --git a/projects/aas-portal/src/app/view/view.state.ts b/projects/aas-portal/src/app/view/view.state.ts new file mode 100644 index 00000000..3bca9fdb --- /dev/null +++ b/projects/aas-portal/src/app/view/view.state.ts @@ -0,0 +1,18 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { DocumentSubmodelPair } from 'aas-lib'; + +export interface ViewState { + template?: string; + submodels: DocumentSubmodelPair[]; +} + +export interface State { + view: ViewState; +} diff --git a/projects/aas-portal/src/assets/.gitkeep b/projects/aas-portal/src/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/projects/aas-portal/src/assets/fhg-logo.svg b/projects/aas-portal/src/assets/fhg-logo.svg new file mode 100644 index 00000000..9acd53b0 --- /dev/null +++ b/projects/aas-portal/src/assets/fhg-logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/projects/aas-portal/src/assets/i18n/de-de.json b/projects/aas-portal/src/assets/i18n/de-de.json new file mode 100644 index 00000000..2b512d18 --- /dev/null +++ b/projects/aas-portal/src/assets/i18n/de-de.json @@ -0,0 +1,180 @@ +{ + "CAPTION_START": "Start", + "CAPTION_VIEW": "Sicht", + "CAPTION_AAS": "VWS", + "CAPTION_ABOUT": "Über", + "CAPTION_LOGIN": "Anmeldung", + "CAPTION_PROFILE": "Profil", + "CAPTION_REGISTRATION": "Registrierung", + "CAPTION_PASSWORD_FORGOTTEN": "Passwort vergessen?", + "CAPTION_DASHBOARD": "Dashboard", + "CAPTION_INPUT_ARGUMENTS": "Eingangsargumente", + "CAPTION_OUTPUT_ARGUMENTS": "Ausgangsargumente", + "CAPTION_CREATE_WORKSPACE": "Gruppieren", + "CAPTION_EDIT_WORKSPACE": "Gruppe bearbeiten", + "CAPTION_REMOVE_WORKSPACE": "Gruppe löschen", + "CAPTION_ADD_ENDPOINT": "AAS-Endpunkt hinzufügen", + "CAPTION_REMOVE_ENDPOINT": "AAS-Endpunkt entfernen", + "CAPTION_NEW_ELEMENT": "Neu hinzufügen", + "CAPTION_EDIT_ELEMENT": "Bearbeiten", + "CAPTION_ERROR": "Fehler", + "CAPTION_INFO": "Info", + "CAPTION_WARNING": "Warnung", + "CAPTION_UPLOAD_FILE": "AASX-Datei hochladen", + "CMD_OK": "OK", + "CMD_OPEN_AAS": "VWS öffnen", + "CMD_UPLOAD": "Hochladen", + "CMD_DOWNLOAD": "Herunterladen", + "CMD_REMOVE": "Entfernen", + "CMD_DELETE": "Löschen", + "CMD_CANCEL": "Abbrechen", + "CMD_LOGIN": "Anmelden", + "CMD_LOGOUT": "Abmelden", + "CMD_CALL": "Anruf", + "CMD_CLOSE": "Schließen", + "CMD_SELECT_ALL": "Alle selektieren", + "CMD_DESELECT_ALL": "Alle deselektieren", + "CMD_CHANGE_PASSWORD": "Passwort ändern", + "CMD_REGISTER_USER": "Registrieren", + "CMD_UPDATE_PROFILE": "Profil", + "CMD_RESET_PASSWORD": "Passwort vergessen?", + "CMD_OPERATION_CALL": "Aufrufen", + "CMD_ADD_ENDPOINT": "Hinzufügen...", + "CMD_CREATE_WORKSPACE": "Gruppieren...", + "CMD_EDIT_WORKSPACE": "Gruppe bearbeiten...", + "CMD_REMOVE_WORKSPACE": "Gruppierung aufheben...", + "CMD_REMOVE_ENDPOINT": "Entfernen...", + "CMD_RESET_CONFIGURATION": "Zurücksetzen...", + "CMD_TOGGLE_MESSAGES": "Meldungen", + "CMD_TOGGLE_PACKAGES": "Packages", + "CMD_DELETE_USER": "Benutzerkonto löschen...", + "CMD_VIEW_USER_FEEDBACK": "Nutzer-Feedback", + "CMD_VIEW_NAMEPLATE": "Typenschild", + "COLUMN_VARIANT": "Variante", + "COLUMN_NAME": "Name", + "COLUMN_MODEL_TYPE": "Modeltyp", + "COLUMN_SIZE": "Größe", + "COLUMN_MODIFIED": "Änderungsdatum", + "COLUMN_ID": "ID", + "COLUMN_URL": "URL", + "COLUMN_VALUE": "Wert", + "COLUMN_DATA_TYPE": "Datentyp", + "COLUMN_DESCRIPTION": "Beschreibung", + "COLUMN_MESSAGE_TYPE": "Typ", + "COLUMN_TIMESTAMP": "Zeit", + "COLUMN_MESSAGE_TEXT": "Meldung", + "COLUMN_PACKAGE": "Package", + "COLUMN_VERSION": "Version", + "COLUMN_LICENSE": "Lizenz", + "LABEL_NAME": "Name", + "LABEL_AAS_ID": "Id:", + "LABEL_ASSET_ID": "Asset ID:", + "LABEL_EMAIL": "E-Mail", + "LABEL_STAY_LOGGED_IN": "Angemeldet bleiben", + "LABEL_PASSWORD": "Passwort", + "LABEL_CONFIRM_PASSWORD": "Passwort bestätigen", + "LABEL_FILE": "Datei:", + "LABEL_AAS_ID_SHORT": "ID-Short:", + "LABEL_ASSET_ID_SHORT": "Asset ID-Short:", + "LABEL_VERSION": "Version:", + "LABEL_ENDPOINT": "Endpunkt:", + "LABEL_DEFINITION": "Definition:", + "LABEL_DESCRIPTION": "Beschreibung:", + "LABEL_SELECT_WORKSPACE": "Gruppe", + "LABEL_SELECT_REGISTRY": "AAS-Registry", + "LABEL_SHOW_ALL": "Alle anzeigen", + "LABEL_REGISTRY_NAME": "Name", + "LABEL_REGISTRY_URL": "URL", + "LABEL_VIEW_MODE": "Anzeige:", + "LABEL_INFO": "Info", + "LABEL_WARNING": "Warnungen", + "LABEL_ERROR": "Fehler", + "LABEL_MODEL_TYPE": "Modelltyp:", + "LABEL_MODEL_TYPE_TEMPLATE": "Vorlage:", + "LABEL_INSERT_POSITION": "Position:", + "LABEL_VALUE": "Wert:", + "LABEL_VALUE_TYPE": "Wertetyp", + "LABEL_AAS_URL": "AAS Endpunkt", + "LABEL_SERVER_URL": "Server Endpunkt", + "LABEL_CHART_TYPE": "Diagrammtyp", + "LABEL_COLOR": "Farbe", + "LABEL_UPLOAD_CONTAINER": "Ziel", + "LABEL_OVERWRITE_FILE": "Überschreiben", + "LABEL_MIN": "Min", + "LABEL_MAX": "Max", + "LABEL_MIME_TYPE": "MIME-Typ", + "LABEL_VIEWS": "Sichten", + "LABEL_CATEGORY": "Kategorie", + "LABEL_SEMANTIC_ID": "Semantik ID", + "PLEASE_WAIT": "Bitte warten...", + "PLACEHOLDER_EMAIL": "E-Mail-Adresse eingeben", + "PLACEHOLDER_PASSWORD": "Passwort eingeben", + "PLACEHOLDER_NEW_PASSWORD": "Neues Passwort eingeben", + "PLACEHOLDER_REPEAT_PASSWORD": "Passwort bestätigen", + "PLACEHOLDER_USERNAME": "Namen eingeben", + "PLACEHOLDER_ENDPOINT_URL": "URL eingeben", + "PLACEHOLDER_ENDPOINT_NAME": "Name eingeben", + "PLACEHOLDER_FILTER": "Filter", + "PLACEHOLDER_WORKSPACE": "Gruppenname", + "PLACEHOLDER_SEARCH": "Suche", + "GUEST_USER": "Gast", + "ERROR_UNCAUGHT": "{0}", + "ERROR_UNKNOWN_USER": "Der Benutzer {0} ist unbekannt.", + "ERROR_UPLOAD_FAILED": "Das Hochladen und öffnen der Datei {0} ist fehlgeschlagen. {1}", + "ERROR_INVALID_CREDENTIALS": "Ungültige Zugangsdaten.", + "ERROR_UNAUTHORIZED_ACCESS": "Nicht autorisierter Zugriff.", + "ERROR_INVALID_PASSWORD": "Das Passwort genügt nicht den geforderten Richtlinien. Es muss mindestens acht Zeichen lang sein und darf keine führenden und nachfolgenden Leerzeichen enthalten.", + "ERROR_PASSWORD_REQUIRED": "Passwort erforderlich.", + "ERROR_INVALID_EMAIL": "'{0}' ist keine gültige E-Mail.", + "ERROR_EMAIL_REQUIRED": "E-Mail erforderlich.", + "ERROR_USER_ALREADY_EXISTS": "Zu dieser E-Mail existiert bereits ein Konto.", + "ERROR_AAS_NOT_FOUND": "Eine Verwaltungsschale mit der Kennung '{0}' existiert nicht.", + "ERROR_PASSWORD_EXPIRED": "Das Password ist abgelaufen.", + "ERROR_INVALID_AASX_PACKAGE": "'{0}' ist ein ungültiges AASX Package.", + "ERROR_MAX_POSITIONS_EXCEEDED": "Es können maximal {0} Artikel bestellt werden.", + "ERROR_MAX_QUANTITY_EXCEEDED": "Die Stückzahl eines Artikels ist auf {0} begrenzt.", + "ERROR_PASSWORDS_NOT_EQUAL": "Die Passwörter sind nicht gleich.", + "ERROR_INVALID_OPERATION_VARIABLE_EXPRESSION": "Der Ausdruck '{0}' für die Variable '{1}' kann nicht in den Typ '{2}' konvertiert werden.", + "ERROR_UNKNOWN_VARIABLE_VALUE_TYPE": "Der Datentyp der Variable '{0}' ist unbestimmt.'", + "ERROR_DASHBOARD_PAGE_ALREADY_EXISTS": "Ein Dashboard mit dem Namen '{0}' existiert bereits.", + "ERROR_INVALID_URL": "'{0}' ist eine ungültige URL.", + "ERROR_ENDPOINT_ALREADY_EXIST": "Ein AAS-Endpunkt mit dem Namen '{0}' existiert bereits.", + "ERROR_EMPTY_ENDPOINT_NAME": "Geben Sie einen eindeutigen Namen für den AAS-Endpunkt ein.", + "ERROR_NO_ELEMENT_SELECTED": "Mindestens ein Element muss ausgewählt sein.", + "ERROR_INVALID_CONTAINER_URL": "'{0}' adressiert eine ungülig oder nicht unterstützte VWS-Ressoure.", + "INFO_NEW_PASSWORD_SENT": "Ein neues Passwort wurde an '{0}' gesendet", + "INFO_DOWNLOAD_FILE_SUCCESS": "{0} wurde erfolgreich heruntergeladen.", + "INFO_UPLOAD_AASX_FILE_SUCCESS": "{0} wurde erfolgreich hochgeladen.", + "CONFIRM_DELETE_FILE": "{0} unwiderruflich löschen?", + "CONFIRM_DELETE_FILES": "{0} Dateien unwiderruflich löschen?", + "CONFIRM_RESET_CONFIGURATION": "Möchten Sie die AASServer Standardkonfiguration wiederherstellen?", + "CONFIRM_DELETE_USER": "Möchten Sie das Konto '{0}' löschen?", + "CONFIRM_DELETE_DOCUMENT": "Möchten Sie wirklich die Dokumente {0} löschen?", + "PROMPT_DASHBOARD_NAME": "Geben Sie einen Namen für das Dashboard ein.", + "TIP_PASSWORD_SEND_VIA_EMAIL": "An '{{email}}' wird ein neues Password gesendet.", + "VALUE_ORDER": "{0} vom {1}", + "ROUTE_FILE_SYSTEM": "Dateisystem", + "ROUTE_OPC_UA": "OPC UA", + "ALERT_SUCCESS": "Erfolg!", + "ALERT_FAILED": "Fehlgeschlagen!", + "OPTION_TIMELINE_CHART": "Zeitdiagramm", + "OPTION_BAR_VERTICAL_CHART": "Balkendiagramm vertikal", + "OPTION_BAR_HORIZONTAL_CHART": "Balkendiagramm horizontal", + "AASEndpointType": { + "AasxDirectory": "Verzeichnis", + "AasxServer": "AASX-Server", + "AASRegistry": "AAS-Registry", + "OpcuaServer": "OPC-UA-Server" + }, + "CustomerFeedback": { + "OverallRating": "Gesamtbewertung", + "Form": "Gestallt", + "Looks": "Optik", + "Interaction": "Funktionalität", + "Structure": "Struktur", + "Haptics": "Haptik", + "Acustics": "Akustik", + "Assembly_Installation": "Montage & Installation", + "Material": "Material" + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/assets/i18n/en-us.json b/projects/aas-portal/src/assets/i18n/en-us.json new file mode 100644 index 00000000..d8ceed33 --- /dev/null +++ b/projects/aas-portal/src/assets/i18n/en-us.json @@ -0,0 +1,180 @@ +{ + "CAPTION_START": "Start", + "CAPTION_VIEW": "View", + "CAPTION_AAS": "AAS", + "CAPTION_ABOUT": "About", + "CAPTION_LOGIN": "Login", + "CAPTION_PROFILE": "Profile", + "CAPTION_REGISTRATION": "Registration", + "CAPTION_PASSWORD_FORGOTTEN": "Password forgotten?", + "CAPTION_DASHBOARD": "Dashboard", + "CAPTION_INPUT_ARGUMENTS": "Input Arguments", + "CAPTION_OUTPUT_ARGUMENTS": "Output Arguments", + "CAPTION_CREATE_WORKSPACE": "Group", + "CAPTION_EDIT_WORKSPACE": "Edit Group", + "CAPTION_REMOVE_WORKSPACE": "Remove Group", + "CAPTION_ADD_ENDPOINT": "Add AAS Endpoint", + "CAPTION_REMOVE_ENDPOINT": "Remove AAS Endpoint", + "CAPTION_NEW_ELEMENT": "Insert New", + "CAPTION_EDIT_ELEMENT": "Edit", + "CAPTION_ERROR": "Error", + "CAPTION_INFO": "Info", + "CAPTION_WARNING": "Warning", + "CAPTION_UPLOAD_FILE": "Upload AASX File", + "CMD_OK": "OK", + "CMD_OPEN_AAS": "Open AAS", + "CMD_UPLOAD": "Upload", + "CMD_DOWNLOAD": "Download", + "CMD_REMOVE": "Remove", + "CMD_DELETE": "Delete", + "CMD_CANCEL": "Cancel", + "CMD_LOGIN": "Login", + "CMD_LOGOUT": "Logout", + "CMD_CLOSE": "Close", + "CMD_SELECT_ALL": "Select All", + "CMD_DESELECT_ALL": "Deselect ALL", + "CMD_CHANGE_PASSWORD": "Change password", + "CMD_REGISTER_USER": "Register", + "CMD_UPDATE_PROFILE": "Profile", + "CMD_CALL": "Call", + "CMD_RESET_PASSWORD": "Password forgotten?", + "CMD_OPERATION_CALL": "Call", + "CMD_CREATE_WORKSPACE": "Group...", + "CMD_EDIT_WORKSPACE": "Edit group...", + "CMD_REMOVE_WORKSPACE": "Ungroup...", + "CMD_ADD_ENDPOINT": "Add...", + "CMD_REMOVE_ENDPOINT": "Remove...", + "CMD_RESET_CONFIGURATION": "Reset...", + "CMD_TOGGLE_MESSAGES": "Messages", + "CMD_TOGGLE_PACKAGES": "Packages", + "CMD_DELETE_USER": "Delete user account...", + "CMD_VIEW_USER_FEEDBACK": "User feedback", + "CMD_VIEW_NAMEPLATE": "Nameplate", + "COLUMN_NAME": "Name", + "COLUMN_MODEL_TYPE": "Model type", + "COLUMN_SIZE": "Size", + "COLUMN_MODIFIED": "Date of modification", + "COLUMN_ID": "ID", + "COLUMN_URL": "URL", + "COLUMN_VALUE": "Value", + "COLUMN_DATA_TYPE": "DataType", + "COLUMN_DESCRIPTION": "Description", + "COLUMN_MESSAGE_TYPE": "Type", + "COLUMN_TIMESTAMP": "Time", + "COLUMN_MESSAGE_TEXT": "Message", + "COLUMN_PACKAGE": "Package", + "COLUMN_VERSION": "Version", + "COLUMN_LICENSE": "License", + "FILE_PATH": "File URL", + "LABEL_NAME": "Name", + "LABEL_AAS_ID": "ID:", + "LABEL_ASSET_ID": "Asset ID:", + "LABEL_STAY_LOGGED_IN": "Stay logged in", + "LABEL_EMAIL": "E-Mail", + "LABEL_PASSWORD": "Password", + "LABEL_CONFIRM_PASSWORD": "Confirm password", + "LABEL_FILE": "File:", + "LABEL_AAS_ID_SHORT": "ID short:", + "LABEL_ASSET_ID_SHORT": "Asset ID short:", + "LABEL_VERSION": "Version:", + "LABEL_ENDPOINT": "Endpoint:", + "LABEL_DEFINITION": "Definition:", + "LABEL_DESCRIPTION": "Description:", + "LABEL_SELECT_WORKSPACE": "Group", + "LABEL_SELECT_REGISTRY": "AAS registry", + "LABEL_SHOW_ALL": "Show all", + "LABEL_REGISTRY_NAME": "Name", + "LABEL_REGISTRY_URL": "URL", + "LABEL_VIEW_MODE": "View:", + "LABEL_INFO": "Info", + "LABEL_WARNING": "Warnings", + "LABEL_ERROR": "Errors", + "LABEL_MODEL_TYPE": "Model type:", + "LABEL_MODEL_TYPE_TEMPLATE": "Template:", + "LABEL_INSERT_POSITION": "Position:", + "LABEL_VALUE_TYPE": "Value type", + "LABEL_VALUE": "Value", + "LABEL_AAS_URL": "AAS endpoint", + "LABEL_SERVER_URL": "Server endpoint", + "LABEL_CHART_TYPE": "Chart type", + "LABEL_COLOR": "Color", + "LABEL_UPLOAD_CONTAINER": "Destination", + "LABEL_OVERWRITE_FILE": "Overwrite", + "LABEL_MIN": "Min", + "LABEL_MAX": "Max", + "LABEL_MIME_TYPE": "MIME type", + "LABEL_VIEWS": "Views", + "LABEL_CATEGORY": "Category", + "LABEL_SEMANTIC_ID": "Semantic ID", + "PLEASE_WAIT": "Please wait...", + "PLACEHOLDER_EMAIL": "enter email address", + "PLACEHOLDER_PASSWORD": "enter password", + "PLACEHOLDER_NEW_PASSWORD": "enter new password", + "PLACEHOLDER_CONFIRM_PASSWORD": "confirm password", + "PLACEHOLDER_USERNAME": "enter a name", + "PLACEHOLDER_ENDPOINT_URL": "enter an URL", + "PLACEHOLDER_ENDPOINT_NAME": "enter a name", + "PLACEHOLDER_FILTER": "Filter", + "PLACEHOLDER_WORKSPACE": "group name", + "PLACEHOLDER_SEARCH": "Search", + "GUEST_USER": "Guest", + "ERROR_UNCAUGHT": "{0}", + "ERROR_UNKNOWN_USER": "The user {0} is unknown.", + "ERROR_UPLOAD_FAILED": "Uploading and opening the file {0} failed. {1}", + "ERROR_INVALID_CREDENTIALS": "Invalid credentials.", + "ERROR_UNAUTHORIZED_ACCESS": "Unauthorized access.", + "ERROR_INVALID_PASSWORD": "The password does not meet the required guidelines. It must be at least eight characters long and may not contain leading and trailing spaces.", + "ERROR_PASSWORD_REQUIRED": "Password required.", + "ERROR_INVALID_EMAIL": "'{0}' is not a valid e-mail.", + "ERROR_EMAIL_REQUIRED": "E-mail is required.", + "ERROR_USER_ALREADY_EXISTS": "An account to this e-mail already exists.", + "ERROR_AAS_NOT_FOUND": "An asset administration shell with the identification '{0}' does not exist.", + "ERROR_PASSWORD_EXPIRED": "The password is expired.", + "ERROR_INVALID_AASX_PACKAGE": "'{0}' is an invalid AASX package.", + "ERROR_MAX_POSITIONS_EXCEEDED": "A maximum of {0} article can be ordered.", + "ERROR_MAX_QUANTITY_EXCEEDED": "The number of pieces of an article is limited to {0}.", + "ERROR_PASSWORDS_NOT_EQUAL": "The passwords are not equal.", + "ERROR_INVALID_OPERATION_VARIABLE_EXPRESSION": "The expression '{0}' for the variable '{1}' cannot be converted to the type '{2}'.", + "ERROR_UNKNOWN_VARIABLE_VALUE_TYPE": "The data type of the variable '{0}' is undefined.", + "ERROR_DASHBOARD_PAGE_ALREADY_EXISTS": "A dashboard with the name '{0}' already exists.", + "ERROR_INVALID_URL": "'{0}' is an invalid URL.", + "ERROR_ENDPOINT_ALREADY_EXIST": "An AAS endpoint with the name '{0}' already exists.", + "ERROR_EMPTY_ENDPOINT_NAME": "Enter a unique AAS endpoint name.", + "ERROR_NO_ELEMENT_SELECTED": "At least one element must be selected.", + "ERROR_INVALID_CONTAINER_URL": "'{0}' addresses an invalid or not supported AAS resource.", + "INFO_NEW_PASSWORD_SENT": "A new password was sent to '{0}'.", + "INFO_DOWNLOAD_FILE_SUCCESS": "{0} was downloaded successfully.", + "INFO_UPLOAD_AASX_FILE_SUCCESS": "{0} was uploaded successfully.", + "CONFIRM_DELETE_FILE": "Permanently delete {0}?", + "CONFIRM_DELETE_FILES": "Permanently delete {0} files?", + "CONFIRM_RESET_CONFIGURATION": "Do you want to restore the default AASServer configuration?", + "CONFIRM_DELETE_USER": "Do you want to delete the account '{0}'?", + "CONFIRM_DELETE_DOCUMENT": "Do you really want to delete documents {0}?", + "PROMPT_DASHBOARD_NAME": "Enter a name for the dashboard.", + "TIP_PASSWORD_SEND_VIA_EMAIL": "A new password is sent to '{{email}}'.", + "VALUE_ORDER": "{0} from {1}", + "ROUTE_FILE_SYSTEM": "File system", + "ROUTE_OPC_UA": "OPC UA", + "ALERT_SUCCESS": "Success!", + "ALERT_FAILED": "Failed!", + "OPTION_TIMELINE_CHART": "Timeline chart", + "OPTION_BAR_VERTICAL_CHART": "Vertical bar chart", + "OPTION_BAR_HORIZONTAL_CHART": "Horizontal bar chart", + "AASEndpointType": { + "AasxDirectory": "Directory", + "AasxServer": "AASX Server", + "AASRegistry": "AAS Registry", + "OpcuaServer": "OPC UA Server" + }, + "CustomerFeedback": { + "OverallRating": "Overall rating", + "Form": "Form", + "Looks": "Looks", + "Interaction": "Interaction", + "Structure": "Structure", + "Haptics": "Haptics", + "Acustics": "Acustics", + "Assembly_Installation": "Assembly & Installation", + "Material": "Material" + } +} diff --git a/projects/aas-portal/src/assets/i40-spec-logo.png b/projects/aas-portal/src/assets/i40-spec-logo.png new file mode 100644 index 00000000..8711b3cb Binary files /dev/null and b/projects/aas-portal/src/assets/i40-spec-logo.png differ diff --git a/projects/aas-portal/src/assets/resources/aas-idta.png b/projects/aas-portal/src/assets/resources/aas-idta.png new file mode 100644 index 00000000..7835ceb1 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aas-idta.png differ diff --git a/projects/aas-portal/src/assets/resources/aas.16.png b/projects/aas-portal/src/assets/resources/aas.16.png new file mode 100644 index 00000000..fd586577 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aas.16.png differ diff --git a/projects/aas-portal/src/assets/resources/aas.32.png b/projects/aas-portal/src/assets/resources/aas.32.png new file mode 100644 index 00000000..5c0cb19c Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aas.32.png differ diff --git a/projects/aas-portal/src/assets/resources/aas.48.png b/projects/aas-portal/src/assets/resources/aas.48.png new file mode 100644 index 00000000..3a266b60 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aas.48.png differ diff --git a/projects/aas-portal/src/assets/resources/aas.64.png b/projects/aas-portal/src/assets/resources/aas.64.png new file mode 100644 index 00000000..5ea9a610 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aas.64.png differ diff --git a/projects/aas-portal/src/assets/resources/aas.svg b/projects/aas-portal/src/assets/resources/aas.svg new file mode 100644 index 00000000..ef0d201b --- /dev/null +++ b/projects/aas-portal/src/assets/resources/aas.svg @@ -0,0 +1 @@ +PORTAL IOAASAASAAS \ No newline at end of file diff --git a/projects/aas-portal/src/assets/resources/aasx-bckgrnd.256.png b/projects/aas-portal/src/assets/resources/aasx-bckgrnd.256.png new file mode 100644 index 00000000..0b940e4d Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx-bckgrnd.256.png differ diff --git a/projects/aas-portal/src/assets/resources/aasx.16.png b/projects/aas-portal/src/assets/resources/aasx.16.png new file mode 100644 index 00000000..9312500f Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx.16.png differ diff --git a/projects/aas-portal/src/assets/resources/aasx.24.png b/projects/aas-portal/src/assets/resources/aasx.24.png new file mode 100644 index 00000000..791a08e5 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx.24.png differ diff --git a/projects/aas-portal/src/assets/resources/aasx.256.png b/projects/aas-portal/src/assets/resources/aasx.256.png new file mode 100644 index 00000000..ae109a8d Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx.256.png differ diff --git a/projects/aas-portal/src/assets/resources/aasx.32.png b/projects/aas-portal/src/assets/resources/aasx.32.png new file mode 100644 index 00000000..2d9408f4 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx.32.png differ diff --git a/projects/aas-portal/src/assets/resources/aasx.48.png b/projects/aas-portal/src/assets/resources/aasx.48.png new file mode 100644 index 00000000..02f3cf58 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx.48.png differ diff --git a/projects/aas-portal/src/assets/resources/aasx.64.png b/projects/aas-portal/src/assets/resources/aasx.64.png new file mode 100644 index 00000000..a6d6f258 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/aasx.64.png differ diff --git a/projects/aas-portal/src/assets/resources/fhg.svg b/projects/aas-portal/src/assets/resources/fhg.svg new file mode 100644 index 00000000..20b7ecf5 --- /dev/null +++ b/projects/aas-portal/src/assets/resources/fhg.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/aas-portal/src/assets/resources/fhg_logo.32.png b/projects/aas-portal/src/assets/resources/fhg_logo.32.png new file mode 100644 index 00000000..7f982b68 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/fhg_logo.32.png differ diff --git a/projects/aas-portal/src/assets/resources/flag-de-de.png b/projects/aas-portal/src/assets/resources/flag-de-de.png new file mode 100644 index 00000000..0940dddf Binary files /dev/null and b/projects/aas-portal/src/assets/resources/flag-de-de.png differ diff --git a/projects/aas-portal/src/assets/resources/flag-en-us.png b/projects/aas-portal/src/assets/resources/flag-en-us.png new file mode 100644 index 00000000..ff39a31b Binary files /dev/null and b/projects/aas-portal/src/assets/resources/flag-en-us.png differ diff --git a/projects/aas-portal/src/assets/resources/folder.24.png b/projects/aas-portal/src/assets/resources/folder.24.png new file mode 100644 index 00000000..f3a2a835 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/folder.24.png differ diff --git a/projects/aas-portal/src/assets/resources/folder.32.png b/projects/aas-portal/src/assets/resources/folder.32.png new file mode 100644 index 00000000..cc7d8432 Binary files /dev/null and b/projects/aas-portal/src/assets/resources/folder.32.png differ diff --git a/projects/aas-portal/src/assets/resources/folder.png b/projects/aas-portal/src/assets/resources/folder.png new file mode 100644 index 00000000..ab04cc0c Binary files /dev/null and b/projects/aas-portal/src/assets/resources/folder.png differ diff --git a/projects/aas-portal/src/assets/resources/opcua.256.png b/projects/aas-portal/src/assets/resources/opcua.256.png new file mode 100644 index 00000000..bcbf49ac Binary files /dev/null and b/projects/aas-portal/src/assets/resources/opcua.256.png differ diff --git a/projects/aas-portal/src/assets/resources/opcua.32.png b/projects/aas-portal/src/assets/resources/opcua.32.png new file mode 100644 index 00000000..d514b33a Binary files /dev/null and b/projects/aas-portal/src/assets/resources/opcua.32.png differ diff --git a/projects/aas-portal/src/assets/resources/opcua.64.png b/projects/aas-portal/src/assets/resources/opcua.64.png new file mode 100644 index 00000000..58370c8f Binary files /dev/null and b/projects/aas-portal/src/assets/resources/opcua.64.png differ diff --git a/projects/aas-portal/src/assets/resources/question.svg b/projects/aas-portal/src/assets/resources/question.svg new file mode 100644 index 00000000..7c43f8d2 --- /dev/null +++ b/projects/aas-portal/src/assets/resources/question.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/projects/aas-portal/src/environments/environment.prod.ts b/projects/aas-portal/src/environments/environment.prod.ts new file mode 100644 index 00000000..2a5a28ae --- /dev/null +++ b/projects/aas-portal/src/environments/environment.prod.ts @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export const environment = { + production: true +}; \ No newline at end of file diff --git a/projects/aas-portal/src/environments/environment.ts b/projects/aas-portal/src/environments/environment.ts new file mode 100644 index 00000000..9840ee6f --- /dev/null +++ b/projects/aas-portal/src/environments/environment.ts @@ -0,0 +1,24 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false +}; + +/* + * For easier debugging in development mode, you can import the following file + * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. + * + * This import should be commented out in production mode because it will have a negative impact + * on performance if an error is thrown. + */ +// import 'zone.js/plugins/zone-error'; // Included with Angular CLI. \ No newline at end of file diff --git a/projects/aas-portal/src/favicon.ico b/projects/aas-portal/src/favicon.ico new file mode 100644 index 00000000..949bf4ca Binary files /dev/null and b/projects/aas-portal/src/favicon.ico differ diff --git a/projects/aas-portal/src/index.html b/projects/aas-portal/src/index.html new file mode 100644 index 00000000..7d707196 --- /dev/null +++ b/projects/aas-portal/src/index.html @@ -0,0 +1,24 @@ + + + + + + + + AASPortal + + + + + + + + + + \ No newline at end of file diff --git a/projects/aas-portal/src/main.ts b/projects/aas-portal/src/main.ts new file mode 100644 index 00000000..ba1146b2 --- /dev/null +++ b/projects/aas-portal/src/main.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); \ No newline at end of file diff --git a/projects/aas-portal/src/styles.scss b/projects/aas-portal/src/styles.scss new file mode 100644 index 00000000..f793de9f --- /dev/null +++ b/projects/aas-portal/src/styles.scss @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2022 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +@import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css"); + +:root { + --fhg-green: #009374; + --fhg-blue: #1f82c0; + --fhg-abc: #33B8CA; + --fhg-def: #B1C800; + --fhg-ghi: #6DBFA9; + --fhg-klm: #B4CA3C; + --fhg-nop: #1D9B83; + --fhg-qrs: #5D5299; + --fhg-tuv: #F7C727; + --fhg-xyz: #E78E26; + --fhg-123: #8B3F4B; + --fhg-456: #5EB0BE; + --fhg-red: #C52523; +} + +$primary: #009374; +$info: #1f82c0; + +th[sortable] { + cursor: pointer; + user-select: none; + -webkit-user-select: none; +} + +th[sortable].asc:before { + content: ''; + display: block; + background: url('data:image/svg+xml;utf8,') center center no-repeat; + background-size: 16px; + width: 22px; + height: 22px; + float: left; + margin-left: 0px; +} + +th[sortable].desc:before { + content: ''; + display: block; + background: url('data:image/svg+xml;utf8,') center center no-repeat; + background-size: 16px; + width: 22px; + height: 22px; + float: left; + margin-left: 0px; +} + +.ts-small { + font-size: small; +} + +.ts-smaller { + font-size: smaller; +} + +.ts-x-small { + font-size: x-small; +} + +.ts-xx-small { + font-size: xx-small; +} + +/* Importing Bootstrap SCSS file. */ +@import 'bootstrap/scss/bootstrap'; diff --git a/projects/aas-portal/src/test/aas/aas.component.spec.ts b/projects/aas-portal/src/test/aas/aas.component.spec.ts new file mode 100644 index 00000000..f82c0055 --- /dev/null +++ b/projects/aas-portal/src/test/aas/aas.component.spec.ts @@ -0,0 +1,183 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { AASDocument, aas } from 'common'; +import { Observable, noop, of } from 'rxjs'; +import { AASTree, DownloadService, NotifyService, OnlineState } from 'aas-lib'; +import { CommonModule } from '@angular/common'; + +import { AASComponent } from '../../app/aas/aas.component'; +import { aasReducer } from 'src/app/aas/aas.reducer'; +import { rotationSpeed, sampleDocument, torque } from 'src/test/assets/sample-document'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { DashboardService } from 'src/app/dashboard/dashboard.service'; +import { DashboardChartType, DashboardPage } from 'src/app/dashboard/dashboard.state'; +import { Router } from '@angular/router'; +import { AppRoutingModule } from 'src/app/app-routing.module'; +import { AASState } from 'src/app/aas/aas.state'; +import * as AASActions from 'src/app/aas/aas.actions'; +import { ProjectService } from 'src/app/project/project.service'; +import { Component, Input } from '@angular/core'; + +class TestProjectService implements Partial { + constructor(private document: AASDocument) { } + + public getDocument(): Observable { + return of(this.document); + } +} + +class TestDashboardService implements Partial { + public pages: Observable = of([]); + public name: Observable = of('Dashboard 1'); + public add(): void { + noop(); + } +} + +@Component({ + selector: 'fhg-aas-tree', + template: '
', + styleUrls: [] +}) +class TestAASTreeComponent implements AASTree { + @Input() + public state: OnlineState = 'offline'; + @Input() + public document: AASDocument | null = null; + @Input() + public search: Observable | null = null; + + public selectedElements: Observable = of([torque, rotationSpeed]); + + public findNext(): void { + noop(); + } + + public findPrevious(): void { + noop(); + } +} + +@Component({ + selector: 'fhg-img', + template: '
', + styleUrls: [] +}) +class TestSecureImageComponent { + @Input() + public src = ''; + @Input() + public alt?:string; + @Input() + public classname?: string; + @Input() + public width = -1; + @Input() + public height = -1; +} + +describe('AASComponent', () => { + let component: AASComponent; + let fixture: ComponentFixture; + let store: Store<{ aas: AASState }>; + let dashboard: DashboardService; + let router: Router; + let download: DownloadService; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + AASComponent, + TestAASTreeComponent, + TestSecureImageComponent + ], + providers: [ + { + provide: ProjectService, + useValue: new TestProjectService(sampleDocument) + }, + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error']) + }, + { + provide: DashboardService, + useValue: new TestDashboardService() + } + ], + imports: [ + CommonModule, + AppRoutingModule, + HttpClientTestingModule, + NgbModule, + StoreModule.forRoot( + { + aas: aasReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(AASComponent); + component = fixture.componentInstance; + store = TestBed.inject(Store); + dashboard = TestBed.inject(DashboardService); + router = TestBed.inject(Router); + download = TestBed.inject(DownloadService); + store.dispatch(AASActions.setDocument({ document: sampleDocument })); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('shows a document overview', function () { + const aas = sampleDocument.content!.assetAdministrationShells[0]; + const assetId = aas.assetInformation.globalAssetId ?? '-'; + + expect(component.endpoint).toEqual(sampleDocument.endpoint!.address); + expect(component.idShort).toEqual(sampleDocument.idShort); + expect(component.id).toEqual(sampleDocument.id); + expect(component.version).toEqual('-'); + expect(component.assetId).toEqual(assetId); + }); + + it('indicates that the sample AAS is not online ready', function () { + expect(component.onlineReady).toBeFalse(); + }); + + it('indicates that the sample AAS is editable', function () { + expect(component.readonly).toBeFalse(); + }); + + it('can add the selected properties to the dashboard', async function () { + spyOn(dashboard, 'add'); + spyOn(router, 'navigateByUrl').and.resolveTo(true); + expect(component.canAddToDashboard()).toBeTrue(); + await expectAsync(component.addToDashboard(DashboardChartType.BarVertical)).toBeResolvedTo(true); + expect(dashboard.add).toHaveBeenCalled(); + expect(router.navigateByUrl).toHaveBeenCalled(); + }); + + it('can download an AASX file', async function () { + spyOn(download, 'downloadDocumentAsync').and.returnValue(Promise.resolve()); + expect(component.canDownloadDocument()).toBeTrue(); + await expectAsync(component.downloadDocument()).toBeResolved(); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/aas/command-handler.service.spec.ts b/projects/aas-portal/src/test/aas/command-handler.service.spec.ts new file mode 100644 index 00000000..4eb42e84 --- /dev/null +++ b/projects/aas-portal/src/test/aas/command-handler.service.spec.ts @@ -0,0 +1,126 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { Command } from 'src/app/types/command'; +import { noop } from 'rxjs'; +import { NotifyService } from 'aas-lib'; +import { CommandHandlerService } from 'src/app/aas/command-handler.service'; + +class TestCommand extends Command { + constructor(private spy?: jasmine.Spy, private undoSpy?: jasmine.Spy, private redoSpy?: jasmine.Spy) { + super("TestCommand"); + } + + protected onExecute(): void { + if (this.spy) { + this.spy(); + } + } + + protected onUndo(): void { + if (this.undoSpy) { + this.undoSpy(); + } + } + + protected onRedo(): void { + if (this.redoSpy) { + this.redoSpy(); + } + } + + protected onAbort(): void { + noop(); + } +} + +class FailCommand extends Command { + constructor(private abortSpy: jasmine.Spy) { + super("TestCommand"); + } + + protected onExecute(): void { + throw new Error("Command throws an error."); + } + + protected onUndo(): void { + noop(); + } + + protected onRedo(): void { + noop(); + } + + protected onAbort(): void { + this.abortSpy(); + } +} + +describe('CommandHandlerService', () => { + let service: CommandHandlerService; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [], + providers: [ + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error']) + } + ], + imports: [] + }); + + service = TestBed.inject(CommandHandlerService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('indicates that undo is not possible', function () { + expect(service.canUndo).toBeFalse(); + }); + + it('indicates that redo is not possible', function () { + expect(service.canRedo).toBeFalse(); + }); + + it("can execute a command", function () { + const spy = jasmine.createSpy('execute'); + service.execute(new TestCommand(spy)); + expect(spy).toHaveBeenCalled(); + }); + + it('can undo/redo a command', function () { + const undoSpy = jasmine.createSpy('undo'); + const redoSpy = jasmine.createSpy('redo'); + service.execute(new TestCommand(undefined, undoSpy, redoSpy)); + expect(service.canUndo).toBeTrue(); + service.undo(); + expect(undoSpy).toHaveBeenCalled(); + expect(service.canRedo).toBeTrue(); + service.redo(); + expect(redoSpy).toHaveBeenCalled(); + }); + + it("clears the undo/redo stack", function () { + service.execute(new TestCommand()); + service.execute(new TestCommand()); + service.clear(); + expect(service.canUndo).toBeFalse(); + expect(service.canRedo).toBeFalse(); + }); + + it("aborts a failed command", function () { + const abortSpy = jasmine.createSpy('abort'); + expect(() => service.execute(new FailCommand(abortSpy))).toThrowError(); + expect(abortSpy).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/aas/delete-command.spec.ts b/projects/aas-portal/src/test/aas/delete-command.spec.ts new file mode 100644 index 00000000..da2babfd --- /dev/null +++ b/projects/aas-portal/src/test/aas/delete-command.spec.ts @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from "@angular/core/testing"; +import { Store, StoreModule } from "@ngrx/store"; +import { first } from 'rxjs'; +import { aas, AASDocument, selectElement } from "common"; +import { aasReducer } from "src/app/aas/aas.reducer"; +import { DeleteCommand } from "src/app/aas/commands/delete-command"; +import { sampleDocument } from "src/test/assets/sample-document"; +import { cloneDeep } from "lodash-es"; +import { State } from "src/app/aas/aas.state"; + +describe('DeleteCommand', function () { + let command: DeleteCommand; + let store: Store; + let document: AASDocument; + + beforeEach(function () { + document = cloneDeep(sampleDocument); + + TestBed.configureTestingModule({ + declarations: [], + providers: [ + ], + imports: [ + StoreModule.forRoot( + { + aas: aasReducer + }), + ] + }); + + store = TestBed.inject(Store); + }); + + describe('delete Submodel', function () { + let submodel: aas.Submodel; + + beforeEach(function () { + submodel = selectElement(document!.content!, 'TechnicalData')!; + command = new DeleteCommand(store, document, submodel); + command.execute(); + }); + + it('can be executed', function (done: DoneFn) { + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData'); + expect(element).toBeUndefined(); + const submodels = document?.content?.assetAdministrationShells[0].submodels; + const reference = submodels?.find(r => r.keys[0].value === submodel.id); + expect(reference).toBeUndefined(); + done(); + }); + }); + + it('can be undone/redone', function (done: DoneFn) { + command.undo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData'); + expect(element).toBeDefined(); + const submodels = document?.content?.assetAdministrationShells[0].submodels; + const reference = submodels?.find(r => r.keys[0].value === submodel.id); + expect(reference).toBeDefined(); + }); + + command.redo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData'); + expect(element).toBeUndefined(); + const submodels = document?.content?.assetAdministrationShells[0].submodels; + const reference = submodels?.find(r => r.keys[0].value === submodel.id); + expect(reference).toBeUndefined(); + done(); + }); + }); + }); + + describe('delete Property', function () { + let property: aas.Property; + + beforeEach(function () { + property = selectElement(document.content!, 'TechnicalData', 'MaxRotationSpeed')!; + command = new DeleteCommand(store, document, property); + command.execute(); + }); + + it('can be executed', function (done: DoneFn) { + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData', 'MaxRotationSpeed'); + expect(element).toBeUndefined(); + done(); + }); + }); + + it('can be undone/redone', function (done: DoneFn) { + command.undo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData', 'MaxRotationSpeed'); + expect(element).toBeDefined(); + }); + + command.redo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData', 'MaxRotationSpeed'); + expect(element).toBeUndefined(); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/aas/edit-element-form.component.spec.ts b/projects/aas-portal/src/test/aas/edit-element-form.component.spec.ts new file mode 100644 index 00000000..b4591c7a --- /dev/null +++ b/projects/aas-portal/src/test/aas/edit-element-form.component.spec.ts @@ -0,0 +1,180 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { aas } from 'common'; +import { EditElementFormComponent } from '../../app/aas/edit-element-form/edit-element-form.component'; + +describe('EditElementFormComponent', () => { + let component: EditElementFormComponent; + let fixture: ComponentFixture; + let activeModal: jasmine.SpyObj; + + beforeEach(() => { + activeModal = jasmine.createSpyObj('NgbActiveModal', ['close']); + TestBed.configureTestingModule({ + declarations: [ + EditElementFormComponent + ], + providers: [ + { + provide: NgbActiveModal, + useValue: activeModal + } + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(EditElementFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('Property', function () { + let property: aas.Property; + + beforeEach(function () { + property = { + idShort: 'Text', + modelType: 'Property', + category: 'CONSTANT', + kind: 'Instance', + valueType: 'xs:string' + }; + + component.initialize(property); + fixture.detectChanges(); + }); + + it('allows editing a string Property', function (done: DoneFn) { + activeModal.close.and.callFake(result => { + expect((result as aas.Property).value).toEqual('Hello World!'); + done(); + }); + + const element: HTMLElement = fixture.debugElement.nativeElement; + const inputElement: HTMLInputElement = element.querySelector('#inputValue')!; + + inputElement.value = 'Hello World!'; + inputElement.dispatchEvent(new Event('input')); + fixture.detectChanges(); + + component.value = inputElement.value; + component.submit(); + }); + + it('allows changing the category to PARAMETER', function (done: DoneFn) { + activeModal.close.and.callFake(result => { + expect((result as aas.Property).category).toEqual('PARAMETER'); + done(); + }); + + const element: HTMLElement = fixture.debugElement.nativeElement; + const selectElement: HTMLSelectElement = element.querySelector('#selectCategory')!; + selectElement.options[component.categories.indexOf('PARAMETER')].defaultSelected = true; + selectElement.dispatchEvent(new Event('change')); + fixture.detectChanges(); + + // hack + component.category = selectElement.options[selectElement.selectedIndex].label; + component.submit(); + }); + + it('allows changing the value type to "double"', function (done: DoneFn) { + activeModal.close.and.callFake(result => { + expect((result as aas.Property).valueType).toEqual('xs:double'); + done(); + }); + + const element: HTMLElement = fixture.debugElement.nativeElement; + const selectElement: HTMLSelectElement = element.querySelector('#selectValueType')!; + selectElement.options[component.valueTypes.indexOf('xs:double')].defaultSelected = true; + selectElement.dispatchEvent(new Event('change')); + fixture.detectChanges(); + + // hack + component.valueType = selectElement.options[selectElement.selectedIndex].label as aas.DataTypeDefXsd; + component.submit(); + }); + }); + + describe('MultiLanguageProperty', function () { + let property: aas.MultiLanguageProperty; + + beforeEach(function () { + property = { + idShort: 'A multi language property', + modelType: 'MultiLanguageProperty', + category: 'CONSTANT', + kind: 'Instance', + value: [{ language: 'de', text: 'Hallo Welt!' }] + }; + + component.initialize(property); + fixture.detectChanges(); + }); + + it('allows editing an existing locale text', function (done: DoneFn) { + activeModal.close.and.callFake(result => { + const expected: aas.LangString[] = [{ language: 'de', text: 'Hallo Mond!' }]; + expect((result as aas.MultiLanguageProperty).value).toEqual(expected); + done(); + }); + + component.setText(component.langStrings[0], 'Hallo Mond!'); + component.submit(); + }); + + it('allows removing an existing locale text', function (done: DoneFn) { + activeModal.close.and.callFake(result => { + const expected: aas.LangString[] = []; + expect((result as aas.MultiLanguageProperty).value).toEqual(expected); + done(); + }); + + component.removeLangString(component.langStrings[0]); + component.submit(); + }); + + it('allows adding a new locale text', function (done: DoneFn) { + activeModal.close.and.callFake(result => { + const expected: aas.LangString[] = [ + { language: 'de', text: 'Hallo Welt!' }, + { language: 'en', text: 'Hello World!' }, + ]; + + expect((result as aas.MultiLanguageProperty).value).toEqual(expected); + done(); + }); + + const langString = component.langStrings[component.langStrings.length - 1]; + component.addLangString(); + component.setLanguage(langString, 'en'); + component.setText(langString, 'Hello World!'); + component.submit(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/aas/new-element-command.spec.ts b/projects/aas-portal/src/test/aas/new-element-command.spec.ts new file mode 100644 index 00000000..96978f92 --- /dev/null +++ b/projects/aas-portal/src/test/aas/new-element-command.spec.ts @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { first } from 'rxjs'; +import { aas, AASDocument, selectElement } from 'common'; +import { cloneDeep } from 'lodash-es'; +import { aasReducer } from 'src/app/aas/aas.reducer'; +import { aasNoTechnicalData, submodelTechnicalData } from 'src/test/assets/sample-document'; +import { NewElementCommand } from 'src/app/aas/commands/new-element-command'; +import { AASState } from 'src/app/aas/aas.state'; + +describe('NewElementCommand', function () { + let command: NewElementCommand; + let store: Store<{ aas: AASState }>; + let document: AASDocument; + let submodel: aas.Submodel; + + beforeEach(function () { + document = cloneDeep(aasNoTechnicalData); + submodel = cloneDeep(submodelTechnicalData); + + TestBed.configureTestingModule({ + declarations: [], + providers: [ + ], + imports: [ + StoreModule.forRoot( + { + aas: aasReducer + }), + ] + }); + + store = TestBed.inject(Store); + }); + + beforeEach(function () { + command = new NewElementCommand(store, document, document.content!.assetAdministrationShells[0], submodel); + command.execute(); + }); + + it('can be executed', function (done: DoneFn) { + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData'); + expect(element).toBeDefined(); + done(); + }); + }); + + it('can be undone/redone', function (done: DoneFn) { + command.undo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData'); + expect(element).toBeUndefined(); + }); + + command.redo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const element = selectElement(document!.content!, 'TechnicalData'); + expect(element).toBeDefined(); + done(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/aas/new-element-form.component.spec.ts b/projects/aas-portal/src/test/aas/new-element-form.component.spec.ts new file mode 100644 index 00000000..e4498755 --- /dev/null +++ b/projects/aas-portal/src/test/aas/new-element-form.component.spec.ts @@ -0,0 +1,49 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { NewElementFormComponent } from 'src/app/aas/new-element-form/new-element-form.component'; + +describe('NewElementFormComponent', () => { + let component: NewElementFormComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + NewElementFormComponent + ], + providers: [ + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(NewElementFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/aas/update-element-command.spec.ts b/projects/aas-portal/src/test/aas/update-element-command.spec.ts new file mode 100644 index 00000000..e1ae424f --- /dev/null +++ b/projects/aas-portal/src/test/aas/update-element-command.spec.ts @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { first } from 'rxjs'; +import { aas, AASDocument, selectElement } from 'common'; +import { aasReducer } from 'src/app/aas/aas.reducer'; +import { UpdateElementCommand } from 'src/app/aas/commands/update-element-command'; +import { sampleDocument } from 'src/test/assets/sample-document'; +import { cloneDeep } from 'lodash-es'; +import { State } from 'src/app/aas/aas.state'; + +describe('SetValueCommand', function () { + let command: UpdateElementCommand; + let store: Store; + let document: AASDocument; + let property: aas.Property; + let element: aas.Property; + + beforeEach(function () { + document = cloneDeep(sampleDocument); + property = selectElement(document.content!, 'TechnicalData', 'MaxRotationSpeed')!; + element = cloneDeep(property); + element.value = '42'; + + TestBed.configureTestingModule({ + declarations: [], + providers: [ + ], + imports: [ + StoreModule.forRoot( + { + aas: aasReducer + }), + ] + }); + + store = TestBed.inject(Store); + }); + + beforeEach(function () { + command = new UpdateElementCommand(store, document, property, element); + command.execute(); + }); + + it('can be executed', function (done: DoneFn) { + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const value: aas.Property = selectElement(document!.content!, 'TechnicalData', 'MaxRotationSpeed')!; + expect(value.value).toEqual('42'); + done(); + }); + }); + + it('can be undone/redone', function (done: DoneFn) { + command.undo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const value: aas.Property = selectElement(document!.content!, 'TechnicalData', 'MaxRotationSpeed')!; + expect(value.value).toEqual('5000'); + }); + + command.redo(); + store.select(state => state.aas.document).pipe(first()).subscribe(document => { + const value: aas.Property = selectElement(document!.content!, 'TechnicalData', 'MaxRotationSpeed')!; + expect(value.value).toEqual('42'); + done(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/about/about.component.spec.ts b/projects/aas-portal/src/test/about/about.component.spec.ts new file mode 100644 index 00000000..1135f9a2 --- /dev/null +++ b/projects/aas-portal/src/test/about/about.component.spec.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { CommonModule } from '@angular/common'; +import { AASLibModule } from 'aas-lib'; +import { EffectsModule } from '@ngrx/effects'; +import { StoreModule } from '@ngrx/store'; + +import { AboutComponent } from '../../app/about/about.component'; + +describe('AboutComponent', () => { + let component: AboutComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + AboutComponent + ], + providers: [ + ], + imports: [ + CommonModule, + HttpClientTestingModule, + AASLibModule, + EffectsModule.forRoot(), + StoreModule.forRoot(), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(AboutComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/app/app.component.spec.ts b/projects/aas-portal/src/test/app/app.component.spec.ts new file mode 100644 index 00000000..8ad2bb7e --- /dev/null +++ b/projects/aas-portal/src/test/app/app.component.spec.ts @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { AppComponent } from '../../app/app.component'; +import { Component } from '@angular/core'; + +@Component({ + selector: 'fhg-main', + template: '

', + styleUrls: [] +}) +class TestMainComponent { +} + +describe('AppComponent', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + RouterTestingModule + ], + declarations: [ + TestMainComponent, + AppComponent + ], + }); + }); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'AASPortal'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('AASPortal'); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/assets/environment.json b/projects/aas-portal/src/test/assets/environment.json new file mode 100644 index 00000000..330d62e7 --- /dev/null +++ b/projects/aas-portal/src/test/assets/environment.json @@ -0,0 +1,1636 @@ +{ + "assetAdministrationShells": [ + { + "asset": { + "keys": [ + { + "type": "Asset", + "local": true, + "value": "http://customer.com/assets/KHBVZJSQKIY", + "index": 0, + "idType": "IRI" + } + ] + }, + "submodels": [ + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "index": 0, + "idType": "IRI" + } + ] + } + ], + "conceptDictionaries": [], + "identification": { + "idType": "IRI", + "id": "http://customer.com/aas/9175_7013_7091_9168" + }, + "idShort": "ExampleMotor", + "category": "CONSTANT", + "modelType": { + "name": "AssetAdministrationShell" + } + } + ], + "assets": [ + { + "assetIdentificationModelRef": { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "i40.customer.com/type/1/1/F13E8576F6488342", + "index": 0, + "idType": "IRI" + } + ] + }, + "identification": { + "idType": "IRI", + "id": "http://customer.com/assets/KHBVZJSQKIY" + }, + "idShort": "ServoDCMotor", + "category": "", + "modelType": { + "name": "Asset" + }, + "kind": "Instance" + } + ], + "submodels": [ + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#01-ADN198#009", + "index": 0, + "idType": "IRDI" + } + ] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342" + }, + "idShort": "Identification", + "category": "CONSTANT", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "CUSTOMER GmbH", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAO677#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "Manufacturer", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "10101010", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAY812#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "GLN", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "integer" + } + }, + "kind": "Instance" + }, + { + "value": "I40 Capable Servo Motor (EN)", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAW338#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "ProductDesignation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "langString" + } + }, + "kind": "Instance" + }, + { + "value": "P12345678I40", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAM556#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "SerialNumber", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ] + }, + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#01-AFZ615#016", + "index": 0, + "idType": "IRDI" + } + ] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + }, + "idShort": "TechnicalData", + "category": "CONSTANT", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "5000", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAA120#008", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "MaxRotationSpeed", + "category": "PARAMETER", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "integer" + } + }, + "kind": "Instance" + }, + { + "value": "200", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAE098#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "MaxTorque", + "category": "PARAMETER", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "value": "BAB657", + "valueId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#07-BAB657#003 ", + "index": 0, + "idType": "IRDI" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAE122#006", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "CoolingType", + "category": "PARAMETER", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ] + } + ] + }, + { + "semanticId": { + "keys": [] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + "idShort": "Documentation", + "category": "CONSTANT", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "OperatingManual", + "category": "", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "3 608 870 A47", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "03-02", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentClassId", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Operation (EN) Bedienung (DE)", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentClassName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "langString" + } + }, + "kind": "Instance" + }, + { + "value": "VDI2770:2018", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentClassificationSystem", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "CUSTOMER", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "OrganizationName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "CUSTOMER GmbH", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "OrganizationOfficialName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Operating Manual Servo Motor", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "Title", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "langString" + } + }, + "kind": "Instance" + }, + { + "value": "en-US", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "Language", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "mimeType": "application/pdf", + "value": "/aasx/OperatingManual.pdf", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DigitalFile_PDF", + "category": "PARAMETER", + "modelType": { + "name": "File" + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ] + }, + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#01-AFZ615#016", + "index": 0, + "idType": "IRDI" + } + ] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + }, + "idShort": "OperationalData", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "4370", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "hasDataSpecification": [], + "idShort": "RotationSpeed", + "category": "VARIABLE", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "integer" + } + }, + "kind": "Instance" + }, + { + "value": "117.4", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "hasDataSpecification": [], + "idShort": "Torque", + "category": "VARIABLE", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + } + ] + } + ], + "conceptDescriptions": [ + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + }, + "idShort": "Document", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "unit": "", + "sourceOfDefinition": "[ISO 15519-1:2010]", + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ] + } + } + ], + "descriptions": [] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + }, + "idShort": "DocumentIdValue", + "category": "CONSTANT", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ], + "unit": "", + "sourceOfDefinition": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + }, + "idShort": "DocumentClassId", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + }, + "idShort": "DocumentClassName", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ], + "unit": "", + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + }, + "idShort": "DocumentClassificationSystem", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + }, + "idShort": "OrganizationName", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + }, + "idShort": "OrganizationOfficialName", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ] + } + } + ], + "isCaseOf": [ + { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO677#002", + "index": 0, + "idType": "IRDI" + } + ] + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion" + }, + "idShort": "DocumentVersion", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ], + "unit": "", + "dataType": "", + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + }, + "idShort": "Language", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + }, + "idShort": "Title", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ], + "unit": "", + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate" + }, + "idShort": "Date", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ], + "unit": "", + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val" + }, + "idShort": "DocumentVersionIdValue", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + }, + "idShort": "DigitalFile", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ], + "unit": "", + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#02-BAA120#008" + }, + "administration": { + "version": "", + "revision": "2" + }, + "idShort": "MaxRotationSpeed", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#05-AAA650#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ] + } + } + ], + "isCaseOf": [ + { + "keys": [] + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#02-BAE098#004" + }, + "idShort": "MaxTorque", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#05-AAA212#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895" + }, + "idShort": "RotationSpeed", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#05-AAA650#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896" + }, + "idShort": "Torque", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "keys": [] + }, + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#02-BAE122#006" + }, + "idShort": "CoolingType", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "shortName": [], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#07-BAB657#003" + }, + "idShort": "BAB657", + "category": "VALUE", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "shortName": [], + "unit": "", + "dataType": "STRING", + "definition": [] + } + } + ] + } + ] + } \ No newline at end of file diff --git a/projects/aas-portal/src/test/assets/json-web-token.ts b/projects/aas-portal/src/test/assets/json-web-token.ts new file mode 100644 index 00000000..01c53b8b --- /dev/null +++ b/projects/aas-portal/src/test/assets/json-web-token.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +const guestToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiZ3Vlc3QiLCJpYXQiOjE2OTA4ODgwMjd9.mUnIUXDwWOlE89QmgXjAVryZY_qWPL-ai-i76ClLTH8'; +const johnToken = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBlbWFpbC5jb20iLCJyb2xlIjoiZWRpdG9yIiwibmFtZSI6IkpvaG4ifQ.L-RbuQQdjgFOhiFqGVxXBBjnyUaAXvMeu9PM-fMshN0'; +const johnDoeToken = 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBlbWFpbC5jb20iLCJyb2xlIjoiZWRpdG9yIiwibmFtZSI6IkpvaG4gRG9lIn0.JNBzGftOKu4HY9VzSS5ArWwBrgOc1rHi1ooFcMwcXvw'; + +export function getToken(name: string): string { + switch (name) { + case 'John': + return johnToken; + case 'John Doe': + return johnDoeToken; + default: + throw new Error('Not implemented.'); + } +} + +export function getGuestToken(): string { + return guestToken; +} \ No newline at end of file diff --git a/projects/aas-portal/src/test/assets/sample-document.ts b/projects/aas-portal/src/test/assets/sample-document.ts new file mode 100644 index 00000000..4cfb6593 --- /dev/null +++ b/projects/aas-portal/src/test/assets/sample-document.ts @@ -0,0 +1,3008 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, AASDocument, selectElement } from "common" + +const content: object = { + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassId" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassName" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassificationSystem" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationName" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationOfficialName" + }, + { + "idShort": "Title", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Title" + }, + { + "idShort": "Language", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Language" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/RotationSpeed" + }, + { + "idShort": "Torque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/Torque" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +}; + +const sampleNoTechnicalData: object = { + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassId" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassName" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassificationSystem" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationName" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationOfficialName" + }, + { + "idShort": "Title", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Title" + }, + { + "idShort": "Language", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Language" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/RotationSpeed" + }, + { + "idShort": "Torque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/Torque" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +}; + +const technicalData: object = { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] +}; + +export const sampleDocument: AASDocument = { + "id": "http://customer.com/aas/9175_7013_7091_9168", + "idShort": "ExampleMotor", + "container": "file:///samples?name=Samples&type=AasxDirectory", + "endpoint": { + "type": "file", + "address": "ExampleMotor.aasx" + }, + "timeStamp": 1675961220599, + "modified": false, + "readonly": false, + "onlineReady": false, + "content": content as aas.Environment +}; + +export const aasNoTechnicalData: AASDocument = { + "id": "http://customer.com/aas/9175_7013_7091_9168", + "idShort": "ExampleMotor", + "container": "file:///endpoints/samples?name=Samples&type=AasxDirectory", + "endpoint": { + "type": "file", + "address": "ExampleMotor.aasx" + }, + "timeStamp": 1675961220599, + "modified": false, + "readonly": false, + "onlineReady": false, + "content": sampleNoTechnicalData as aas.Environment +}; + +export const submodelTechnicalData: aas.Submodel = technicalData as aas.Submodel; + +export const rotationSpeed: aas.Property = selectElement(sampleDocument.content!, 'OperationalData', 'RotationSpeed')!; + +export const torque: aas.Property = selectElement(sampleDocument.content!, 'OperationalData', 'Torque')!; + +export const maxRotationSpeed: aas.Property = selectElement(sampleDocument.content!, 'TechnicalData', 'MaxRotationSpeed')!; \ No newline at end of file diff --git a/projects/aas-portal/src/test/assets/test-document.ts b/projects/aas-portal/src/test/assets/test-document.ts new file mode 100644 index 00000000..f62434db --- /dev/null +++ b/projects/aas-portal/src/test/assets/test-document.ts @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, AASContainer, AASWorkspace, aas } from 'common'; + +export function createContainer(url: string, documents: AASDocument[]): AASContainer { + return { + documents: documents, + url: url, + name: url + }; +} + +export function createWorkspace(name: string, containers: AASContainer[]): AASWorkspace { + return { + name: name, + containers: containers, + }; +} + +export function createDocument(name: string, url= "http://localhost/container1"): AASDocument { + const document: AASDocument = { + id: `http://localhost/aas/${name}`, + idShort: name, + container: url, + endpoint: { address: "", type: "file" }, + timeStamp: 0, + modified: false, + readonly: false, + onlineReady: false, + content: { assetAdministrationShells: [], submodels: [], conceptDescriptions: [] }, + }; + + return document; +} + +export function createDocumentHeader(name: string, url: string): AASDocument { + const document: AASDocument = { + id: `http://localhost/aas/${name}`, + idShort: name, + container: url, + endpoint: { address: "", type: "file" }, + timeStamp: 0, + modified: false, + readonly: false, + onlineReady: false, + content: null, + }; + + return document; +} + +export function createContent(): aas.Environment { + return { assetAdministrationShells: [], submodels: [], conceptDescriptions: [] }; +} \ No newline at end of file diff --git a/projects/aas-portal/src/test/assets/test-web-socket-factory.service.ts b/projects/aas-portal/src/test/assets/test-web-socket-factory.service.ts new file mode 100644 index 00000000..fe0a0951 --- /dev/null +++ b/projects/aas-portal/src/test/assets/test-web-socket-factory.service.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { WebSocketFactoryService } from 'aas-lib'; +import { WebSocketData } from 'common'; +import { Subject } from 'rxjs'; +import { WebSocketSubject } from 'rxjs/webSocket'; + +export class TestWebSocketFactoryService implements Partial { + constructor(private readonly subject: Subject) {} + + public create(): WebSocketSubject { + return this.subject as WebSocketSubject; + } +} \ No newline at end of file diff --git a/projects/aas-portal/src/test/dashboard/dashboard-api.service.spec.ts b/projects/aas-portal/src/test/dashboard/dashboard-api.service.spec.ts new file mode 100644 index 00000000..5128e549 --- /dev/null +++ b/projects/aas-portal/src/test/dashboard/dashboard-api.service.spec.ts @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; + +import { DashboardApiService } from '../../app/dashboard/dashboard-api.service'; + +describe('DashboardApiService', () => { + let service: DashboardApiService; + let httpTestingController: HttpTestingController; + + beforeEach(() => { + + TestBed.configureTestingModule({ + providers: [], + imports: [HttpClientTestingModule] + }); + + service = TestBed.inject(DashboardApiService); + httpTestingController = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('GET: ', function () { + const container = encodeBase64Url('http://localhost/container'); + const id = encodeBase64Url('http://localhost/document'); + const smId = encodeBase64Url('http://localhost/submodel'); + const path = 'Blob'; + const url = `/api/v1/containers/${container}/documents/${id}/submodels/${smId}/blobs/${path}/value`; + const value = window.btoa('Hello World!'); + + service.getBlobValue(url).subscribe(value => { + expect(value).toEqual(value); + }); + + const req = httpTestingController.expectOne(url); + expect(req.request.method).toEqual('GET'); + req.flush(value); + }) +}); + +function encodeBase64Url(s: string): string { + return window.btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); +} \ No newline at end of file diff --git a/projects/aas-portal/src/test/dashboard/dashboard.component.spec.ts b/projects/aas-portal/src/test/dashboard/dashboard.component.spec.ts new file mode 100644 index 00000000..a5e04326 --- /dev/null +++ b/projects/aas-portal/src/test/dashboard/dashboard.component.spec.ts @@ -0,0 +1,344 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { JWTPayload, WebSocketData } from 'common'; +import { first, of, Subject } from 'rxjs'; +import { AASLibModule, NotifyService, AuthService, WebSocketFactoryService } from 'aas-lib'; + +import { DashboardComponent } from '../../app/dashboard/dashboard.component'; +import { TestWebSocketFactoryService } from 'src/test/assets/test-web-socket-factory.service'; +import { AppRoutingModule } from 'src/app/app-routing.module'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { Store, StoreModule } from '@ngrx/store'; +import { dashboardReducer } from 'src/app/dashboard/dashboard.reducer'; +import { CommonModule } from '@angular/common'; +import { pages } from './test-pages'; +import { DashboardService } from 'src/app/dashboard/dashboard.service'; +import { SelectionMode } from 'src/app/types/selection-mode'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { EffectsModule } from '@ngrx/effects'; +import * as DashboardActions from '../../app/dashboard/dashboard.actions'; +import { DashboardChart, State } from 'src/app/dashboard/dashboard.state'; + +describe('DashboardComponent', () => { + let component: DashboardComponent; + let fixture: ComponentFixture; + let webSocketSubject: Subject; + let store: Store; + let service: DashboardService; + let auth: jasmine.SpyObj; + + beforeEach(() => { + webSocketSubject = new Subject(); + + auth = jasmine.createSpyObj(['checkCookie', 'getCookie', 'setCookie'], { + payload: of({ id: 'john.doe@email.com', role: 'editor', name: 'John' } as JWTPayload) + }); + + auth.checkCookie.and.returnValue(true); + auth.getCookie.and.returnValue(JSON.stringify(pages)); + + TestBed.configureTestingModule({ + declarations: [ + DashboardComponent + ], + providers: [ + { + provide: WebSocketFactoryService, + useValue: new TestWebSocketFactoryService(webSocketSubject) + }, + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error']) + }, + { + provide: AuthService, + useValue: auth + } + ], + imports: [ + CommonModule, + AppRoutingModule, + HttpClientTestingModule, + AASLibModule, + EffectsModule.forRoot(), + StoreModule.forRoot( + { + dashboard: dashboardReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + + ] + }); + + fixture = TestBed.createComponent(DashboardComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + store = TestBed.inject(Store); + service = TestBed.inject(DashboardService); + + store.dispatch(DashboardActions.setPages({ pages })); + store.dispatch(DashboardActions.setPageName({ name: 'Test' })); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('shows the Test page', function () { + expect(component.page.name).toEqual('Test'); + }); + + it('displays two rows', function () { + expect(component.rows.length).toEqual(2); + }); + + describe('single selection', function () { + it('supports single mode selection', function () { + expect(component.selectionMode).toEqual(SelectionMode.Single); + }); + + it('indicates no item selected', function () { + expect(component.selectedItem).toBeNull(); + expect(component.selectedItems.length).toEqual(0); + }); + + it('allows to toggle the selection of a chart', function () { + component.toggleSelection(component.rows[0].columns[0]); + expect(component.selectedItem).toEqual(component.rows[0].columns[0].item); + expect(component.selectedItems.length).toEqual(1); + component.toggleSelection(component.rows[0].columns[0]); + expect(component.selectedItem).toBeNull(); + expect(component.selectedItems.length).toEqual(0); + }); + + it('ensures that only one item is selected', function () { + component.toggleSelection(component.rows[0].columns[0]); + expect(component.selectedItem).toEqual(component.rows[0].columns[0].item); + expect(component.selectedItems.length).toEqual(1); + component.toggleSelection(component.rows[0].columns[1]); + expect(component.selectedItem).toEqual(component.rows[0].columns[1].item); + expect(component.selectedItems.length).toEqual(1); + }); + }); + + describe('view mode', function () { + it('has a view mode (initial)', function () { + expect(component.editMode).toBeFalse(); + }); + }); + + describe('edit mode', function () { + beforeEach(function () { + component.toggleEditMode(); + }); + + it('has an edit mode', function () { + expect(component.editMode).toBeTrue(); + }); + + it('can move item[0, 1] to the left', function (done: DoneFn) { + const id = component.rows[0].columns[1].id; + component.toggleSelection(component.rows[0].columns[1]); + expect(component.canMoveLeft()).toBeTrue(); + component.moveLeft(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[0].id).toEqual(id); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[1].id).toEqual(id); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[0].id).toEqual(id); + done(); + }); + }); + + it('can move item[0, 0] to the right including undo/redo', function (done: DoneFn) { + const id = component.rows[0].columns[0].id; + component.toggleSelection(component.rows[0].columns[0]); + expect(component.canMoveRight()).toBeTrue(); + component.moveRight(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[1].id).toEqual(id); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[0].id).toEqual(id); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[1].id).toEqual(id); + done(); + }); + }); + + it('can move item[0, 0] up creating a new row including undo/redo', function (done: DoneFn) { + const id = component.rows[0].columns[0].id; + component.toggleSelection(component.rows[0].columns[0]); + expect(component.canMoveUp()).toBeTrue(); + component.moveUp(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows.length).toEqual(3); + expect(rows[0].columns[0].id).toEqual(id); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows.length).toEqual(2); + expect(rows[0].columns[0].id).toEqual(id); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows.length).toEqual(3); + expect(rows[0].columns[0].id).toEqual(id); + done(); + }); + }); + + it('can move item[0, 0] down to [1, 1] including undo/redo', function (done: DoneFn) { + const id = component.rows[0].columns[0].id; + component.toggleSelection(component.rows[0].columns[0]); + expect(component.canMoveDown()).toBeTrue(); + component.moveDown(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[1].columns[1].id).toEqual(id); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[0].columns[0].id).toEqual(id); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect(rows[1].columns[1].id).toEqual(id); + done(); + }); + }); + + it('gets the color of a chart', function () { + expect(component.getColor(component.rows[0].columns[0])).toEqual('#123456'); + }); + + it('sets the color of a chart including undo/redo', function (done: DoneFn) { + component.changeColor(component.rows[0].columns[0], '#AA55AA'); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).sources[0].color).toEqual('#AA55AA'); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).sources[0].color).toEqual('#123456'); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).sources[0].color).toEqual('#AA55AA'); + done(); + }); + }); + + it('gets the source labels of a chart', function () { + expect(component.getSources(component.rows[0].columns[0])).toEqual(['RotationSpeed']); + }); + + it('can delete the Test page', function (done: DoneFn) { + const name = component.page.name; + component.delete(); + service.pages.pipe(first()).subscribe(pages => { + expect(pages.find(item => item.name === name)).toBeUndefined(); + done(); + }); + }); + + it('can change the min value', function (done: DoneFn) { + component.changeMin(component.rows[0].columns[0], '0'); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).min).toEqual(0); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).min).toBeUndefined(); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).min).toEqual(0); + done(); + }); + }); + + it('can change the max value', function (done: DoneFn) { + component.changeMax(component.rows[0].columns[0], '5500'); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).max).toEqual(5500); + }); + + expect(component.canUndo()).toBeTrue(); + component.undo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).max).toBeUndefined(); + }); + + expect(component.canRedo()).toBeTrue(); + component.redo(); + store.select(state => state.dashboard.rows).pipe(first()) + .subscribe(rows => { + expect((rows[0].columns[0].item as DashboardChart).max).toEqual(5500); + done(); + }); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/dashboard/dashboard.service.spec.ts b/projects/aas-portal/src/test/dashboard/dashboard.service.spec.ts new file mode 100644 index 00000000..18c8bd67 --- /dev/null +++ b/projects/aas-portal/src/test/dashboard/dashboard.service.spec.ts @@ -0,0 +1,187 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { first } from 'rxjs'; +import { dashboardReducer } from 'src/app/dashboard/dashboard.reducer'; +import { rotationSpeed, sampleDocument, torque } from 'src/test/assets/sample-document'; + +import { DashboardService } from '../../app/dashboard/dashboard.service'; +import { pages } from './test-pages'; +import { DashboardChart, DashboardChartType, DashboardItem, DashboardPage } from 'src/app/dashboard/dashboard.state'; +import { AuthService } from 'aas-lib'; + +describe('DashboardService', function () { + let service: DashboardService; + let auth: jasmine.SpyObj; + + beforeEach(() => { + auth = jasmine.createSpyObj(['checkCookie', 'getCookie', 'setCookie']); + auth.checkCookie.and.returnValue(true); + auth.getCookie.and.returnValue(JSON.stringify(pages)); + + TestBed.configureTestingModule({ + providers: [ + { + provide: AuthService, + useValue: auth + } + ], + imports: [ + HttpClientTestingModule, + StoreModule.forRoot( + { + dashboard: dashboardReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + service = TestBed.inject(DashboardService); + }); + + it('should be created', function () { + expect(service).toBeTruthy(); + }); + + it('provides always a default page', function () { + expect(service.defaultPage?.name).toBeDefined(); + }); + + it('provides an observable collection of pages', function (done: DoneFn) { + service.pages.pipe(first()).subscribe(items => { + expect(items).toEqual(pages); + done(); + }); + }); + + it('allows finding a specific dashboard page', function () { + expect(service.find('Test')).toEqual(pages[1]); + }); + + it('returns undefined for an unknown dashboard page', function () { + expect(service.find('unknown')).toBeUndefined(); + }); + + it('returns the Test dashboard as a grid with 2 rows and 2/1 column', function () { + const page = service.find('Test')!; + const grid = service.getGrid(page); + expect(grid.length).toEqual(2); + expect(grid[0].length).toEqual(2); + expect(grid[1].length).toEqual(1); + }); + + it('returns the Test dashboard as rows', function () { + const page = service.find('Test')!; + const rows = service.getRows(page); + expect(rows.length).toEqual(2); + expect(rows[0].columns.length).toEqual(2); + expect(rows[1].columns.length).toEqual(1); + }); + + it('provides the name of the current active dashboard', function (done: DoneFn) { + service.name.pipe(first()).subscribe(value => { + expect(value).toEqual('Dashboard 1'); + done(); + }); + }); + + describe('setPageName', function () { + it('allows setting "Test" as new active dashboard', function (done: DoneFn) { + service.setPageName('Test'); + service.name.pipe(first()).subscribe(value => { + expect(value).toEqual('Test'); + done(); + }); + }); + + it('throws an error if a dashboard with the specified does not exist', function () { + expect(() => service.setPageName('unknown')).toThrowError(); + }); + }); + + describe('add', function () { + it('allows adding RotationSpeed and Torque to the default page as separate line charts', function (done: DoneFn) { + service.add(service.defaultPage.name, sampleDocument, [rotationSpeed, torque], DashboardChartType.Line); + service.pages.pipe(first()).subscribe(items => { + const defaultPage = items[0]; + expect(defaultPage.items.length).toEqual(2); + expect(defaultPage.items.map(item => item as DashboardChart) + .flatMap(item => item.sources) + .map(item => item.label)).toEqual(['RotationSpeed', 'Torque']); + + done(); + }); + }); + + it('allows adding RotationSpeed and Torque to the default page as single bar chart', function (done: DoneFn) { + service.add(service.defaultPage.name, sampleDocument, [rotationSpeed, torque], DashboardChartType.BarVertical); + service.pages.pipe(first()).subscribe(items => { + const defaultPage = items[0]; + expect(defaultPage.items.length).toEqual(1); + const chart = defaultPage.items[0] as DashboardChart; + expect(chart.sources.map(source => source.label)).toEqual(['RotationSpeed', 'Torque']); + done(); + }); + }); + + it('throws an error when adding a property to an unknown page', function () { + expect(() => service.add('unknown', sampleDocument, [rotationSpeed, torque], DashboardChartType.BarVertical)).toThrowError(); + }); + }); + + describe('save', function () { + it('allows saving the current dashboard state', function () { + service.add(service.defaultPage.name, sampleDocument, [rotationSpeed, torque], DashboardChartType.BarVertical); + service.save(); + expect(auth.setCookie).toHaveBeenCalled(); + }); + }); + + describe('canMove...', function () { + let page: DashboardPage; + let grid: DashboardItem[][]; + + beforeEach(function () { + page = service.find('Test')!; + grid = service.getGrid(page); + }); + + it('indicates whether a chart can be moved to the left', function () { + expect(service.canMoveLeft(page, grid[0][0])).toBeFalse(); + expect(service.canMoveLeft(page, grid[0][1])).toBeTrue(); + expect(service.canMoveLeft(page, grid[1][0])).toBeFalse(); + }); + + it('indicates whether a chart can be moved to the right', function () { + expect(service.canMoveRight(page, grid[0][0])).toBeTrue(); + expect(service.canMoveRight(page, grid[0][1])).toBeFalse(); + expect(service.canMoveRight(page, grid[1][0])).toBeFalse(); + }); + + it('indicates whether a chart can be moved up', function () { + expect(service.canMoveUp(page, grid[0][0])).toBeTrue(); + expect(service.canMoveUp(page, grid[0][1])).toBeTrue(); + expect(service.canMoveUp(page, grid[1][0])).toBeTrue(); + }); + + it('indicates whether a chart can be moved down', function () { + expect(service.canMoveDown(page, grid[0][0])).toBeTrue(); + expect(service.canMoveDown(page, grid[0][1])).toBeTrue(); + expect(service.canMoveDown(page, grid[1][0])).toBeFalse(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/dashboard/test-pages.ts b/projects/aas-portal/src/test/dashboard/test-pages.ts new file mode 100644 index 00000000..4e62ed7f --- /dev/null +++ b/projects/aas-portal/src/test/dashboard/test-pages.ts @@ -0,0 +1,66 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { DashboardChart, DashboardChartType, DashboardItemType } from "src/app/dashboard/dashboard.state"; +import { maxRotationSpeed, rotationSpeed, torque } from "src/test/assets/sample-document"; + +export const pages = [{ + name: 'Dashboard 1', + items: [], + requests: [] +}, +{ + name: 'Test', + items: [ + { + label: 'Chart 1', + chartType: DashboardChartType.Line, + id: '42', + sources: [ + { + color: '#123456', + label: 'RotationSpeed', + node: null, + element: rotationSpeed + }], + positions: [{ x: 0, y: 0 }], + type: DashboardItemType.Chart + } as DashboardChart, + { + label: 'Chart 2', + chartType: DashboardChartType.Line, + id: '4711', + sources: [ + { + color: '#654321', + label: 'Torque', + node: null, + element: torque + }], + positions: [{ x: 1, y: 0 }], + type: DashboardItemType.Chart + + } as DashboardChart, + { + label: 'Chart 3', + chartType: DashboardChartType.Line, + id: '0815', + sources: [ + { + color: '#987654', + label: 'MaxRotationSpeed', + node: null, + element: maxRotationSpeed + }], + positions: [{ x: 0, y: 1 }], + type: DashboardItemType.Chart + + } as DashboardChart + ], + requests: [] +}]; \ No newline at end of file diff --git a/projects/aas-portal/src/test/main/main.component.spec.ts b/projects/aas-portal/src/test/main/main.component.spec.ts new file mode 100644 index 00000000..52a68de6 --- /dev/null +++ b/projects/aas-portal/src/test/main/main.component.spec.ts @@ -0,0 +1,72 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AppRoutingModule } from 'src/app/app-routing.module'; +import { MainComponent } from '../../app/main/main.component'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { AASDocument } from 'common'; +import { Subject } from 'rxjs'; +import { CommonModule } from '@angular/common'; +import { AASLibModule } from 'aas-lib'; +import { EffectsModule } from '@ngrx/effects'; +import { StoreModule } from '@ngrx/store'; +import { ProjectService } from 'src/app/project/project.service'; + +describe('MainComponent', () => { + let component: MainComponent; + let fixture: ComponentFixture; + let documentSubject: Subject; + let project: jasmine.SpyObj; + + beforeEach(() => { + documentSubject = new Subject(); + documentSubject.next(null); + project = jasmine.createSpyObj('ProjectService', ['getDocument', 'findDocument']); + + TestBed.configureTestingModule({ + declarations: [ + MainComponent + ], + providers: [ + { + provide: ProjectService, + useValue: project + } + ], + imports: [ + CommonModule, + AppRoutingModule, + NgbModule, + AASLibModule, + EffectsModule.forRoot(), + StoreModule.forRoot(), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(MainComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('provides a list of route links', function () { + expect(component.links).toBeDefined(); + expect(component.links.map(link => link.url)).toEqual(['/start', '/aas', '/view', '/dashboard', '/about']); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/project/project-api.service.spec.ts b/projects/aas-portal/src/test/project/project-api.service.spec.ts new file mode 100644 index 00000000..69d67dd9 --- /dev/null +++ b/projects/aas-portal/src/test/project/project-api.service.spec.ts @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { TestBed } from '@angular/core/testing'; +import { AASWorkspace } from 'common'; + +import { ProjectAPIService } from '../../app/project/project-api.service'; +import { createDocument } from '../assets/test-document'; + +describe('ProjectApiService', function () { + let service: ProjectAPIService; + let httpTestingController: HttpTestingController; + + beforeEach(function () { + + TestBed.configureTestingModule({ + declarations: [], + providers: [], + imports: [HttpClientTestingModule], + }); + + service = TestBed.inject(ProjectAPIService); + httpTestingController = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpTestingController.verify(); + }); + + it('should created', function () { + expect(service).toBeTruthy(); + }); + + it('GET: /api/v1/workspaces', function () { + const workspaces: AASWorkspace[] = [ + { + name: 'WS1', + containers: [] + }, + { + name: 'WS2', + containers: [] + }, + ]; + + service.getWorkspaces().subscribe(value => { + expect(value).toEqual(workspaces); + }); + + const req = httpTestingController.expectOne('/api/v1/workspaces'); + expect(req.request.method).toEqual('GET'); + req.flush(workspaces); + }); + + it('GET: /api/v1/controllers/:url/documents/:id', function () { + const document = createDocument('document1'); + + service.getDocument('document1', 'https:/www.fraunhofer.de/container1').subscribe(value => { + expect(value).toEqual(document); + }); + + const req = httpTestingController.expectOne('/api/v1/containers/aHR0cHM6L3d3dy5mcmF1bmhvZmVyLmRlL2NvbnRhaW5lcjE/documents/ZG9jdW1lbnQx'); + expect(req.request.method).toEqual('GET'); + req.flush(document); + }); + + it('GET: /api/v1/documents/:id', function () { + const document = createDocument('document1'); + + service.getDocument('document1').subscribe(value => { + expect(value).toEqual(document); + }); + + const req = httpTestingController.expectOne('/api/v1/documents/ZG9jdW1lbnQx'); + expect(req.request.method).toEqual('GET'); + req.flush(document); + }); + + it('GET: /api/v1/containers/:url/documents', function () { + const documents = [createDocument('document1'), createDocument('document2')]; + + service.getDocuments('https:/www.fraunhofer.de/container1').subscribe(value => { + expect(value).toEqual(documents); + }); + + const req = httpTestingController.expectOne('/api/v1/containers/aHR0cHM6L3d3dy5mcmF1bmhvZmVyLmRlL2NvbnRhaW5lcjE/documents'); + expect(req.request.method).toEqual('GET'); + req.flush(documents); + }); + + it('GET: /api/v1/containers/:url/documents/:id/content', function () { + const root = createDocument('document1').content!; + + service.getContent('document1', 'https:/www.fraunhofer.de/container1').subscribe(value => { + expect(value).toEqual(root); + }); + + const req = httpTestingController.expectOne('/api/v1/containers/aHR0cHM6L3d3dy5mcmF1bmhvZmVyLmRlL2NvbnRhaW5lcjE/documents/ZG9jdW1lbnQx/content'); + expect(req.request.method).toEqual('GET'); + req.flush(root); + }); + + it('POST: /api/v1/endpoints/:name', function () { + const name = 'Test'; + const url = `file:///resources/samples/`; + service.addEndpoint(name, url).subscribe(); + const req = httpTestingController.expectOne('/api/v1/endpoints/Test'); + expect(req.request.method).toEqual('POST'); + expect(req.request.body).toEqual({ url }); + }); + + it('DELETE: /api/v1/endpoints/:name', function () { + service.removeEndpoint('samples').subscribe(); + const req = httpTestingController.expectOne('/api/v1/endpoints/samples'); + expect(req.request.method).toEqual('DELETE'); + }); + + it('DELETE: /api/v1/containers/:url/documents/:id', function () { + service.deleteDocument('document1', 'https:/www.fraunhofer.de/container1').subscribe(); + const req = httpTestingController.expectOne('/api/v1/containers/aHR0cHM6L3d3dy5mcmF1bmhvZmVyLmRlL2NvbnRhaW5lcjE/documents/ZG9jdW1lbnQx'); + expect(req.request.method).toEqual('DELETE'); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/project/project.service.spec.ts b/projects/aas-portal/src/test/project/project.service.spec.ts new file mode 100644 index 00000000..5aa7f65a --- /dev/null +++ b/projects/aas-portal/src/test/project/project.service.spec.ts @@ -0,0 +1,399 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TestBed } from '@angular/core/testing'; +import { EffectsModule } from '@ngrx/effects'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { EMPTY, first, of, Subject, throwError } from 'rxjs'; +import { Store, StoreModule } from '@ngrx/store'; +import { CommonModule } from '@angular/common'; +import { AASLibModule, NotifyService, AuthService, WebSocketFactoryService } from 'aas-lib'; +import { WebSocketSubject } from 'rxjs/webSocket'; +import { + aas, + AASDocument, + AASContainer, + WebSocketData, + AASServerMessage, + AASWorkspace +} from 'common'; + +import * as ws from '../assets/test-document'; +import { ProjectEffects } from '../../app/project/project.effects'; +import { ProjectAPIService } from '../../app/project/project-api.service'; +import { projectReducer } from '../../app/project/project.reducer'; +import { ProjectState } from '../../app/project/project.state'; +import { ProjectService } from '../../app/project/project.service'; +import { createEndpoint } from '../../app/configuration'; + +class TestWebSocketFactoryService implements Partial { + constructor(private readonly subject: Subject) { } + + public create(): WebSocketSubject { + return this.subject as WebSocketSubject; + } +} + +describe('ProjectService', () => { + let service: ProjectService; + let api: jasmine.SpyObj; + let auth: jasmine.SpyObj; + let store: Store<{ project: ProjectState }>; + let document1: AASDocument; + let document2: AASDocument; + let document3: AASDocument; + let content: aas.Environment; + let container1: AASContainer; + let container2: AASContainer; + let ws1: AASWorkspace; + let ws2: AASWorkspace; + let webSocketSubject: Subject; + + beforeEach(() => { + document1 = ws.createDocument('document1', 'http://localhost/container1'); + document2 = ws.createDocumentHeader('document2', 'http://localhost/container2'); + document3 = ws.createDocument('document3', 'http://localhost/container2'); + document3.modified = true; + container1 = ws.createContainer('http://localhost/container1', [document1, document2]); + container2 = ws.createContainer('http://localhost/container2', [document3]); + ws1 = ws.createWorkspace('WS1', [container1, container2]); + ws2 = ws.createWorkspace('WS2', [container1, container2]); + + webSocketSubject = new Subject(); + + api = jasmine.createSpyObj( + 'ProjectAPIService', + [ + 'getWorkspaces', + 'getDocuments', + 'getDocument', + 'getContent', + 'addEndpoint', + 'removeEndpoint', + 'reset', + 'deleteDocument']); + + api.getWorkspaces.and.returnValue(of([ws1, ws2])); + api.getDocuments.and.callFake((url: string) => { + if (url === 'http://localhost/container1') { + return of([document1, document2]); + } else if (url === 'http://localhost/container2') { + return of([document3]); + } + + return EMPTY; + }); + + api.getContent.and.returnValue(of(content)); + + auth = jasmine.createSpyObj('AuthService', ['checkCookie', 'getCookie', 'setCookie']); + auth.checkCookie.and.returnValue(false); + + TestBed.configureTestingModule({ + declarations: [], + providers: [ + { + provide: ProjectAPIService, + useValue: api, + }, + { + provide: NotifyService, + useValue: jasmine.createSpyObj(['error']) + }, + { + provide: WebSocketFactoryService, + useValue: new TestWebSocketFactoryService(webSocketSubject), + }, + { + provide: AuthService, + useValue: auth, + } + ], + imports: [ + CommonModule, + HttpClientTestingModule, + AASLibModule, + EffectsModule.forRoot([ProjectEffects]), + StoreModule.forRoot({ + project: projectReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + service = TestBed.inject(ProjectService); + store = TestBed.inject(Store); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + it('has an initial workspace', function (done: DoneFn) { + service.workspace.pipe(first()).subscribe((workspace) => { + expect(workspace?.name).toEqual('WS1'); + done(); + }); + }); + + it('sets a new active workspace', function (done: DoneFn) { + service.setWorkspace('WS2'); + service.workspace.pipe(first()).subscribe((value) => { + expect(value?.name).toEqual('WS2'); + done(); + }); + }); + + it('throws an error if the workspace does not exist', function (done: DoneFn) { + service.setWorkspace('unknown'); + store.select(state => state.project.error).pipe(first()).subscribe({ + next: (error) => { + expect(error instanceof Error).toBeTrue(); + done(); + } + }) + }); + + it('returns all available documents', function (done: DoneFn) { + service.documents.pipe(first()).subscribe(documents => { + expect(documents.map(item => item.idShort)).toEqual(['document1', 'document2', 'document3']); + done(); + }); + }); + + it('adds a new document (with content)', function (done: DoneFn) { + const data: WebSocketData = { + type: 'AASServerMessage', + data: { + type: 'Added', + document: ws.createDocument('AddedDocument', 'http://localhost/container1'), + } as AASServerMessage, + }; + + webSocketSubject.next(data); + + service.documents.pipe(first()).subscribe((documents) => { + expect(documents.find((document) => document.idShort === 'AddedDocument')).toBeDefined(); + done(); + }); + }); + + it('adds a new document (no content)', function (done: DoneFn) { + const data: WebSocketData = { + type: 'AASServerMessage', + data: { + type: 'Added', + document: ws.createDocumentHeader('AddedDocument', 'http://localhost/container1'), + } as AASServerMessage, + }; + + webSocketSubject.next(data); + + service.documents.pipe(first()).subscribe((documents) => { + expect(documents.find((document) => document.idShort === 'AddedDocument')).toBeDefined(); + done(); + }); + }); + + it('removes a document', function (done: DoneFn) { + const data: WebSocketData = { + type: 'AASServerMessage', + data: { + type: 'Removed', + document: document2 + } as AASServerMessage, + }; + + webSocketSubject.next(data); + + service.documents.pipe(first()).subscribe((documents) => { + expect(documents.find((document) => document.idShort === 'AddedDocument')).toBeUndefined(); + done(); + }); + }); + + it('updates a document', function (done: DoneFn) { + const data: WebSocketData = { + type: 'AASServerMessage', + data: { + type: 'Changed', + document: document2, + } as AASServerMessage, + }; + + webSocketSubject.next(data); + + service.documents.pipe(first()).subscribe((documents) => { + expect(documents.find((document) => document.idShort === 'document2')).toBeDefined(); + done() + }); + }); + + it('adds an AAS container to a workspace', function (done: DoneFn) { + const data: WebSocketData = { + type: 'AASServerMessage', + data: { + type: 'ContainerAdded', + endpoint: createEndpoint('http://localhost/registry', { name: 'WS1', type: 'AASRegistry' }), + container: ws.createContainer('http://localhost/container3', []) + } as AASServerMessage, + }; + + webSocketSubject.next(data); + + service.containers.pipe(first()).subscribe({ + next: (containers) => { + expect(containers.some(item => item.url === 'http://localhost/container3')).toBeTrue(); + done(); + } + }); + }); + + it('removes an AAS container from workspace', function (done: DoneFn) { + const data: WebSocketData = { + type: 'AASServerMessage', + data: { + type: 'ContainerRemoved', + endpoint: createEndpoint('http://localhost/registry', { name: 'WS1', type: 'AASRegistry' }), + container: container2 + } as AASServerMessage, + }; + + webSocketSubject.next(data); + + service.workspaces.pipe(first()).subscribe({ + next: (workspaces) => { + expect(workspaces.find(item => item.name === 'WS1')!.containers).toEqual([container1]); + expect(workspaces.find(item => item.name === 'WS2')!.containers).toEqual([container1, container2]); + done(); + } + }); + }); + + it('adds an AAS endpoint to the current server configuration', function (done: DoneFn) { + api.addEndpoint.and.returnValue(EMPTY); + service.addEndpoint( + 'samples', + createEndpoint('file:///samples', 'samples')) + .subscribe({ + complete: () => { + expect(api.addEndpoint).toHaveBeenCalled(); + done(); + } + }); + }); + + it('removes an AAS endpoint from the server configuration', function (done: DoneFn) { + api.removeEndpoint.and.returnValue(EMPTY); + service.removeEndpoint('samples').subscribe({ + complete: () => { + expect().nothing(); + done(); + } + }); + }); + + it('restores the default server configuration', function (done: DoneFn) { + api.reset.and.returnValue(EMPTY); + service.reset().subscribe({ + complete: () => { + expect().nothing(); + done(); + } + }); + }); + + it('allows deleting a document', function (done: DoneFn) { + api.deleteDocument.and.returnValue(EMPTY); + service.deleteDocument(document1).subscribe({ + complete: () => { + expect(api.deleteDocument).toHaveBeenCalled(); + done(); + } + }) + }); + + it('applies a modified document', function (done: DoneFn) { + const modified: AASDocument = { ...document1, modified: true }; + service.applyDocument(modified); + service.documents.pipe(first()).subscribe(items => { + const document = items.find(item => item.id === modified.id && + item.container === modified.container); + + expect(document).toBeDefined(); + expect(document?.modified).toBeTrue(); + done(); + }); + }); + + describe('findDocument', function () { + it('indicates that any "document1" exist', function (done: DoneFn) { + service.findDocument('document1').pipe(first()).subscribe(result => { + expect(result).toBeDefined(); + done(); + }) + }); + + it('indicates that "document1" in "http://localhost/container1" exist', function (done: DoneFn) { + service.findDocument('document1', 'http://localhost/container1').pipe(first()).subscribe(result => { + expect(result).toBeDefined(); + done(); + }) + }); + + it('indicates that "document1" does not exist in "http://localhost/container2" exist', function (done: DoneFn) { + api.getDocument.and.returnValue(throwError(() => { throw new Error(); })); + service.findDocument('document1', 'http://localhost/container2').pipe(first()).subscribe(result => { + expect(result).toBeUndefined(); + done(); + }) + }); + + it('indicates that any "document42" does not exist', function (done: DoneFn) { + api.getDocument.and.returnValue(throwError(() => { throw new Error(); })); + service.findDocument('document42').pipe(first()).subscribe(result => { + expect(result).toBeUndefined(); + done(); + }) + }); + }); + + describe('getDocument', function () { + it('gets a document with the id or name "document1"', function (done: DoneFn) { + service.getDocument('document1').pipe(first()).subscribe(document => { + expect(document).toEqual(document1); + done(); + }) + }); + + it('gets "document1" from "http://localhost/container1"', function (done: DoneFn) { + service.getDocument('document1', 'http://localhost/container1').pipe(first()).subscribe(document => { + expect(document).toEqual(document1); + done(); + }) + }); + + it('gets "document42" from AASServer', function (done: DoneFn) { + const document42 = ws.createDocumentHeader('document42', 'http://localhost/container42'); + const content = ws.createContent(); + api.getDocument.and.returnValue(of(document42)); + api.getContent.and.returnValue(of(content)); + + service.getDocument('document42', 'http://localhost/container42').pipe(first()).subscribe(document => { + expect(document.idShort).toEqual('document42'); + done(); + }) + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/start/add-endpoint-form.component.spec.ts b/projects/aas-portal/src/test/start/add-endpoint-form.component.spec.ts new file mode 100644 index 00000000..a585fa81 --- /dev/null +++ b/projects/aas-portal/src/test/start/add-endpoint-form.component.spec.ts @@ -0,0 +1,175 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AddEndpointFormComponent } from '../../app/start/add-endpoint-form/add-endpoint-form.component'; + +describe('AddEndpointFormComponent', () => { + let component: AddEndpointFormComponent; + let fixture: ComponentFixture; + let inputNameElement: HTMLInputElement; + let inputUrlElement: HTMLInputElement; + let modal: NgbActiveModal; + let form: HTMLFormElement; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + AddEndpointFormComponent + ], + providers: [ + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(AddEndpointFormComponent); + modal = TestBed.inject(NgbActiveModal); + component = fixture.componentInstance; + fixture.detectChanges(); + + form = fixture.debugElement.nativeElement.querySelector('form'); + inputNameElement = fixture.debugElement.nativeElement.querySelector('#input-endpoint-name'); + inputUrlElement = fixture.debugElement.nativeElement.querySelector('#input-endpoint-url'); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('submits endpoint Name: "My endpoint", URL: "file:///my-endpoint"', function () { + let endpoint: string | undefined; + spyOn(modal, 'close').and.callFake((result) => endpoint = result); + + component.item = component.items[3]; + component.name = 'My endpoint'; + component.item.value = 'file:///my-endpoint'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalled(); + expect(endpoint).toEqual('file:///my-endpoint?name=My+endpoint'); + }); + + it('submits AAS endpoint Name: "My endpoint", URL: "file:///a\\b\\my-endpoint"', function () { + let endpoint: string | undefined; + spyOn(modal, 'close').and.callFake((result) => endpoint = result); + + component.item = component.items[3]; + component.name = 'My endpoint'; + component.item.value = 'file:///a\\b\\my-endpoint'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalled(); + expect(endpoint).toEqual('file:///a/b/my-endpoint?name=My+endpoint'); + }); + + it('ignores AAS endpoint: Name: "", URL: "file:///my-endpoint"', function () { + spyOn(modal, 'close'); + + component.item = component.items[3]; + component.name = ''; + component.item.value = 'file:///my-endpoint'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalledTimes(0); + expect(component.messages.length > 0).toBeTrue(); + }); + + it('ignores AAS endpoint Name: "My endpoint", URL: "file:///"', function () { + spyOn(modal, 'close'); + + component.item = component.items[3]; + component.name = 'My endpoint'; + component.item.value = 'file:///'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalledTimes(0); + expect(component.messages.length > 0).toBeTrue(); + }); + + it('submits AAS endpoint Name: "I4AAS Server", URL: "opc.tcp://172.16.160.178:30001/I4AASServer"', function () { + let endpoint: string | undefined; + spyOn(modal, 'close').and.callFake((result) => endpoint = result); + + component.item = component.items[2]; + component.name = 'I4AAS Server'; + component.item.value = 'opc.tcp://172.16.160.178:30001/I4AASServer'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalled(); + expect(endpoint).toEqual('opc.tcp://172.16.160.178:30001/I4AASServer?name=I4AAS+Server'); + }); + + it('ignores AAS endpoint Name: "I4AAS Server", URL: "opc.tcp://"', function () { + spyOn(modal, 'close'); + + component.item = component.items[2]; + fixture.detectChanges(); + + inputNameElement.value = 'I4AAS Server'; + inputNameElement.dispatchEvent(new Event('input')); + inputUrlElement.value = 'opc.tcp://'; + inputUrlElement.dispatchEvent(new Event('input')); + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalledTimes(0); + expect(component.messages.length > 0).toBeTrue(); + }); + + it('submits AAS registry Name: "AAS Registry", URL: "http://172.16.160.188:50000/registry/api/v1/registry/"', function () { + let endpoint: string | undefined; + spyOn(modal, 'close').and.callFake((result) => endpoint = result); + + component.item = component.items[1]; + component.name = 'AAS Registry'; + component.item.value = 'http://172.16.160.188:50000/registry/api/v1/registry/'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalled(); + expect(endpoint).toEqual('http://172.16.160.188:50000/registry/api/v1/registry/?name=AAS+Registry&type=AASRegistry'); + }); + + it('ignores endpoint Name: "AAS Registry", URL: "http://"', function () { + spyOn(modal, 'close'); + + component.item = component.items[1]; + component.name = 'AAS Registry'; + component.item.value = 'http://'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalledTimes(0); + expect(component.messages.length > 0).toBeTrue(); + }); + + it('submits AASX server Name: "AASX Server", URL: "http://172.16.160.188:50001/"', function () { + let endpoint: string | undefined; + spyOn(modal, 'close').and.callFake((result) => endpoint = result); + + component.item = component.items[0]; + component.name = 'AASX Server'; + component.item.value = 'http://172.16.160.188:50001/'; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalled(); + expect(endpoint).toEqual('http://172.16.160.188:50001/?name=AASX+Server'); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts b/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts new file mode 100644 index 00000000..24377c10 --- /dev/null +++ b/projects/aas-portal/src/test/start/remove-endpoint-form.component.spec.ts @@ -0,0 +1,87 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; + +import { RemoveEndpointFormComponent } from '../../app/start/remove-endpoint-form/remove-endpoint-form.component'; + + +describe('RemoveEndpointFormComponent', () => { + let component: RemoveEndpointFormComponent; + let fixture: ComponentFixture; + let submitButton: HTMLButtonElement; + let modal: NgbActiveModal; + let form: HTMLFormElement; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + RemoveEndpointFormComponent + ], + providers: [ + NgbActiveModal + ], + imports: [ + CommonModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + + ] + }); + + fixture = TestBed.createComponent(RemoveEndpointFormComponent); + component = fixture.componentInstance; + component.endpoints = [ + { name: 'Samples', url: 'http://localhost:1234', selected: false }, + { name: 'I4AAS Server', url: 'http://localhost:1235', selected: false }, + { name: 'AAS Registry', url: 'http://localhost:1236', selected: false } + ]; + + fixture.detectChanges(); + + modal = TestBed.inject(NgbActiveModal); + form = fixture.debugElement.nativeElement.querySelector('form'); + submitButton = fixture.debugElement.nativeElement.querySelector('button[type="submit"]'); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('allows deleting the "Samples" registry', function () { + spyOn(modal, 'close').and.callFake(result => { + expect(result).toEqual(['Samples']); + }); + + const inputElement: HTMLInputElement = fixture.debugElement.nativeElement.querySelector('#inputSamples'); + inputElement.checked = true; + inputElement.dispatchEvent(new Event('change')); + // Hack + component.endpoints[0].selected = true; + + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalled(); + }); + + it('allows deleting the "Samples" registry', function () { + spyOn(modal, 'close'); + form.dispatchEvent(new Event('submit')); + expect(modal.close).toHaveBeenCalledTimes(0); + expect(component.messages.length > 0).toBeTrue(); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/start/start.component.spec.ts b/projects/aas-portal/src/test/start/start.component.spec.ts new file mode 100644 index 00000000..93162224 --- /dev/null +++ b/projects/aas-portal/src/test/start/start.component.spec.ts @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Store, StoreModule } from '@ngrx/store'; +import { Observable, of } from 'rxjs'; +import { WindowService, AASLibModule, ViewMode } from 'aas-lib'; +import { RouterModule } from '@angular/router'; +import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { AASContainer, AASDocument, AASWorkspace } from 'common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { EffectsModule } from '@ngrx/effects'; + +import * as ws from 'src/test/assets/test-document'; +import { startReducer } from 'src/app/start/start.reducer'; +import { StartComponent } from '../../app/start/start.component'; +import { StartState } from 'src/app/start/start.state'; +import { ProjectService } from 'src/app/project/project.service'; + +class TestProjectService implements Partial { + constructor( + private _containers: AASContainer[], + private _workspaces: AASWorkspace[], + private _workspace: AASWorkspace + ) { } + + public get containers(): Observable { + return of(this._containers); + } + + public get workspace(): Observable { + return of(this._workspace); + } + + public get workspaces(): Observable { + return of(this._workspaces); + } + + public get document(): Observable { + return of(null); + } + + public get documents(): Observable { + return of(this._workspace.containers.flatMap(item => item.documents ?? [])); + } + + public setDocument(): Observable { + return new Observable(); + } +} + +describe('StartComponent', () => { + let store: Store<{ start: StartState }>; + let window: jasmine.SpyObj; + let component: StartComponent; + let fixture: ComponentFixture; + let document1: AASDocument; + let document2: AASDocument; + let document3: AASDocument; + let container1: AASContainer; + let container2: AASContainer; + let ws1: AASWorkspace; + let ws2: AASWorkspace; + + beforeEach(() => { + window = jasmine.createSpyObj(['confirm', 'getLocalStorageItem', 'setLocalStorageItem']); + document1 = ws.createDocument('document1'); + document2 = ws.createDocument('document2'); + document3 = ws.createDocument('document3'); + container1 = ws.createContainer('https:/www.fraunhofer.de/container1', [document1, document2]); + container2 = ws.createContainer('https:/www.fraunhofer.de/container2', [document3]); + ws1 = ws.createWorkspace('WS1', [container1]); + ws2 = ws.createWorkspace('WS2', [container2]); + + TestBed.configureTestingModule({ + declarations: [ + StartComponent + ], + providers: [ + { + provide: ProjectService, + useValue: new TestProjectService([container1, container2], [ws1, ws2], ws1), + }, + { + provide: WindowService, + useValue: window, + } + ], + imports: [ + NgbModule, + RouterModule, + HttpClientTestingModule, + AASLibModule, + EffectsModule.forRoot(), + StoreModule.forRoot({ + start: startReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ], + }); + + store = TestBed.inject(Store); + fixture = TestBed.createComponent(StartComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('provides workspaces', function () { + expect(component.workspaces).toEqual([ws1, ws2]); + }); + + it('provides an active workspace', function () { + expect(component.workspace).toEqual(ws1); + }); + + it('initial view mode is "list"', function () { + expect(component.viewMode).toEqual(ViewMode.List); + }); + + it('initial shows only AAS documents with content.', function () { + expect(component.showAll).toBeFalse(); + }); + + it('indicates whether all AAS documents have content', function () { + expect(component.allAvailable).toBeTrue(); + }); + + it('sets "tree" view mode', function () { + component.setViewMode(ViewMode.Tree); + store.subscribe(state => expect(state.start.viewMode).toEqual(ViewMode.Tree)); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/start/upload-form.component.spec.ts b/projects/aas-portal/src/test/start/upload-form.component.spec.ts new file mode 100644 index 00000000..cdb96345 --- /dev/null +++ b/projects/aas-portal/src/test/start/upload-form.component.spec.ts @@ -0,0 +1,52 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { HttpClientTestingModule } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { FormsModule } from '@angular/forms'; +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap'; + +import { UploadFormComponent } from '../../app/start/upload-form/upload-form.component'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; + +describe('UploadFormComponent', () => { + let component: UploadFormComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + UploadFormComponent + ], + providers: [ + NgbActiveModal + ], + imports: [ + CommonModule, + HttpClientTestingModule, + FormsModule, + NgbModule, + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + fixture = TestBed.createComponent(UploadFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/src/test/view/view.component.spec.ts b/projects/aas-portal/src/test/view/view.component.spec.ts new file mode 100644 index 00000000..43ee5ab4 --- /dev/null +++ b/projects/aas-portal/src/test/view/view.component.spec.ts @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { CommonModule } from '@angular/common'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { ActivatedRoute, ActivatedRouteSnapshot } from '@angular/router'; +import { Store, StoreModule } from '@ngrx/store'; +import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core'; +import { first, of } from 'rxjs'; +import { SubmodelViewDescriptor, ViewQuery } from 'aas-lib'; +import { EffectsModule } from '@ngrx/effects'; +import { AASLibModule, ClipboardService } from 'aas-lib'; + +import { AppRoutingModule } from 'src/app/app-routing.module'; +import { viewReducer } from 'src/app/view/view.reducer'; +import { ViewState } from 'src/app/view/view.state'; +import { sampleDocument } from 'src/test/assets/sample-document'; +import { ViewComponent } from '../../app/view/view.component'; +import { ProjectService } from 'src/app/project/project.service'; + +describe('ViewComponent', () => { + let component: ViewComponent; + let fixture: ComponentFixture; + let store: Store<{ view: ViewState }>; + let project: jasmine.SpyObj; + let route: jasmine.SpyObj; + let clipboard: ClipboardService; + + beforeEach(() => { + project = jasmine.createSpyObj('ProjectService', ['getDocument']); + project.getDocument.and.returnValue(of(sampleDocument)); + + const descriptor: SubmodelViewDescriptor = { + template: 'Nameplate', + submodels: [{ + id: 'http://customer.com/aas/9175_7013_7091_9168', + url: 'C:\\Git\\aasportal\\data\\endpoints\\samples', + idShort: 'Identification' + }] + } + + route = jasmine.createSpyObj('ActivatedRoute', {}, { + snapshot: jasmine.createSpyObj( + 'ActivatedRouteSnapshot', + {}, + { + queryParams: { + format: 'ViewQuery' + } + }) + }); + + TestBed.configureTestingModule({ + declarations: [ + ViewComponent, + ], + providers: [ + { + provide: ProjectService, + useValue: project + }, + { + provide: ActivatedRoute, + useValue: route + } + ], + imports: [ + AppRoutingModule, + CommonModule, + AppRoutingModule, + AASLibModule, + EffectsModule.forRoot(), + StoreModule.forRoot( + { + view: viewReducer + }), + TranslateModule.forRoot({ + loader: { + provide: TranslateLoader, + useClass: TranslateFakeLoader + } + }) + ] + }); + + store = TestBed.inject(Store); + clipboard = TestBed.inject(ClipboardService); + clipboard.set('ViewQuery', { descriptor } as ViewQuery); + fixture = TestBed.createComponent(ViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('provides a view for a specific template view', function (done: DoneFn) { + store.select(state => state.view).pipe(first()).subscribe(state => { + expect(state.submodels[0].submodel.idShort).toEqual('Identification'); + expect(component.submodels[0].submodel.idShort).toEqual('Identification'); + done(); + }) + }); +}); \ No newline at end of file diff --git a/projects/aas-portal/tsconfig.app.json b/projects/aas-portal/tsconfig.app.json new file mode 100644 index 00000000..36c434c2 --- /dev/null +++ b/projects/aas-portal/tsconfig.app.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [ + "@angular/localize" + ] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} \ No newline at end of file diff --git a/projects/aas-portal/tsconfig.json b/projects/aas-portal/tsconfig.json new file mode 100644 index 00000000..04263165 --- /dev/null +++ b/projects/aas-portal/tsconfig.json @@ -0,0 +1,35 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "useDefineForClassFields": false, + "lib": [ + "ES2022", + "dom" + ] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } + } + \ No newline at end of file diff --git a/projects/aas-portal/tsconfig.spec.json b/projects/aas-portal/tsconfig.spec.json new file mode 100644 index 00000000..8dde0850 --- /dev/null +++ b/projects/aas-portal/tsconfig.spec.json @@ -0,0 +1,16 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine", + "node", + "@angular/localize" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} \ No newline at end of file diff --git a/projects/aas-server/.eslintrc b/projects/aas-server/.eslintrc new file mode 100644 index 00000000..c939dc42 --- /dev/null +++ b/projects/aas-server/.eslintrc @@ -0,0 +1,7 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "extends": ["plugin:@typescript-eslint/recommended"], + "parserOptions": { "ecmaVersion": 2018, "sourceType": "module" }, + "rules": {} + } \ No newline at end of file diff --git a/projects/aas-server/app-info.json b/projects/aas-server/app-info.json new file mode 100644 index 00000000..862dd3cc --- /dev/null +++ b/projects/aas-server/app-info.json @@ -0,0 +1,312 @@ +{ + "name": "aas-portal-project", + "version": "2.21.29", + "description": "Web-based visualization and control of asset administration shells.", + "author": "Fraunhofer IOSB-INA", + "homepage": "https://www.iosb-ina.fraunhofer.de/", + "license": "Apache-2.0", + "libraries": [ + { + "name": "@angular/animations", + "version": "16.1.3", + "description": "Angular - animations integration with web-animations", + "license": "MIT" + }, + { + "name": "@angular/common", + "version": "16.1.3", + "description": "Angular - commonly needed directives and services", + "license": "MIT" + }, + { + "name": "@angular/compiler", + "version": "16.1.3", + "description": "Angular - the compiler library", + "license": "MIT" + }, + { + "name": "@angular/core", + "version": "16.1.3", + "description": "Angular - the core framework", + "license": "MIT" + }, + { + "name": "@angular/forms", + "version": "16.1.3", + "description": "Angular - directives and services for creating forms", + "license": "MIT" + }, + { + "name": "@angular/localize", + "version": "16.1.3", + "description": "Angular - library for localizing messages", + "license": "MIT" + }, + { + "name": "@angular/platform-browser", + "version": "16.1.3", + "description": "Angular - library for using Angular in a web browser", + "license": "MIT" + }, + { + "name": "@angular/platform-browser-dynamic", + "version": "16.1.3", + "description": "Angular - library for using Angular in a web browser with JIT compilation", + "license": "MIT" + }, + { + "name": "@angular/router", + "version": "16.1.3", + "description": "Angular - the routing library", + "license": "MIT", + "homepage": "https://github.com/angular/angular/tree/main/packages/router" + }, + { + "name": "@ng-bootstrap/ng-bootstrap", + "version": "15.0.1", + "description": "Angular powered Bootstrap", + "license": "MIT", + "homepage": "https://github.com/ng-bootstrap/ng-bootstrap#readme" + }, + { + "name": "@ngrx/effects", + "version": "16.0.1", + "description": "Side effect model for @ngrx/store", + "license": "MIT", + "homepage": "https://github.com/ngrx/platform#readme" + }, + { + "name": "@ngrx/eslint-plugin", + "version": "16.0.1", + "description": "NgRx ESLint Plugin", + "license": "MIT", + "homepage": "https://github.com/ngrx/platform#readme" + }, + { + "name": "@ngrx/store", + "version": "16.0.1", + "description": "RxJS powered Redux for Angular apps", + "license": "MIT", + "homepage": "https://github.com/ngrx/platform#readme" + }, + { + "name": "@ngx-translate/core", + "version": "15.0.0", + "license": "SEE LICENSE IN LICENSE" + }, + { + "name": "@ngx-translate/http-loader", + "version": "8.0.0", + "license": "SEE LICENSE IN LICENSE" + }, + { + "name": "@popperjs/core", + "version": "2.11.8", + "description": "Tooltip and Popover Positioning Engine", + "license": "MIT" + }, + { + "name": "@xmldom/xmldom", + "version": "0.8.8", + "description": "A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.", + "license": "MIT", + "homepage": "https://github.com/xmldom/xmldom" + }, + { + "name": "bcryptjs", + "version": "2.4.3", + "description": "Optimized bcrypt in plain JavaScript with zero dependencies. Compatible to 'bcrypt'.", + "license": "MIT" + }, + { + "name": "body-parser", + "version": "1.20.2", + "description": "Node.js body parsing middleware", + "license": "MIT" + }, + { + "name": "bootstrap", + "version": "5.3.0", + "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", + "license": "MIT", + "homepage": "https://getbootstrap.com/" + }, + { + "name": "bootstrap-icons", + "version": "1.10.5", + "description": "Official open source SVG icon library for Bootstrap", + "license": "MIT", + "homepage": "https://icons.getbootstrap.com/" + }, + { + "name": "chart.js", + "version": "4.3.0", + "description": "Simple HTML5 charts using the canvas element.", + "license": "MIT", + "homepage": "https://www.chartjs.org" + }, + { + "name": "cookie-auth", + "version": "2.0.0", + "description": "cookie session middleware", + "license": "MIT" + }, + { + "name": "cors", + "version": "2.8.5", + "description": "Node.js CORS middleware", + "license": "MIT" + }, + { + "name": "express", + "version": "4.18.2", + "description": "Fast, unopinionated, minimalist web framework", + "license": "MIT", + "homepage": "http://expressjs.com/" + }, + { + "name": "express-fileupload", + "version": "1.4.0", + "description": "Simple express file upload middleware that wraps around Busboy", + "license": "MIT" + }, + { + "name": "form-data", + "version": "4.0.0", + "description": "A library to create readable \"multipart/form-data\" streams. Can be used to submit forms and file uploads to other web applications.", + "license": "MIT" + }, + { + "name": "jimp", + "version": "0.22.8", + "description": "An image processing library written entirely in JavaScript (i.e. zero external or native dependencies)", + "license": "MIT" + }, + { + "name": "jszip", + "version": "3.10.1", + "description": "Create, read and edit .zip files with JavaScript http://stuartk.com/jszip", + "license": "(MIT OR GPL-3.0-or-later)" + }, + { + "name": "lodash-es", + "version": "4.17.21", + "description": "Lodash exported as ES modules.", + "license": "MIT", + "homepage": "https://lodash.com/custom-builds" + }, + { + "name": "mongoose", + "version": "7.3.1", + "description": "Mongoose MongoDB ODM", + "license": "MIT", + "homepage": "https://mongoosejs.com" + }, + { + "name": "morgan", + "version": "1.10.0", + "description": "HTTP request logger middleware for node.js", + "license": "MIT" + }, + { + "name": "ngx-cookie-service", + "version": "16.0.0", + "description": "Angular cookie service", + "license": "MIT" + }, + { + "name": "node-opcua", + "version": "2.106.0", + "description": "pure nodejs OPCUA SDK - module node-opcua", + "license": "MIT", + "homepage": "http://node-opcua.github.io/" + }, + { + "name": "node-opcua-client-crawler", + "version": "2.106.0", + "description": "pure nodejs OPCUA SDK - module client-crawler", + "license": "MIT", + "homepage": "http://node-opcua.github.io/" + }, + { + "name": "nodemailer", + "version": "6.9.3", + "description": "Easy as cake e-mail sending from your Node.js applications", + "license": "MIT-0", + "homepage": "https://nodemailer.com/" + }, + { + "name": "owncloud-sdk", + "version": "3.1.0-alpha.4", + "description": "ownCloud client library for JavaScript", + "license": "MIT", + "homepage": "https://owncloud.github.io/owncloud-sdk/" + }, + { + "name": "reflect-metadata", + "version": "0.1.13", + "description": "Polyfill for Metadata Reflection API", + "license": "Apache-2.0", + "homepage": "http://rbuckton.github.io/reflect-metadata" + }, + { + "name": "rxjs", + "version": "7.8.1", + "description": "Reactive Extensions for modern JavaScript", + "license": "Apache-2.0", + "homepage": "https://rxjs.dev" + }, + { + "name": "tslib", + "version": "2.6.0", + "description": "Runtime library for TypeScript helper functions", + "license": "0BSD", + "homepage": "https://www.typescriptlang.org/" + }, + { + "name": "tsyringe", + "version": "4.8.0", + "description": "Lightweight dependency injection container for JavaScript/TypeScript", + "license": "MIT", + "homepage": "https://github.com/Microsoft/tsyringe#readme" + }, + { + "name": "uuid", + "version": "8.3.2", + "description": "RFC4122 (v1, v4, and v5) UUIDs", + "license": "MIT" + }, + { + "name": "winston", + "version": "3.9.0", + "description": "A logger for just about everything.", + "license": "MIT" + }, + { + "name": "winston-daily-rotate-file", + "version": "4.7.1", + "description": "A transport for winston which logs to a rotating file each day.", + "license": "MIT", + "homepage": "https://github.com/winstonjs/winston-daily-rotate-file#readme" + }, + { + "name": "ws", + "version": "8.13.0", + "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js", + "license": "MIT", + "homepage": "https://github.com/websockets/ws" + }, + { + "name": "xpath", + "version": "0.0.32", + "description": "DOM 3 XPath implemention and helper for node.js.", + "license": "MIT" + }, + { + "name": "zone.js", + "version": "0.13.1", + "description": "Zones for JavaScript", + "license": "MIT" + } + ] +} \ No newline at end of file diff --git a/projects/aas-server/esbuild.dev.js b/projects/aas-server/esbuild.dev.js new file mode 100644 index 00000000..3914fac6 --- /dev/null +++ b/projects/aas-server/esbuild.dev.js @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as esbuild from 'esbuild'; + +await esbuild.build({ + entryPoints: ['./src/app/aas-server.ts'], + outdir: './dist', + bundle: true, + platform: 'node', + format: 'esm', + target: 'es2022', + tsconfig: 'tsconfig.app.json', + packages: 'external' +}); + +await esbuild.build({ + entryPoints: ['./src/app/aas-scan-worker.ts'], + outdir: './dist', + bundle: true, + platform: 'node', + format: 'esm', + target: 'es2022', + tsconfig: 'tsconfig.app.json', + packages: 'external' +}); \ No newline at end of file diff --git a/projects/aas-server/esbuild.prod.js b/projects/aas-server/esbuild.prod.js new file mode 100644 index 00000000..b9fb9078 --- /dev/null +++ b/projects/aas-server/esbuild.prod.js @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as esbuild from 'esbuild'; + +await esbuild.build({ + entryPoints: ['./src/app/aas-server.ts'], + outdir: './dist', + bundle: true, + platform: 'node', + format: 'esm', + target: 'es2022', + tsconfig: 'tsconfig.app.json', + packages: 'external', + minify: true, + preserveSymlinks: false +}); + +await esbuild.build({ + entryPoints: ['./src/app/aas-scan-worker.ts'], + outdir: './dist', + bundle: true, + platform: 'node', + format: 'esm', + target: 'es2022', + tsconfig: 'tsconfig.app.json', + packages: 'external', + minify: true, + preserveSymlinks: false +}); \ No newline at end of file diff --git a/projects/aas-server/jest.config.js b/projects/aas-server/jest.config.js new file mode 100644 index 00000000..67cbbb20 --- /dev/null +++ b/projects/aas-server/jest.config.js @@ -0,0 +1,31 @@ +export default { + clearMocks: true, + collectCoverage: true, + collectCoverageFrom: [ + '/src/app/**/*.ts' + ], + coverageDirectory: '/../../reports/aas-server', + coverageReporters: ['html', 'json-summary', 'cobertura'], + extensionsToTreatAsEsm: ['.ts'], + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + preset: 'ts-jest/presets/default-esm', + rootDir: '.', + roots: ['/src/'], + testEnvironment: 'node', + testMatch: [ + '**/?(*.)+(spec|test).[tj]s?(x)' + ], + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + useESM: true, + babelConfig: { + plugins: ["babel-plugin-transform-import-meta"] + } + } + ] + } +}; diff --git a/projects/aas-server/package.json b/projects/aas-server/package.json new file mode 100644 index 00000000..0fb24f27 --- /dev/null +++ b/projects/aas-server/package.json @@ -0,0 +1,79 @@ +{ + "name": "aas-server", + "version": "2.0.0", + "author": "Fraunhofer IOSB-INA", + "license": "Apache 2.0", + "description": "Web-based visualization and control of asset administration shells.", + "module": "./dist/aas-server.js", + "homepage": "https://www.iosb-ina.fraunhofer.de/", + "type": "module", + "scripts": { + "tsoa": "tsoa spec-and-routes", + "serve": "rimraf build && npm run tsoa && tsc -p tsconfig.app.json", + "test": "node --experimental-vm-modules --no-warnings ../../node_modules/jest/bin/jest.js -c jest.config.js", + "test:debug": "node --experimental-vm-modules --no-warnings ../../node_modules/jest/bin/jest.js -c jest.config.js --runInBand --no-cache --verbose --watchAll=true", + "build": "rimraf dist && npm run tsoa && node esbuild.prod.js", + "build:debug": "rimraf dist && npm run tsoa && node esbuild.dev.js", + "tsc": "rimraf build && tsc -p tsconfig.json", + "lint": "eslint src/app/**/*.ts", + "format": "eslint src/app/**/*.ts --fix" + }, + "dependencies": { + "@xmldom/xmldom": "^0.8.10", + "bcryptjs": "^2.4.3", + "common": "2.0.0", + "cors": "^2.8.5", + "express": "^4.18.2", + "form-data": "^4.0.0", + "jimp": "^0.22.10", + "jsonwebtoken": "^9.0.1", + "jszip": "^3.10.1", + "jwt-decode": "^3.1.2", + "lodash-es": "^4.17.21", + "mongoose": "^7.4.2", + "morgan": "^1.10.0", + "multer": "^1.4.5-lts.1", + "node-opcua": "^2.108.0", + "node-opcua-client-crawler": "^2.108.0", + "nodemailer": "^6.9.4", + "owncloud-sdk": "^3.1.0-alpha.7", + "reflect-metadata": "^0.1.13", + "rxjs": "~7.8.1", + "swagger-ui-express": "^5.0.0", + "tslib": "^2.6.1", + "tsoa": "^5.1.1", + "tsyringe": "^4.8.0", + "winston": "^3.10.0", + "winston-daily-rotate-file": "^4.7.1", + "ws": "^8.13.0", + "xpath": "^0.0.33" + }, + "devDependencies": { + "@jest/globals": "^29.6.2", + "@types/bcryptjs": "^2.4.2", + "@types/cors": "^2.8.13", + "@types/express": "^4.17.17", + "@types/jquery": "^3.5.16", + "@types/jsonwebtoken": "^9.0.2", + "@types/lodash-es": "^4.17.8", + "@types/morgan": "^1.9.4", + "@types/multer": "^1.4.7", + "@types/node": "^18.16.0", + "@types/nodemailer": "^6.4.9", + "@types/supertest": "^2.0.12", + "@types/swagger-ui-express": "^4.1.3", + "@types/ws": "^8.5.5", + "@typescript-eslint/eslint-plugin": "^6.2.1", + "@typescript-eslint/parser": "^6.2.1", + "babel-plugin-transform-import-meta": "^2.2.1", + "esbuild": "^0.18.19", + "eslint": "^8.46.0", + "jest": "^29.6.2", + "ng-packagr": "^16.1.0", + "rimraf": "^5.0.1", + "supertest": "^6.3.3", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "typescript": "5.0.*" + } +} diff --git a/projects/aas-server/src/app/aas-endpoint-scan-factory.ts b/projects/aas-server/src/app/aas-endpoint-scan-factory.ts new file mode 100644 index 00000000..f7e14367 --- /dev/null +++ b/projects/aas-server/src/app/aas-endpoint-scan-factory.ts @@ -0,0 +1,57 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { AASEndpointScan } from './aas-provider/aas-endpoint-scan.js'; +import { Logger } from './logging/logger.js'; +import { getEndpointType } from './configuration.js'; +import { DirectoryEndpointScan } from './aas-provider/directory-endpoint-scan.js'; +import { AASXServerEndpointScan } from './aas-provider/aasx-server-endpoint-scan.js'; +import { ScanEndpointData } from './aas-provider/worker-data.js'; +import { AASRegistryScan } from './aas-provider/aas-registry-scan.js'; +import { OpcuaEndpointScan } from './aas-provider/opcua-endpoint-scan.js'; +import { AASResourceFactory } from './packages/aas-resource-factory.js'; +import { FileStorageFactory } from './file-storage/file-storage-factory.js'; +import { FileStorage } from './file-storage/file-storage.js'; + +@singleton() +export class AASEndpointScanFactory { + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(AASResourceFactory) private readonly resourceFactory: AASResourceFactory, + @inject(FileStorageFactory) private readonly fileStorageFactory: FileStorageFactory + ) { } + + public create(data: ScanEndpointData): AASEndpointScan { + switch (getEndpointType(data.endpoint)) { + case 'AasxDirectory': + return new DirectoryEndpointScan( + this.logger, + data.endpoint, + this.createFileStorage(data.endpoint), + data.containers); + case 'AasxServer': + return new AASXServerEndpointScan(this.logger, this.resourceFactory, data.endpoint, data.containers); + case 'AASRegistry': + return new AASRegistryScan(this.logger, data.endpoint, data.containers); + case 'OpcuaServer': + return new OpcuaEndpointScan(this.logger, data.endpoint, data.containers); + default: + throw new Error(); + } + } + + private createFileStorage(endpoint: string): FileStorage { + const url = new URL(endpoint); + if (url.protocol === 'file:') { + return this.fileStorageFactory.create('file:///endpoints' + url.pathname); + } else { + return this.fileStorageFactory.create(url); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aas-cache.ts b/projects/aas-server/src/app/aas-provider/aas-cache.ts new file mode 100644 index 00000000..dd15b3f0 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aas-cache.ts @@ -0,0 +1,171 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { getEndpointType } from '../configuration.js'; +import { ERRORS } from '../errors.js'; +import { Container } from './container.js'; +import { AASDocument, ApplicationError, AASContainer } from 'common'; + +export class AASCache { + private _containers = new Map(); + + /** All containers over all workspaces. */ + public get containers(): IterableIterator { + return this._containers.values(); + } + + public has(url: string, id: string): boolean { + const container = this._containers.get(this.getKey(url)); + if (container) { + return container.has(id); + } + + return false; + } + + public get(url: string, id: string): AASDocument { + const container = this._containers.get(this.getKey(url)); + if (container) { + const document = container.find(id); + if (document) { + return document; + } + } + + throw new ApplicationError( + `An AAS with the identification ${id} does not exist in the container '${url}'.`, + ERRORS.AASNotFound, + id, + url); + } + + public add(document: AASDocument): void { + const key = this.getKey(document.container); + const container = this._containers.get(key); + if (!container) { + throw new Error(`A container with the URL '${key}' does not exist.`); + } + + if (container.has(document.id)) { + throw new Error(`A document with the identification '${document.id}' already exists.`); + } + + container.set(document); + } + + public set(document: AASDocument): boolean { + const key = this.getKey(document.container); + const container = this._containers.get(key); + if (!container) { + throw new Error(`A container with the URL '${key}' does not exist.`); + } + + const has = container.has(document.id); + container.set(document); + return !has; + } + + public hasContainer(url: string): boolean { + return this._containers.has(this.getKey(url)); + } + + public getContainer(url: string): Container { + const key = this.getKey(url); + const container = this._containers.get(key); + if (!container) { + throw new Error(`A container with the URL '${key}' does not exist.`); + } + + return container; + } + + public deleteContainer(container: Container): boolean { + return this._containers.delete(this.getKeyFromUrl(container.url)); + } + + public addNewContainer(descriptor: AASContainer, endpoint: string): Container { + const url = this.isValidUrl(descriptor.url); + if (!url) { + throw new Error(`${descriptor.url} is an invalid URL.`); + } + + const key = this.getKeyFromUrl(url); + if (this._containers.has(key)) { + throw new ApplicationError( + `A container with the URL '${key}' already exists.`, + ERRORS.ContainerUrlAlreadyExists, + descriptor.url); + } + + const container: Container = new Container(url.href, descriptor.name, endpoint); + this._containers.set(key, container); + return container; + } + + public *select(match: (document: AASDocument) => boolean): Generator { + match = match ?? function () { return true; }; + + for (const container of this._containers.values()) { + for (const document of container.documents) { + if (match(document)) { + yield document; + } + } + } + } + + public find(match: (document: AASDocument) => boolean): AASDocument | undefined { + for (const container of this._containers.values()) { + for (const document of container.documents) { + if (match(document)) { + return document; + } + } + } + + return undefined; + } + + public delete(url: string, id: string): boolean { + let removed = false; + const container = this._containers.get(this.getKey(url)); + if (container) { + removed = container.remove(id); + } + + return removed; + } + + public reset(): void { + this._containers.clear(); + } + + private getKey(url: string): string { + return url.split('?')[0]; + } + + private getKeyFromUrl(url: URL): string { + return url.href.split('?')[0]; + } + + private isValidUrl(value: string): URL | undefined { + if (value) { + try { + const url = new URL(value); + const type = getEndpointType(url); + if (type === 'AasxServer' || type === 'OpcuaServer' || type === 'AasxDirectory' || type === 'AASRegistry') { + return url; + } + } catch (error) { + return undefined; + } + } + + return undefined; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aas-endpoint-scan.ts b/projects/aas-server/src/app/aas-provider/aas-endpoint-scan.ts new file mode 100644 index 00000000..2942e678 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aas-endpoint-scan.ts @@ -0,0 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { EventEmitter } from 'events'; + +/** Abstract base class of an AAS endpoint scan. */ +export abstract class AASEndpointScan extends EventEmitter { + + /** Scans for containers in the current endpoint. */ + public abstract scanAsync(): Promise; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aas-provider.ts b/projects/aas-server/src/app/aas-provider/aas-provider.ts new file mode 100644 index 00000000..a2f000b7 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aas-provider.ts @@ -0,0 +1,720 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { resolve, extname, isAbsolute } from 'path'; +import { existsSync, readFileSync } from 'fs'; +import { unlink, writeFile } from 'fs/promises'; +import Jimp from 'jimp'; +import { Readable } from 'stream'; +import { + AASDocument, + AASContainer, + LiveRequest, + WebSocketData, + AASServerMessage, + ApplicationError, + aas, + AASWorkspace, + isUrlSafeBase64, + selectElement +} from 'common'; + +import { ImageProcessing } from '../image-processing.js'; +import { AASCache } from './aas-cache.js'; +import { ScanResultType, ScanResult, ScanStatistic, ScanContainerResult, ScanEndpointResult } from './scan-result.js'; +import { Logger } from '../logging/logger.js'; +import { Container } from './container.js'; +import { Parallel } from './parallel.js'; +import { ScanContainerData, ScanEndpointData } from './worker-data.js'; +import { SocketClient } from '../live/socket-client.js'; +import { EmptySubscription } from '../live/empty-subscription.js'; +import { SocketSubscription } from '../live/socket-subscription.js'; +import { ERRORS } from '../errors.js'; +import { AASResourceFactory } from '../packages/aas-resource-factory.js'; +import { decodeBase64Url } from '../convert.js'; +import { AASServerConfiguration, createEndpoint, getEndpointName, getEndpointType } from '../configuration.js'; +import { AASResourceScanFactory } from './aas-resource-scan-factory.js'; +import { Variable } from '../variable.js'; +import { WSServer } from '../ws-server.js'; + +@singleton() +export class AASProvider { + private readonly configuration: AASServerConfiguration; + private readonly endpoints = new Map(); + private readonly timeout: number; + private readonly cache = new AASCache(); + private readonly file: string | undefined; + private wsServer!: WSServer; + private readonly tasks = new Map(); + + private nextTaskId = 1; + + constructor( + @inject(Variable) variable: Variable, + @inject('CONFIGURATION') configuration: string | AASServerConfiguration, + @inject('Logger') private readonly logger: Logger, + @inject(Parallel) private readonly parallel: Parallel, + @inject(AASResourceFactory) private readonly resourceFactory: AASResourceFactory + ) { + let currentEndpoints = variable.ENDPOINTS; + if (typeof configuration === 'string') { + this.configuration = { + endpoints: variable.ENDPOINTS.map(endpoint => createEndpoint(endpoint).href) + }; + + this.file = isAbsolute(configuration) ? configuration : resolve('.', configuration); + if (existsSync(this.file)) { + try { + const value: AASServerConfiguration = JSON.parse(readFileSync(this.file).toString()); + if (value) { + currentEndpoints = value.endpoints; + } + } catch (error) { + logger.error(error); + } + } + } else { + currentEndpoints = configuration.endpoints; + this.configuration = { + endpoints: variable.ENDPOINTS.map(endpoint => createEndpoint(endpoint).href) + }; + } + + this.timeout = variable.TIMEOUT; + + this.initEndpoints(currentEndpoints); + + this.parallel.on('message', this.parallelOnMessage); + this.parallel.on('end', this.parallelOnEnd); + } + + public start(wsServer: WSServer): void { + this.wsServer = wsServer; + this.wsServer.on('message', this.onClientMessage); + + setTimeout(this.startScan, 100); + } + + public getWorkspaces(): AASWorkspace[] { + const items: AASWorkspace[] = []; + for (const endpoint of this.endpoints.values()) { + const containers: AASContainer[] = []; + for (const container of this.cache.containers) { + if (container.isAssignedTo(endpoint)) { + containers.push({ + url: container.url.href, + name: container.name + }); + } + } + + items.push({ + name: getEndpointName(endpoint), + containers: containers + }); + } + + return items; + } + + public getContainer(url: string): Container { + const container = this.cache.getContainer(url); + if (!container) { + throw new Error(`A container with the URL "${url}" does not exist.`); + } + + return container; + } + + public getDocuments(url: string): AASDocument[] { + const documents: AASDocument[] = []; + for (const document of this.cache.getContainer(url).documents) { + documents.push({ ...document, content: document.content ? null : undefined }) + } + + return documents; + } + + public getDocument(id: string, url?: string): AASDocument { + let document: AASDocument | undefined; + if (url) { + document = this.cache.get(url, id); + } else { + let decodedId: string | undefined; + try { + if (isUrlSafeBase64(id)) { + decodedId = decodeBase64Url(id); + } + } catch (_) { } + + document = this.cache.find((document) => document.id === id || document.idShort === id || document.id === decodedId); + } + + if (!document) { + throw new Error(`An AAS with the identification ${id} does not exist.`); + } + + return { ...document, content: document.content ? null : undefined }; + } + + public async getContentAsync(url: string, id: string): Promise { + const document: AASDocument = this.cache.get(url, id); + if (!document.content) { + throw new Error(`${id} has an unexpected empty content.`); + } + + return document.content; + } + + public async getThumbnailAsync(url: string, id: string): Promise { + const document: AASDocument = this.cache.get(url, id); + const source = this.resourceFactory.create(document.container); + try { + await source.openAsync(); + const pkg = source.createPackage(document.endpoint.address); + return await pkg.getThumbnailAsync(); + } finally { + await source.closeAsync(); + } + } + + public async getDataElementValueAsync( + url: string, + id: string, + smId: string, + path: string, + options?: object + ): Promise { + const document = this.cache.get(url, id); + if (!document.content) { + throw new Error('Invalid operation.') + } + + let stream: NodeJS.ReadableStream; + const source = this.resourceFactory.create(document.container); + try { + await source.openAsync(); + const pkg = source.createPackage(document.endpoint.address); + const dataElement: aas.DataElement | undefined = selectElement(document.content, smId, path); + if (!dataElement) { + throw new Error('DataElement not found.'); + } + + if (dataElement.modelType === 'File') { + const file = dataElement as aas.File; + stream = await pkg.openReadStreamAsync(document.content, file); + const extension = file.value ? extname(file.value).toLowerCase() : ''; + const imageOptions = options as { width?: number, height?: number }; + if (file.contentType.startsWith('image/')) { + if (imageOptions?.width || imageOptions?.height) { + stream = await ImageProcessing.resizeAsync(stream, imageOptions.width, imageOptions.height); + } + + if (extension === '.tiff' || extension === '.tif') { + stream = await ImageProcessing.convertAsync(stream, Jimp.MIME_PNG); + } + } + } else if (dataElement.modelType === 'Blob') { + const value = await source.getBlobValueAsync(document.content, smId, path); + const readable = new Readable(); + readable.push(value); + readable.push(null); + stream = readable; + } else { + throw new Error('Not implemented'); + } + } finally { + await source.closeAsync(); + } + + return stream; + } + + /** + * Adds a new endpoint. + * @param name The endpoint name. + * @param url The endpoint URL. + */ + public async addEndpointAsync(name: string, url: URL): Promise { + if (this.endpoints.has(name)) { + throw new ApplicationError( + `An endpoint with the name "${name}" already exists.`, + ERRORS.RegistryAlreadyExists, + name); + } + + await this.resourceFactory.testAsync(url); + + this.endpoints.set(name, url); + + if (this.file) { + await this.saveAsync(this.file); + } + + this.wsServer.notify('WorkspaceChanged', { + type: 'AASServerMessage', + data: { + type: 'EndpointAdded', + endpoint: url.href, + } as AASServerMessage, + }); + + this.startEndpointScan(this.createTaskId(), url, this.createScanStatistic()); + } + + /** + * Removes the endpoint with the specified name. + * @param name The name of the registry to remove. + */ + public async removeEndpointAsync(name: string): Promise { + const endpoint = this.endpoints.get(name); + if (!endpoint) { + throw new Error(`An endpoint with the name '${name}' does not exist.`); + } + + this.endpoints.delete(name); + + for (const container of [...this.cache.containers]) { + if (container.isAssignedTo(endpoint) && container.unassignFrom(endpoint)) { + this.cache.deleteContainer(container); + + this.logger.info(`Container '${container}' removed.`); + this.wsServer.notify('WorkspaceChanged', { + type: 'AASServerMessage', + data: { + type: 'ContainerRemoved', + endpoint: endpoint.href, + container: { name: container.name, url: container.url.href } + } as AASServerMessage, + }); + } + } + + this.wsServer.notify('WorkspaceChanged', { + type: 'AASServerMessage', + data: { + type: 'EndpointRemoved', + endpoint: endpoint.href, + } as AASServerMessage, + }); + + if (this.file) { + await this.saveAsync(this.file); + } + } + + /** + * Restores the default AAS server configuration. + */ + public async resetAsync(): Promise { + this.cache.reset(); + this.tasks.clear(); + this.initEndpoints(this.configuration.endpoints); + + if (this.file && existsSync(this.file)) { + await unlink(this.file); + } + + this.wsServer.notify('WorkspaceChanged', { + type: 'AASServerMessage', + data: { + type: 'Reset', + } as AASServerMessage, + }); + + this.startScan(); + this.logger.info('AAS Server configuration restored.'); + } + + /** + * Updates an Asset Administration Shell. + * @param url The AAS container URL. + * @param id The AAS document ID. + * @param content The new document content. + * @returns + */ + public async updateDocumentAsync(url: string, id: string, content: aas.Environment): Promise { + const container = this.cache.getContainer(url); + const document = container.find(id); + if (!document) { + throw new Error(`The destination document ${id} is not available.`); + } + + const source = this.resourceFactory.create(document.container); + try { + await source.openAsync(); + const pkg = source.createPackage(document.endpoint.address); + return await pkg.commitDocumentAsync(document, content); + } + finally { + await source.closeAsync(); + } + } + + /** + * Downloads an AASX package. + * @param id The AAS identifier. + * @param url The source URL. + * @returns A readable stream. + */ + public async getDocumentAsync(id: string, url: string): Promise { + const document = this.cache.get(url, id); + const source = this.resourceFactory.create(document.container); + try { + await source.openAsync(); + return await source.getPackageAsync(id, document.endpoint.address); + } finally { + await source.closeAsync(); + } + } + + /** + * Uploads an AASX package. + * @param files The AASX package file. + * @param url The destination URL. + */ + public async addDocumentsAsync(url: string, files: Express.Multer.File[]): Promise { + if (!this.cache.hasContainer(url)) { + throw new Error(`The AAS container "${url}" does not exist.`); + } + + const source = this.resourceFactory.create(url); + try { + await source.openAsync(); + for (const file of files) { + const aasPackage = await source.postPackageAsync(file); + if (aasPackage) { + const document = await aasPackage.createDocumentAsync(); + this.cache.add(document); + this.notify({ type: 'Added', document: { ...document, content: null } }); + } + } + } finally { + await source.closeAsync(); + } + } + + /** + * Deletes an AASX package from an endpoint. + * @param url The container URL. + * @param id The AAS identification. + */ + public async deleteDocumentAsync(url: string, id: string): Promise { + const container = this.cache.getContainer(url); + const document = container.get(id); + if (document) { + const source = this.resourceFactory.create(url); + try { + await source.deletePackageAsync(document.id, document.endpoint.address); + container.remove(id); + this.notify({ type: 'Removed', document: { ...document, content: null } }); + } finally { + await source.closeAsync(); + } + } + } + + /** Only used for test. */ + public async scanAsync(factory: AASResourceScanFactory): Promise { + for (const endpoint of this.endpoints.values()) { + if (getEndpointType(endpoint) === 'AasxDirectory') { + const descriptor: AASContainer = { + name: getEndpointName(endpoint), + url: endpoint.href, + documents: [] + }; + + this.cache.addNewContainer(descriptor, endpoint.href); + const documents = await factory.create(endpoint.href).scanAsync(); + documents.forEach(document => this.cache.add(document)); + } + } + } + + /** + * Invokes an operation synchronous. + * @param url The URL of the AAS container. + * @param id The AAS identifier. + * @param operation The Operation element. + * @returns ToDo. + */ + public async invoke(url: string, id: string, operation: aas.Operation): Promise { + const document = this.cache.get(url, id); + const resource = this.resourceFactory.create(document.container); + try { + await resource.openAsync(); + return await resource.invoke(document.content!, operation); + } finally { + await resource.closeAsync() + } + } + + private initEndpoints(endpoints: string[]): void { + this.endpoints.clear(); + endpoints.forEach(item => { + try { + const url = new URL(item); + const name = getEndpointName(url); + if (!this.endpoints.has(name)) { + this.endpoints.set(name, url); + } else { + this.logger.error(`An endpoint with the name "${name}" already exists.`); + } + } catch (error) { + this.logger.error(`"${item}" is an invalid endpoint URL.`); + } + }); + } + + private onClientMessage = async (data: WebSocketData, client: SocketClient): Promise => { + try { + switch (data.type) { + case 'LiveRequest': + client.subscribe(data.type, await this.createSubscription(data.data as LiveRequest, client)); + break; + case 'WorkspaceChanged': + client.subscribe(data.type, new EmptySubscription()); + break; + default: + throw new Error(`'${data.type}' is an unsupported Websocket message type.`); + } + } catch (error) { + this.logger.error(error); + } + }; + + private async createSubscription(message: LiveRequest, client: SocketClient): Promise { + const source = this.resourceFactory.create(message.url); + const env = this.cache.get(message.url, message.id!).content!; + await source.openAsync(); + return source.createSubscription(client, message, env); + } + + private startScan = async (): Promise => { + try { + for (const endpoint of this.endpoints.values()) { + this.startEndpointScan(this.createTaskId(), endpoint, this.createScanStatistic()); + } + } catch (error) { + this.logger.error(error); + } + }; + + private parallelOnEnd = (result: ScanResult): void => { + const task = this.tasks.get(result.taskId); + if (task) { + this.tasks.delete(result.taskId); + if (task.type === 'ScanContainer') { + if (this.cache.hasContainer(task.id)) { + const container = this.cache.getContainer(task.id); + setTimeout(this.startContainerScan.bind(this), this.timeout, result.taskId, container, result.statistic); + } + } else if (task.type === 'ScanEndpoint') { + const endpoint = this.endpoints.get(task.id); + if (endpoint) { + setTimeout(this.startEndpointScan.bind(this), this.timeout, result.taskId, endpoint, result.statistic); + } + } + } + + if (result.messages) { + this.logger.start(`scan ${task?.id ?? 'undefined'}`); + result.messages.forEach(message => this.logger.log(message)); + this.logger.stop(); + } + }; + + private startEndpointScan(taskId: number, endpoint: URL, statistic: ScanStatistic) { + const containers: AASContainer[] = []; + for (const container of this.cache.containers) { + if (container.isAssignedTo(endpoint)) { + containers.push({ + url: container.url.href, + name: container.name + }) + } + } + + const data: ScanEndpointData = { + type: 'ScanEndpointData', + taskId: taskId, + statistic: statistic, + endpoint: endpoint.href, + containers: containers + }; + + this.tasks.set(taskId, { id: getEndpointName(endpoint), type: 'ScanEndpoint' }); + this.parallel.execute(data); + } + + private startContainerScan(taskId: number, container: Container, statistic: ScanStatistic) { + const data: ScanContainerData = { + type: 'ScanContainerData', + taskId: taskId, + statistic: statistic, + container: { + url: container.url.href, + name: container.name, + documents: [...container.documents] + } + }; + + this.tasks.set(taskId, { id: container.url.href, type: 'ScanContainer' }); + this.parallel.execute(data); + } + + private notify(data: AASServerMessage): void { + this.wsServer.notify('WorkspaceChanged', + { + type: 'AASServerMessage', + data: data + }); + } + + private parallelOnMessage = (result: ScanResult) => { + try { + switch (result.type) { + case ScanResultType.Changed: + this.onChanged(result as ScanContainerResult); + break; + case ScanResultType.Added: + this.onAdded(result as ScanContainerResult); + break; + case ScanResultType.Removed: + this.onRemoved(result as ScanContainerResult); + break; + case ScanResultType.Offline: + this.onOffline(result as ScanContainerResult); + break; + case ScanResultType.ContainerAdded: + this.onContainerAdded(result as ScanEndpointResult); + break; + case ScanResultType.ContainerRemoved: + this.onContainerRemoved(result as ScanEndpointResult); + break; + } + } catch (error) { + this.logger.error(error); + } + }; + + private onChanged(result: ScanContainerResult): void { + if (!this.cache.set(result.document)) { + this.logger.info(`Changed: AAS ${result.document.idShort} [${result.document.id}] in ${result.container.url}`); + } else { + this.logger.error(`AAS ${result.document.idShort} [${result.document.id}] in ${result.container.url} does not exist.`); + } + + this.sendMessage({ type: 'Changed', document: { ...result.document, content: null } }); + } + + private onAdded(result: ScanContainerResult): void { + if (this.cache.set(result.document)) { + this.logger.info(`Added: AAS ${result.document.idShort} [${result.document.id}] in ${result.container.url}`); + } else { + this.logger.error( + `AAS ${result.document.idShort} [${result.document.id}] in ${result.container.url} already added.`); + } + + this.sendMessage({ type: 'Added', document: { ...result.document, content: result.document ? null : undefined } }); + } + + private onRemoved(result: ScanContainerResult): void { + this.cache.delete(result.container.url, result.document.id); + this.logger.info(`Removed: AAS ${result.document.idShort} [${result.document.id}] in ${result.container.url}`); + this.sendMessage({ type: 'Removed', document: { ...result.document, content: null } }); + } + + private onOffline(result: ScanContainerResult): void { + const reference = this.cache.get(result.container.url, result.document.id); + reference.content = undefined; + this.sendMessage({ type: 'Offline', document: { ...result.document, content: undefined } }); + } + + private onContainerAdded(result: ScanEndpointResult): void { + const url = new URL(result.endpoint); + const name = getEndpointName(url); + if (this.endpoints.has(name)) { + if (this.cache.hasContainer(result.container.url)) { + this.cache.getContainer(result.container.url).assignTo(url); + } else { + const container = this.cache.addNewContainer(result.container, result.endpoint); + setTimeout( + this.startContainerScan.bind(this), + this.timeout, + this.createTaskId(), + container, + this.createScanStatistic() + ); + } + + this.sendMessage({ type: 'ContainerAdded', endpoint: result.endpoint, container: result.container }); + } + } + + private onContainerRemoved(result: ScanEndpointResult): void { + if (this.cache.hasContainer(result.container.url)) { + this.cache.deleteContainer(this.cache.getContainer(result.container.url)); + } + + this.sendMessage({ type: 'ContainerRemoved', endpoint: result.endpoint, container: result.container }); + } + + private sendMessage(data: AASServerMessage) { + this.wsServer.notify('WorkspaceChanged', { + type: 'AASServerMessage', + data: data + }); + } + + private async getAASDocumentAsync(reference: aas.Key): Promise { + const document = await this.selectDocumentAsync((document) => { + return document.idShort === reference.value || document.id === reference.value; + }); + + if (!document) { + throw new Error(`An AAS with the identification '${reference.value}' does not exist.`); + } + + return document; + } + + private async selectDocumentAsync(func: (document: AASDocument) => boolean): Promise { + return this.cache.find(func); + } + + private createTaskId(): number { + const taskId = this.nextTaskId; + ++this.nextTaskId; + return taskId; + } + + private async saveAsync(path: string): Promise { + const configuration: AASServerConfiguration = { + endpoints: [...this.endpoints.values()].map(item => item.href) + }; + + await writeFile(path, JSON.stringify(configuration)); + } + + private createScanStatistic(): ScanStatistic { + return { + start: 0, + end: 0, + counter: 0, + changed: 0, + new: 0, + deleted: 0, + offline: 0, + }; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aas-registry-scan.ts b/projects/aas-server/src/app/aas-provider/aas-registry-scan.ts new file mode 100644 index 00000000..237df081 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aas-registry-scan.ts @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASContainer } from 'common'; +import { Logger } from '../logging/logger.js'; +import { AASEndpointScan } from './aas-endpoint-scan.js'; +import { ServerMessage } from '../packages/server-message.js'; +import { createEndpoint } from '../configuration.js'; +import { AssetAdministrationShellDescriptor } from 'registry.js'; + +export class AASRegistryScan extends AASEndpointScan { + private readonly registry = new ServerMessage(); + private readonly url: URL; + + constructor( + private readonly logger: Logger, + private readonly endpoint: string, + private readonly containers: AASContainer[]) { + super(); + + this.url = new URL(endpoint.split('?')[0]); + } + + public async scanAsync(): Promise { + try { + const descriptors = await this.getAASDescriptorsAsync(); + this.computeDifference(descriptors); + } catch (error) { + this.logger.debug(`AAS registry not available: ${error?.message}`); + } + } + + private computeDifference(descriptors: AssetAdministrationShellDescriptor[]): void { + const current = new Map(this.containers.map(item => [item.url, item])); + const reference = new Map(); + for (const descriptor of descriptors) { + let url: string | undefined; + switch (descriptor.endpoints[0].type) { + case 'http': + url = this.containerUrl(descriptor.endpoints[0].address); + break; + case 'opc': + url = descriptor.endpoints[0].address; + break; + default: + throw new Error(`'${descriptor.endpoints[0].type}' is a not supported endpoint type.`); + } + + if (url) { + const container = reference.get(url); + if (!container) { + reference.set(url, { url: url, name: '' }); + } + } + } + + for (const entry of reference) { + if (!current.has(entry[0])) { + this.emit('added', this.endpoint, entry[1]); + } + } + + for (const entry of current) { + if (!reference.has(entry[0])) { + this.emit('removed', this.endpoint, entry[1]); + } + } + } + + private containerUrl(value: string): string | undefined { + try { + return createEndpoint(value).href; + } catch (error) { + this.logger.error(`'${value}' is an invalid URL.`); + return undefined; + } + } + + private async getAASDescriptorsAsync(): Promise { + const obj = await this.registry.get(this.url); + const descriptors = Array.isArray(obj) ? obj : [obj]; + return descriptors.filter(d => d.endpoints.length > 0); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aas-resource-scan-factory.ts b/projects/aas-server/src/app/aas-provider/aas-resource-scan-factory.ts new file mode 100644 index 00000000..87b72b6d --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aas-resource-scan-factory.ts @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { AASResourceScan } from './aas-resource-scan.js'; +import { Logger } from '../logging/logger.js'; +import { DirectoryScan } from './directory-scan.js'; +import { AASXServerScan } from './aasx-server-scan.js'; +import { OpcuaServerScan } from './opcua-server-scan.js'; +import { parseUrl } from '../convert.js'; +import { OpcuaServer } from '../packages/opcua/opcua-server.js'; +import { AasxDirectory } from '../packages/aasx-directory/aasx-directory.js'; +import { AasxServer } from '../packages/aasx-server/aasx-server.js'; +import { AasxServerV3 } from '../packages/aasx-server/aasx-server-v3.js'; +import { AasxServerV0 } from '../packages/aasx-server/aasx-server-v0.js'; +import { FileStorageFactory } from '../file-storage/file-storage-factory.js'; +import { FileStorage } from '../file-storage/file-storage.js'; + +@singleton() +export class AASResourceScanFactory { + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(FileStorageFactory) private readonly fileStorageFactory: FileStorageFactory + ) { + } + + public create(url: string | URL): AASResourceScan { + const temp = typeof url === 'string' ? parseUrl(url) : url; + switch (temp.protocol) { + case 'http:': + case 'https': + const version = temp.searchParams.get('version')?.toLowerCase() ?? '3.0'; + let source: AasxServer; + if (version === '3.0') { + source = new AasxServerV3(this.logger, temp); + } else if (version === '0.0') { + source = new AasxServerV0(this.logger, temp); + } else { + throw new Error('Not implemented.'); + } + + return new AASXServerScan(this.logger, source); + case 'opc.tcp:': + return new OpcuaServerScan(this.logger, new OpcuaServer(this.logger, temp)); + case 'file:': + return new DirectoryScan( + this.logger, + new AasxDirectory(this.logger, temp, this.createLocalFileStorage(temp))); + default: + throw new Error('Not implemented.'); + } + } + + private createLocalFileStorage(url: URL): FileStorage { + return this.fileStorageFactory.create(`file:///endpoints` + url.pathname); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aas-resource-scan.ts b/projects/aas-server/src/app/aas-provider/aas-resource-scan.ts new file mode 100644 index 00000000..8fa317b3 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aas-resource-scan.ts @@ -0,0 +1,17 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import EventEmitter from "events"; +import { AASDocument } from "common"; + +/** Defines an automate to scan an AAS resource for Asset Administration Shells. */ +export abstract class AASResourceScan extends EventEmitter { + + /** Gets all documents of the current container. */ + public abstract scanAsync(): Promise; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aasx-server-endpoint-scan.ts b/projects/aas-server/src/app/aas-provider/aasx-server-endpoint-scan.ts new file mode 100644 index 00000000..227f7970 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aasx-server-endpoint-scan.ts @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASContainer } from "common"; +import { Logger } from "../logging/logger.js"; +import { AASResourceFactory } from "../packages/aas-resource-factory.js"; +import { AASEndpointScan } from "./aas-endpoint-scan.js"; +import { getEndpointName } from '../configuration.js'; + +export class AASXServerEndpointScan extends AASEndpointScan { + constructor( + private readonly logger: Logger, + private readonly resourceFactory: AASResourceFactory, + private endpoint: string, + private containers: AASContainer[] + ) { + super(); + } + + public async scanAsync(): Promise { + const server = this.resourceFactory.create(this.endpoint); + try { + await server.openAsync(); + const url = new URL(this.endpoint); + if (this.containers.length === 0) { + const container: AASContainer = { + url: url.href, + name: getEndpointName(url) + }; + + this.emit('added', this.endpoint, container); + } + } catch (error) { + if (this.containers.length > 0) { + this.emit('removed', this.endpoint, this.containers[0]); + } + } finally { + await server.closeAsync(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/aasx-server-scan.ts b/projects/aas-server/src/app/aas-provider/aasx-server-scan.ts new file mode 100644 index 00000000..21196afe --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/aasx-server-scan.ts @@ -0,0 +1,47 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument } from "common"; +import { Logger } from "../logging/logger.js"; +import { AasxServer } from "../packages/aasx-server/aasx-server.js"; +import { AasxServerPackage } from "../packages/aasx-server/aasx-server-package.js"; +import { AASResourceScan } from "./aas-resource-scan.js"; + +export class AASXServerScan extends AASResourceScan { + private readonly logger: Logger; + private readonly server: AasxServer; + + constructor(logger: Logger, server: AasxServer) { + super(); + + this.logger = logger; + this.server = server; + } + + public async scanAsync(): Promise { + try { + await this.server.openAsync(); + const documents: AASDocument[] = []; + const listAAS = await this.server.getShellsAsync(); + for (const idShort of listAAS) { + try { + const aasxPackage = new AasxServerPackage(this.logger, this.server, idShort); + const document = await aasxPackage.createDocumentAsync(); + documents.push(document); + this.emit('scanned', document); + } catch (error) { + this.emit('error', error, this.server, idShort); + } + } + + return documents; + } finally { + await this.server.closeAsync(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/container.ts b/projects/aas-server/src/app/aas-provider/container.ts new file mode 100644 index 00000000..0992d437 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/container.ts @@ -0,0 +1,112 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, isUrlSafeBase64 } from 'common'; +import { decodeBase64Url } from '../convert.js'; +import { getEndpointName } from '../configuration.js'; + +/** A container of Asset Administration Shells. */ +export class Container { + private readonly _documents = new Map(); + + constructor( + url: string, + name: string, + configurationEndpoint: string) { + + this.url = new URL(url); + this.name = name; + this.configurationEndpoints = [configurationEndpoint]; + } + + public readonly url: URL; + + public readonly name: string; + + public readonly configurationEndpoints: string[]; + + /** The AAS documents. */ + public get documents(): IterableIterator { + return this._documents.values(); + } + + public has(id: string): boolean { + return this._documents.has(id); + } + + public find(id: string): AASDocument | undefined { + let document = this._documents.get(id); + if (!document) { + let decodedId: string | undefined; + try { + if (isUrlSafeBase64(id)) { + decodedId = decodeBase64Url(id); + } + } catch (_) { } + + for (const item of this._documents.values()) { + if (item.idShort === id || item.id === decodedId) { + document = item; + break; + } + } + } + + return document; + } + + public get(id: string): AASDocument { + const document = this._documents.get(id); + if (!document) { + throw new Error(`An AAS with the identification '${id}' does not exist.`); + } + + return document; + } + + public set(aas: AASDocument): void { + this._documents.set(aas.id, aas); + } + + public remove(id: string): boolean { + return this._documents.delete(id); + } + + public toString(): string { + return `URL = ${this.url.href}`; + } + + public isAssignedTo(configurationEndpoint: URL): boolean { + const name = getEndpointName(configurationEndpoint); + return this.configurationEndpoints.some(item => getEndpointName(item) === name); + } + + public assignTo(configurationEndpoint: URL): void { + this.configurationEndpoints.push(configurationEndpoint.href); + } + + public unassignFrom(configurationEndpoint: URL): boolean { + const name = getEndpointName(configurationEndpoint); + const index = this.configurationEndpoints.findIndex(item => getEndpointName(item) === name); + if (index >= 0) { + this.configurationEndpoints.splice(index, 1); + } + + return this.configurationEndpoints.length === 0; + } + + private findByIdShort(idShort: string): AASDocument | undefined { + for (const item of this._documents.values()) { + if (item.idShort === idShort) { + return item; + } + } + + return undefined; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/directory-endpoint-scan.ts b/projects/aas-server/src/app/aas-provider/directory-endpoint-scan.ts new file mode 100644 index 00000000..92ac3c23 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/directory-endpoint-scan.ts @@ -0,0 +1,42 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASContainer } from "common"; +import { FileStorage } from "../file-storage/file-storage.js"; +import { Logger } from "../logging/logger.js"; +import { AASEndpointScan } from "./aas-endpoint-scan.js"; +import { getEndpointName } from '../configuration.js'; + +export class DirectoryEndpointScan extends AASEndpointScan { + + constructor( + private readonly logger: Logger, + private readonly endpoint: string, + private readonly fileStorage: FileStorage, + private readonly containers: AASContainer[]) { + super(); + } + + public async scanAsync(): Promise { + if (await this.fileStorage.exists('.')) { + if (this.containers.length === 0) { + const url = new URL(this.endpoint); + const container: AASContainer = { + url: url.href, + name: getEndpointName(url) + }; + + this.emit('added', this.endpoint, container); + } + } else { + if (this.containers.length > 0) { + this.emit('removed', this.endpoint, this.containers[0]); + } + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/directory-scan.ts b/projects/aas-server/src/app/aas-provider/directory-scan.ts new file mode 100644 index 00000000..3afd0aed --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/directory-scan.ts @@ -0,0 +1,49 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument } from 'common'; +import { Logger } from '../logging/logger.js'; +import { AasxPackage } from '../packages/aasx-directory/aasx-package.js'; +import { AasxDirectory } from '../packages/aasx-directory/aasx-directory.js'; +import { extname } from 'path'; +import { AASResourceScan } from './aas-resource-scan.js'; + +export class DirectoryScan extends AASResourceScan { + constructor( + private readonly logger: Logger, + private readonly source: AasxDirectory + ) { + super(); + } + + public async scanAsync(): Promise { + try { + await this.source.openAsync() + const files = await this.source.getStorage().readdir('.'); + const documents: AASDocument[] = []; + + for (const file of files) { + try { + const extension = extname(file); + if (extension === '.aasx') { + const aasxPackage = new AasxPackage(this.logger, this.source, file); + const document = await aasxPackage.createDocumentAsync(); + documents.push(document); + this.emit('scanned', document); + } + } catch (error) { + this.emit('error', error, this.source, file); + } + } + + return documents; + } finally { + await this.source.closeAsync(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/opcua-endpoint-scan.ts b/projects/aas-server/src/app/aas-provider/opcua-endpoint-scan.ts new file mode 100644 index 00000000..4a9ce6e4 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/opcua-endpoint-scan.ts @@ -0,0 +1,44 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASContainer } from "common"; +import { Logger } from "../logging/logger.js"; +import { OpcuaServer } from "../packages/opcua/opcua-server.js"; +import { AASEndpointScan } from "./aas-endpoint-scan.js"; +import { getEndpointName } from '../configuration.js'; + +export class OpcuaEndpointScan extends AASEndpointScan { + constructor( + private readonly logger: Logger, + private readonly endpoint: string, + private readonly containers: AASContainer[]) { + super(); + } + + public async scanAsync(): Promise { + const source = new OpcuaServer(this.logger, this.endpoint); + try { + await source.openAsync(); + if (this.containers.length === 0) { + const url = new URL(this.endpoint); + const container: AASContainer = { + url: url.href, + name: getEndpointName(url) + }; + + this.emit('added', this.endpoint, container); + } + } catch (error) { + if (this.containers.length > 0) { + this.emit('removed', this.endpoint, this.containers[0]); + } + } finally { + await source.closeAsync(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/opcua-server-scan.ts b/projects/aas-server/src/app/aas-provider/opcua-server-scan.ts new file mode 100644 index 00000000..5097bb21 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/opcua-server-scan.ts @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AttributeIds, BrowseDescriptionLike, QualifiedName, ReferenceDescription } from 'node-opcua'; +import { AASDocument } from 'common'; +import { Logger } from '../logging/logger.js'; +import { OpcuaDataTypeDictionary } from '../packages/opcua/opcua-data-type-dictionary.js'; +import { OpcuaServer } from '../packages/opcua/opcua-server.js'; +import { OpcuaPackage } from '../packages/opcua/opcua-package.js'; +import { AASResourceScan } from './aas-resource-scan.js'; + +export class OpcuaServerScan extends AASResourceScan { + private readonly logger: Logger; + private readonly server: OpcuaServer; + + constructor(logger: Logger, server: OpcuaServer) { + super(); + + this.logger = logger; + this.server = server; + } + + public async scanAsync(): Promise { + try { + await this.server.openAsync(); + const documents: AASDocument[] = []; + const dataTypes = new OpcuaDataTypeDictionary(); + await dataTypes.initializeAsync(this.server.getSession()); + for (const description of await this.browseAsync('ObjectsFolder')) { + const nodeId = description.nodeId.toString(); + try { + const opcuaPackage = new OpcuaPackage(this.logger, this.server, nodeId, dataTypes); + const document = await opcuaPackage.createDocumentAsync(); + documents.push(document); + this.emit('scanned', document); + } catch (error) { + this.emit('error', error, this.server, nodeId); + } + } + + return documents; + } finally { + await this.server.closeAsync(); + } + } + + private async browseAsync(nodeToBrowse: BrowseDescriptionLike, descriptions: ReferenceDescription[] = []): Promise { + const session = this.server.getSession(); + const result = await session.browse(nodeToBrowse); + if (result.references) { + for (const obj of result.references) { + if (await this.isAASTypeAsync(obj)) { + descriptions.push(obj); + } else if (await this.isFolderAsync(obj)) { + await this.browseAsync(obj.nodeId.toString(), descriptions); + } + } + } + + return descriptions; + } + + private async isFolderAsync(obj: ReferenceDescription): Promise { + const type = (await this.readQualifiedName(obj)).name; + return type === 'FolderType' || type === 'AASEnvironmentType' + } + + private async isAASTypeAsync(obj: ReferenceDescription): Promise { + return (await this.readQualifiedName(obj))?.name === 'AASAssetAdministrationShellType'; + } + + private async readQualifiedName(obj: ReferenceDescription): Promise { + const node = await (this.server.getSession()).read( + { + nodeId: obj.typeDefinition, + attributeId: AttributeIds.BrowseName + }); + + return node.value.value as QualifiedName; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/parallel.ts b/projects/aas-server/src/app/aas-provider/parallel.ts new file mode 100644 index 00000000..e0ddfe42 --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/parallel.ts @@ -0,0 +1,171 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { EventEmitter } from "events"; +import { noop } from "lodash-es"; +import { Worker, SHARE_ENV } from "worker_threads"; +import fs from 'fs'; +import path from 'path'; + +import { ScanResultType, ScanResult } from "./scan-result.js"; +import { WorkerData } from "./worker-data.js"; +import { Logger } from "../logging/logger.js"; +import { Variable } from '../variable.js'; + +/** Represents a worker task for scanning a container. */ +class WorkerTask extends EventEmitter { + private _worker?: Worker; + + constructor(data: WorkerData) { + super(); + + this.data = data; + } + + public readonly data: WorkerData; + + public get worker(): Worker | undefined { + return this._worker; + } + + public execute(worker: Worker) { + this._worker = worker; + + worker.on("message", this.workerOnMessage); + worker.on("error", this.workerOnError); + worker.on("exit", this.workerOnExit); + worker.postMessage(this.data); + } + + public destroy(): void { + this.removeAllListeners(); + if (this._worker) { + this._worker.off("message", this.workerOnMessage); + this._worker.off("exit", this.workerOnExit); + this._worker.off("error", this.workerOnError); + } + } + + private workerOnMessage = (value: Uint8Array) => { + const result: ScanResult = JSON.parse(Buffer.from(value).toString()); + if (result.type === ScanResultType.End) { + this.emit("end", this, result); + } else { + this.emit("message", result); + } + } + + private workerOnError = (error: Error) => { + this.emit("error", error, this); + } + + private workerOnExit = (code: number) => { + this.emit("exit", code, this); + } +} + +/** Provides a pool of worker threads. */ +@singleton() +export class Parallel extends EventEmitter { + private readonly script: string; + private readonly waiting = new Array(); + private readonly pool = new Map(); + + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(Variable) private readonly variable: Variable + ) { + super(); + this.script = path.resolve(this.variable.CONTENT_ROOT ?? './', 'aas-scan-worker.js'); + if (fs.existsSync(this.script)) { + for (let i = 0; i < this.variable.MAX_WORKERS; i++) { + this.pool.set(new Worker(this.script, { env: SHARE_ENV }), true); + } + } else { + this.logger.error(`${this.script} does not exist.`); + } + } + + /** + * Executes a new task in parallel. + * @param data The task data. + */ + public execute(data: WorkerData): void { + const task = new WorkerTask(data); + task.on("message", this.taskOnMessage.bind(this)); + task.on("end", this.taskOnEnd.bind(this)); + task.on("error", this.taskOnError.bind(this)); + + const worker = this.nextWorker(); + if (worker) { + task.execute(worker); + } else { + this.waiting.push(task); + } + } + + private nextWorker(): Worker | undefined { + for (const entry of this.pool) { + if (entry[1] === true) { + this.pool.set(entry[0], false); + return entry[0]; + } + } + + return undefined; + } + + private taskOnMessage(result: ScanResult) { + this.emit("message", result); + } + + private taskOnEnd(task: WorkerTask, result: ScanResult) { + this.emit("end", result); + + if (task) { + const worker = task.worker; + task.destroy(); + if (worker) { + if (this.waiting.length > 0) { + const nextTask = this.waiting.shift(); + if (nextTask) { + nextTask.execute(worker); + } + } else { + this.pool.set(worker, true); + } + } + } + } + + private taskOnError(error: Error, task: WorkerTask): void { + this.logger.error(error); + + try { + if (task) { + task.destroy(); + if (task.worker) { + this.pool.delete(task.worker) + } + + const index = this.waiting.indexOf(task); + if (index >= 0) { + this.waiting.splice(index, 1); + } + + while (this.pool.size < this.variable.MAX_WORKERS) { + this.pool.set(new Worker(this.script, { env: SHARE_ENV }), true); + } + } + } + catch (error) { + noop(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/scan-result.ts b/projects/aas-server/src/app/aas-provider/scan-result.ts new file mode 100644 index 00000000..bb65383b --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/scan-result.ts @@ -0,0 +1,76 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, AASContainer, Message } from "common"; + +export enum ScanResultType { + Added, + Removed, + Changed, + Offline, + ContainerAdded, + ContainerRemoved, + End +} + +/** Provides statistic information about a container scan. */ +export interface ScanStatistic { + /** Start time. */ + start: number; + /** End time */ + end: number, + /** The number of scan cycles. */ + counter: number, + /** The number of changed AAS documents.*/ + changed: number, + /** The number of new AAS documents. */ + new: number, + /** The number of deleted AAS documents. */ + deleted: number, + /** The number of offline events. */ + offline: number +} + +/** The result of a container scan. */ +export interface ScanResult { + /** The result. */ + type: ScanResultType, + /** The task identifier. */ + taskId: number; + /** Statistic information. */ + statistic: ScanStatistic; + /** The message memory. */ + messages?: Message[]; +} + +/** The result of an AASServer endpoint scan. */ +export interface ScanEndpointResult extends ScanResult { + /** The AAS registry. */ + endpoint: string; + /** The result subject. */ + container: AASContainer; +} + +/** The result of a container scan. */ +export interface ScanContainerResult extends ScanResult { + /** The AAS container. */ + container: AASContainer; + /** The result subject. */ + document: AASDocument; +} + +/** Indicates whether the specified result is of type `ScanEndpointResult`. */ +export function isScanEndpointResult(result: ScanResult): result is ScanEndpointResult { + return result.type === ScanResultType.ContainerAdded || result.type === ScanResultType.ContainerRemoved; +} + +/** Indicates whether the specified result is of type `ScanContainerResult`. */ +export function isScanContainerResult(result: ScanResult): result is ScanContainerResult { + return result.type === ScanResultType.Added || result.type === ScanResultType.Changed || + result.type === ScanResultType.Removed || result.type === ScanResultType.Offline; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-provider/worker-data.ts b/projects/aas-server/src/app/aas-provider/worker-data.ts new file mode 100644 index 00000000..ad83da8b --- /dev/null +++ b/projects/aas-server/src/app/aas-provider/worker-data.ts @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASContainer } from "common"; +import { ScanStatistic } from "./scan-result.js"; + +export interface WorkerData { + taskId: number; + type: 'ScanContainerData' | 'ScanEndpointData'; + statistic: ScanStatistic; +} + +export interface ScanContainerData extends WorkerData { + type: 'ScanContainerData'; + container: AASContainer; +} + +export interface ScanEndpointData extends WorkerData { + type: 'ScanEndpointData'; + endpoint: string; + containers: AASContainer[]; +} + +export function isScanContainerData(data: WorkerData): data is ScanContainerData { + return data.type === 'ScanContainerData'; +} + +export function isScanEndpointData(data: WorkerData): data is ScanEndpointData { + return data.type === 'ScanEndpointData'; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/aas-scan-worker.ts b/projects/aas-server/src/app/aas-scan-worker.ts new file mode 100644 index 00000000..9df30ac2 --- /dev/null +++ b/projects/aas-server/src/app/aas-scan-worker.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { MemoryLogger, MemoryLoggerLevel } from './logging/memory-logger.js'; +import { container } from 'tsyringe'; +import { WorkerApp } from './worker-app.js'; + +container.register('Logger', MemoryLogger); +container.registerInstance( + 'LOG_LEVEL', + process.env.NODE_ENV === 'production' ? MemoryLoggerLevel.Error : MemoryLoggerLevel.All); + +const app = container.resolve(WorkerApp); +app.run(); diff --git a/projects/aas-server/src/app/aas-server.ts b/projects/aas-server/src/app/aas-server.ts new file mode 100644 index 00000000..3b417bde --- /dev/null +++ b/projects/aas-server/src/app/aas-server.ts @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { CookieStorageFactory } from './auth/cookie-storage-factory.js'; +import { UserStorageFactory } from './auth/user-storage-factory.js'; +import { LoggerFactory } from './logging/logger-factory.js'; +import { FileLogger } from './logging/file-logger.js'; +import { TemplateStorageFactory } from './template/template-storage-factory.js'; +import { WSServer } from './ws-server.js'; +import { AASProvider } from './aas-provider/aas-provider.js'; + +container.registerInstance('CONFIGURATION', './aas-server-config.json'); +container.registerInstance('USERS_DIR', './users'); +container.registerType('Logger', FileLogger); +container.register('CookieStorage', { useFactory: c => new CookieStorageFactory(c).create() }); +container.register('UserStorage', { useFactory: c => new UserStorageFactory(c).create() }); +container.register('winston.Logger', { useFactory: c => new LoggerFactory(c).create() }); +container.register('TemplateStorage', { useFactory: c => new TemplateStorageFactory(c).create() }); + +container.afterResolution(AASProvider, (_, instance) => { + (instance as AASProvider).start(container.resolve(WSServer)); +}, { frequency: 'Once' }); + +container.resolve(WSServer).run(); +container.resolve(AASProvider); diff --git a/projects/aas-server/src/app/app.ts b/projects/aas-server/src/app/app.ts new file mode 100644 index 00000000..8e0fbf67 --- /dev/null +++ b/projects/aas-server/src/app/app.ts @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import express, { Express, NextFunction, Request, Response, json, urlencoded } from 'express'; +import cors from 'cors'; +import morgan from 'morgan'; +import mongoose from 'mongoose'; +import swaggerUi, { JsonObject } from 'swagger-ui-express'; +import { ApplicationError } from 'common'; +import { ValidateError } from 'tsoa'; + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore +import swaggerDoc from './swagger.json' assert {type: 'json'}; +import { RegisterRoutes } from './routes/routes.js'; +import { ERRORS } from './errors.js'; +import { Variable } from './variable.js'; +import { Logger } from './logging/logger.js'; +import { parseUrl } from './convert.js'; + +/* istanbul ignore next */ +@singleton() +export class App { + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(Variable) private readonly variable: Variable + ) { + this.app = express(); + this.setup(); + this.connectUserStorage(); + } + + public readonly app: Express; + + private setup(): void { + process.on('uncaughtException', (error: Error) => { + this.logger.error(`Uncaught exception: ${error?.message} Stack: ${error?.stack}`); + }); + + process.on('unhandledRejection', (reason, promise) => { + this.logger.error(`Unhandled Rejection at: ${promise}, reason: ${reason}`); + }); + + this.app.use(cors({ + origin: this.variable.CORS_ORIGIN, + credentials: true + })); + + this.app.use(json()); + this.app.use(urlencoded({ extended: true })); + this.app.use(morgan('dev')); + this.app.use('/api-docs', this.setHost, swaggerUi.serveFiles(swaggerDoc, {}), swaggerUi.setup()); + + RegisterRoutes(this.app); + + this.app.get('/', this.getIndex); + this.app.use(express.static(this.variable.WEB_ROOT)); + + this.app.use(this.notFoundHandler); + this.app.use(this.errorHandler); + } + + private async connectUserStorage(): Promise { + const url = this.variable.USER_STORAGE; + if (url) { + try { + const protocol = parseUrl(url).protocol; + if (protocol === 'mongodb:') { + await mongoose.connect(url); + } else { + throw new Error(`${protocol} is not supported.`); + } + } catch (error) { + this.logger.error(`The connection to the user database cannot be established: ${error?.message}`); + } + } + } + + private errorHandler = (err: unknown, req: Request, res: Response, next: NextFunction): Response | void => { + if (err instanceof ValidateError) { + return res.status(422).json({ + message: "Validation Failed", + details: err?.fields, + }); + } + + if (err instanceof ApplicationError) { + if (err.name === ERRORS.UnauthorizedAccess) { + return res.status(401).json({ + message: 'Unauthorized' + }); + } + + return res.status(500).json({ + message: "Internal Server Error", + }); + } + + if (err instanceof Error) { + return res.status(500).json({ + message: "Internal Server Error", + }); + } + + next(); + }; + + private notFoundHandler = (_req: Request, res: Response) => { + res.status(404).send({ + message: "Not Found", + }); + }; + + private setHost = (req: Request, res: Response, next: NextFunction) => { + (swaggerDoc as { host?: string }).host = req.get('host'); + (req as Request & { swaggerDoc: JsonObject }).swaggerDoc = swaggerDoc; + next(); + } + + private getIndex = (req: Request, res: Response) => { + res.sendFile(this.variable.WEB_ROOT + '/index.html'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/application-info.ts b/projects/aas-server/src/app/application-info.ts new file mode 100644 index 00000000..36d341c0 --- /dev/null +++ b/projects/aas-server/src/app/application-info.ts @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { isAbsolute, resolve } from 'path'; +import { Message, PackageInfo } from 'common'; +import { Logger } from './logging/logger.js'; +import { readFile } from 'fs/promises'; +import { inject, singleton } from 'tsyringe'; + +@singleton() +export class ApplicationInfo { + private data?: PackageInfo; + + constructor( + @inject('Logger') private readonly logger: Logger, + ) { } + + public async getAsync(file?: string): Promise { + if (!this.data) { + this.data = await this.readAsync(file); + } + + return this.data; + } + + public getMessages(): Message[] { + return this.logger.getMessages(); + } + + private async readAsync(file?: string): Promise { + try { + let path: string; + if (file) { + if (isAbsolute(file)) { + path = file; + } else { + path = resolve('.', file); + } + } else { + path = resolve('.', 'app-info.json'); + } + + return JSON.parse((await readFile(path)).toString()); + } catch (error) { + this.logger.error(`Reading package failed: ${error?.message}`); + return { + name: '', + version: '', + author: '', + description: '', + license: '', + homepage: '', + libraries: [] + }; + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/auth-service.ts b/projects/aas-server/src/app/auth/auth-service.ts new file mode 100644 index 00000000..fc848e59 --- /dev/null +++ b/projects/aas-server/src/app/auth/auth-service.ts @@ -0,0 +1,222 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import fs from 'fs'; +import bcrypt from 'bcryptjs'; +import jwt from 'jsonwebtoken'; +import { isEmpty } from 'lodash-es'; +import { Mailer } from '../mailer.js'; +import { ERRORS } from '../errors.js'; +import { UserData } from './user-data.js'; +import { UserStorage } from './user-storage.js'; +import { CookieStorage } from './cookie-storage.js'; +import { Variable } from '../variable.js'; +import { + Credentials, + UserProfile, + isValidEMail, + isValidPassword, + ApplicationError, + UserRole, + getUserNameFromEMail, + Cookie, + JWTPayload, + AuthResult +} from 'common'; + +@singleton() +export class AuthService { + private readonly algorithm: jwt.Algorithm; + private readonly privateKey: string; + + constructor( + @inject(Mailer) private readonly mailer: Mailer, + @inject('UserStorage') private readonly userStorage: UserStorage, + @inject('CookieStorage') private readonly cookieStorage: CookieStorage, + @inject(Variable) private readonly variable: Variable + ) { + if (variable.JWT_PUBLIC_KEY) { + this.algorithm = 'RS256'; + this.privateKey = fs.readFileSync(variable.JWT_SECRET, 'utf8'); + } else { + this.algorithm = 'HS256'; + this.privateKey = variable.JWT_SECRET; + } + } + + public async loginAsync(credentials?: Credentials): Promise { + let token: string; + if (credentials?.id) { + if (credentials.password) { + const data = await this.userStorage.readAsync(credentials.id); + if (!data) { + throw new ApplicationError(`Unknown user ${credentials.id}.`, ERRORS.UnknownUser, credentials.id); + } + + await this.checkPasswordAsync(credentials.password, data.password); + token = this.generateToken(data.id, data.name, data.role); + data.lastLoggedIn = new Date(); + await this.userStorage.writeAsync(credentials.id, data); + } else { + token = this.generateExternalToken(credentials.id); + } + } else { + token = this.generateGuestToken(); + } + + return { token }; + } + + public async updateProfileAsync(id: string, profile: UserProfile): Promise { + const data = await this.userStorage.readAsync(id); + if (data == null) { + throw new ApplicationError(`Unknown user ${id}.`, ERRORS.UnknownUser, id); + } + + if (profile.password) { + if (!isValidPassword(profile.password)) { + throw new ApplicationError('Invalid password.', ERRORS.InvalidPassword); + } + + data.password = await bcrypt.hash(profile.password, 10); + } + + data.name = isEmpty(profile.name) ? getUserNameFromEMail(profile.id) : profile.name; + + if (profile.id && id.toLowerCase() === profile.id.toLowerCase()) { + await this.userStorage.writeAsync(id, data); + } else { + if (await this.userStorage.existAsync(profile.id)) { + throw new ApplicationError( + `An account already exists for this e-mail '${profile.id}'.`, + ERRORS.UserAlreadyExists, + profile.id + ); + } + + await this.userStorage.writeAsync(profile.id, data); + await this.userStorage.deleteAsync(id); + } + + const token = this.generateToken(data.id, data.name, data.role); + + return { token }; + } + + public async registerUserAsync(profile: UserProfile): Promise { + if (!isValidEMail(profile.id)) { + throw new ApplicationError(`'${profile.id}' is not a valid e-mail.`, ERRORS.InvalidEMail); + } + + if (await this.userStorage.existAsync(profile.id)) { + throw new ApplicationError( + `An account already exists for this e-mail '${profile.id}'.`, + ERRORS.UserAlreadyExists, + profile.id + ); + } + + if (!profile.password || !isValidPassword(profile.password)) { + throw new ApplicationError('Invalid password.', ERRORS.InvalidPassword); + } + + let name = profile.name; + if (isEmpty(name)) { + name = getUserNameFromEMail(profile.id); + } + + const data: UserData = { + id: profile.id, + name: name, + role: 'editor', + password: await bcrypt.hash(profile.password, 10), + created: new Date(), + lastLoggedIn: new Date(0) + }; + + const token = this.generateToken(data.id, data.name, data.role); + await this.userStorage.writeAsync(profile.id, data); + return { token }; + } + + public async resetPasswordAsync(id: string): Promise { + const data = await this.userStorage.readAsync(id); + if (data == null) { + throw new ApplicationError(`Unknown user ${id}.`, ERRORS.UnknownUser, id); + } + + const password = this.createPassword(); + this.mailer.sendNewPassword(id, password); + data.password = await bcrypt.hash(password, 10); + await this.userStorage.writeAsync(id, data); + } + + public async deleteUserAsync(id: string): Promise { + if (!(await this.userStorage.deleteAsync(id))) { + throw new ApplicationError(`Unknown user ${id}.`, ERRORS.UnknownUser, id); + } + } + + public getCookieAsync(id: string, name: string): Promise { + return this.cookieStorage.getAsync(id, name); + } + + public getCookiesAsync(id: string): Promise { + return this.cookieStorage.getAllAsync(id); + } + + public setCookieAsync(id: string, name: string, data: string): Promise { + return this.cookieStorage.setAsync(id, name, data); + } + + public deleteCookieAsync(id: string, name: string): Promise { + return this.cookieStorage.deleteAsync(id, name); + } + + public hasUserAsync(id: string): Promise { + return this.userStorage.existAsync(id); + } + + private generateToken(subject: string, name: string, role: UserRole): string { + const payload: JWTPayload = { name, role }; + return jwt.sign(payload, this.privateKey, + { + subject, + expiresIn: this.variable.JWT_EXPIRES_IN, + algorithm: this.algorithm + }); + } + + private generateGuestToken(): string { + const payload: JWTPayload = { role: 'guest' }; + return jwt.sign(payload, this.privateKey, { + expiresIn: this.variable.JWT_EXPIRES_IN, + algorithm: this.algorithm + }); + } + + private generateExternalToken(subject: string): string { + const payload: JWTPayload = { role: 'guest' }; + return jwt.sign(payload, this.privateKey, { + subject, + expiresIn: this.variable.JWT_SHORT_EXP, + algorithm: this.algorithm + }); + } + + private async checkPasswordAsync(password: string, hash: string) { + if (!(await bcrypt.compare(password, hash))) { + throw new ApplicationError('Invalid password.', ERRORS.InvalidPassword); + } + } + + private createPassword(): string { + return Math.random().toString(36).slice(-8); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/cookie-storage-factory.ts b/projects/aas-server/src/app/auth/cookie-storage-factory.ts new file mode 100644 index 00000000..1d87e585 --- /dev/null +++ b/projects/aas-server/src/app/auth/cookie-storage-factory.ts @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { DependencyContainer } from 'tsyringe'; +import { CookieStorage } from './cookie-storage.js'; +import { LocaleCookieStorage } from './locale-cookie-storage.js'; +import { Variable } from '../variable.js'; +import { parseUrl } from '../convert.js'; +import { MongoDBCookieStorage } from './mongo-db-cookie-storage.js'; +import { Logger } from '../logging/logger.js'; + +/* istanbul ignore next */ +export class CookieStorageFactory { + constructor(private readonly container: DependencyContainer) { + } + + public create(): CookieStorage { + const url = this.container.resolve(Variable).USER_STORAGE; + const logger = this.container.resolve('Logger'); + if (url) { + try { + const protocol = parseUrl(url).protocol; + if (protocol === 'mongodb:') { + return new MongoDBCookieStorage(); + } else { + throw new Error(`${url} is not supported cookie storage.`); + } + } catch (error) { + logger.error(error); + } + } + + return this.container.resolve(LocaleCookieStorage); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/cookie-storage.ts b/projects/aas-server/src/app/auth/cookie-storage.ts new file mode 100644 index 00000000..4914e049 --- /dev/null +++ b/projects/aas-server/src/app/auth/cookie-storage.ts @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Cookie } from "common"; + +export abstract class CookieStorage { + /** + * @param id The user identification. + * @param name The cookie name. + */ + public abstract checkAsync(id: string, name: string): Promise; + + /** + * @param id The user identification. + * @param name The cookie name. + */ + public abstract getAsync(id: string, name: string): Promise; + + /** + * @param id The user identification. + */ + public abstract getAllAsync(id: string): Promise; + + /** + * @param id The user identification. + * @param name The cookie name. + * @param data + */ + public abstract setAsync(id: string, name: string, data: string): Promise; + + /** + * @param id The user identification. + * @param name The cookie name. + */ + public abstract deleteAsync(id: string, name: string): Promise; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/locale-cookie-storage.ts b/projects/aas-server/src/app/auth/locale-cookie-storage.ts new file mode 100644 index 00000000..7fed41e6 --- /dev/null +++ b/projects/aas-server/src/app/auth/locale-cookie-storage.ts @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import fs from 'fs'; +import path from 'path'; +import { CookieStorage } from './cookie-storage.js'; +import { Cookie } from 'common'; +import { Logger } from '../logging/logger.js'; + +@injectable() +export class LocaleCookieStorage extends CookieStorage { + private readonly usersDirectory: string; + + constructor( + @inject('Logger') private readonly logger: Logger, + @inject('USERS_DIR') dir: string) { + super(); + + this.usersDirectory = path.resolve(dir); + } + + public async checkAsync(id: string, name: string): Promise { + const file = this.getCookiesFile(id); + if (fs.existsSync(file)) { + const cookies = await this.readCookies(file); + return cookies.some(cookie => cookie.name === name); + } + + return false; + } + + public async getAsync(id: string, name: string): Promise { + const file = this.getCookiesFile(id); + if (fs.existsSync(file)) { + const cookies = await this.readCookies(file); + return cookies.find(cookie => cookie.name === name); + } + + return undefined; + } + + public async getAllAsync(id: string): Promise { + const file = this.getCookiesFile(id); + if (fs.existsSync(file)) { + const cookies = await this.readCookies(file); + return cookies; + } + + return []; + } + + public async setAsync(id: string, name: string, data: string): Promise { + const file = this.getCookiesFile(id); + const cookies = fs.existsSync(file) ? await this.readCookies(file) : []; + const index = cookies.findIndex(cookie => cookie.name === name); + if (index < 0) { + cookies.push({ name, data }); + } else { + cookies[index].data = data; + } + + await await fs.promises.writeFile(file, JSON.stringify(cookies)); + } + + public async deleteAsync(id: string, name: string): Promise { + const file = this.getCookiesFile(id); + const cookies = fs.existsSync(file) ? await this.readCookies(file) : []; + const index = cookies.findIndex(cookie => cookie.name === name); + if (index >= 0) { + cookies.splice(index, 1); + if (cookies.length > 0) { + await fs.promises.writeFile(file, JSON.stringify(cookies)); + } else { + await fs.promises.unlink(file); + } + } + } + + private getCookiesFile(id: string): string { + return path.join(this.usersDirectory, id, 'cookies.json'); + } + + private async readCookies(path: string): Promise { + try { + return JSON.parse((await fs.promises.readFile(path)).toString()) as Cookie[]; + } catch (error) { + this.logger.error(`Reading cookies failed: ${error?.message}`); + return []; + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/locale-user-storage.ts b/projects/aas-server/src/app/auth/locale-user-storage.ts new file mode 100644 index 00000000..1b7118fe --- /dev/null +++ b/projects/aas-server/src/app/auth/locale-user-storage.ts @@ -0,0 +1,73 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import path from 'path'; +import fs from 'fs'; +import { UserStorage } from "./user-storage.js"; +import { UserData } from './user-data.js'; + +@injectable() +export class LocaleUserStorage extends UserStorage { + private readonly usersDirectory: string; + + constructor( + @inject('USERS_DIR') usersDirectory: string + ) { + super(); + + this.usersDirectory = path.resolve(usersDirectory); + + if (!fs.existsSync(this.usersDirectory)) { + fs.mkdirSync(this.usersDirectory); + } + } + + public existAsync(userId: string): Promise { + return new Promise((resolve) => resolve(fs.existsSync(this.getUserDir(userId)))); + } + + public async readAsync(userId: string): Promise { + const userFile = this.getUserFile(userId); + return fs.existsSync(userFile) ? await this.readUserData(userFile) : undefined; + } + + public async writeAsync(userId: string, data: UserData): Promise { + const dir = this.getUserDir(userId); + if (!fs.existsSync(dir)) { + await fs.promises.mkdir(dir); + } + + await fs.promises.writeFile(this.getUserFile(userId), JSON.stringify(data)); + } + + public async deleteAsync(userId: string): Promise { + const dir = this.getUserDir(userId); + if (fs.existsSync(dir)) { + await fs.promises.rm(dir, { recursive: true }); + return true; + } + + return false; + } + + private async readUserData(path: string): Promise { + const data = JSON.parse((await fs.promises.readFile(path)).toString()) as UserData; + data.created = new Date(data.created); + data.lastLoggedIn = new Date(data.lastLoggedIn); + return data as UserData; + } + + private getUserFile(userId: string): string { + return path.join(this.usersDirectory, userId, 'user.json'); + } + + private getUserDir(userId: string): string { + return path.join(this.usersDirectory, userId); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/mongo-db-cookie-storage.ts b/projects/aas-server/src/app/auth/mongo-db-cookie-storage.ts new file mode 100644 index 00000000..0a6710aa --- /dev/null +++ b/projects/aas-server/src/app/auth/mongo-db-cookie-storage.ts @@ -0,0 +1,90 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { injectable } from 'tsyringe'; +import { Cookie } from "common"; +import { model, Schema } from "mongoose"; +import { CookieStorage } from "./cookie-storage.js"; + +export interface UserCookies { + id: string; + cookies: Array; +} + +@injectable() +export class MongoDBCookieStorage extends CookieStorage { + private readonly userCookiesSchema = new Schema({ + id: String, + cookies: [ + { + name: String, + data: String + } + ], + }); + + public readonly UserCookiesModel = model('UserCookiesModel', this.userCookiesSchema); + + public async checkAsync(id: string, name: string): Promise { + const user = await this.UserCookiesModel.findOne({ id: id }).exec(); + if (user != null) { + return user.cookies.some(cookie => cookie.name === name); + } + + return false; + } + + public async getAsync(id: string, name: string): Promise { + const user = await this.UserCookiesModel.findOne({ id: id }).exec(); + if (user != null) { + return user.cookies.find(cookie => cookie.name === name); + } + + return undefined; + } + + public async getAllAsync(id: string): Promise { + const user = await this.UserCookiesModel.findOne({ id: id }).exec(); + if (user != null) { + return user.cookies; + } + + return []; + } + + public async setAsync(id: string, name: string, data: string): Promise { + let user = await this.UserCookiesModel.findOne({ id: id }).exec(); + if (user) { + const index = user.cookies.findIndex(cookie => cookie.name === name); + if (index < 0) { + user.cookies.push({ name, data }); + } else { + user.cookies[index].data = data; + } + } else { + user = new this.UserCookiesModel({ id: id, cookies: [{ name, data }] }); + } + + await user.save(); + } + + public async deleteAsync(id: string, name: string): Promise { + const user = await this.UserCookiesModel.findOne({ id: id }).exec(); + if (user) { + const index = user.cookies.findIndex(cookie => cookie.name === name); + if (index >= 0) { + user.cookies.splice(index, 1); + if (user.cookies.length > 0) { + await user.save(); + } else { + await user.deleteOne(); + } + } + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/mongo-db-user-storage.ts b/projects/aas-server/src/app/auth/mongo-db-user-storage.ts new file mode 100644 index 00000000..b695c434 --- /dev/null +++ b/projects/aas-server/src/app/auth/mongo-db-user-storage.ts @@ -0,0 +1,51 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { injectable } from 'tsyringe'; +import { Schema, model } from 'mongoose'; +import { UserData } from "./user-data.js"; +import { UserStorage } from "./user-storage.js"; + +@injectable() +export class MongoDBUserStorage extends UserStorage { + private readonly userDataSchema = new Schema({ + id: { type: String, required: true }, + name: { type: String, required: true }, + role: { type: String, required: true }, + password: { type: String, required: true }, + created: { type: Date, required: true }, + lastLoggedIn: { type: Date, required: true }, + }); + + public readonly UserDataModel = model('UserDataModel', this.userDataSchema); + + public async existAsync(userId: string): Promise { + return (await this.UserDataModel.findOne({ id: userId }).exec()) != null; + } + + public async readAsync(userId: string): Promise { + return await this.UserDataModel.findOne({ id: userId }).exec() ?? undefined; + } + + public async writeAsync(userId: string, data: UserData): Promise { + let instance = await this.UserDataModel.findOne({ id: userId }).exec(); + if (instance) { + instance.name = data.name; + instance.role = data.role; + instance.password = data.password; + } else { + instance = new this.UserDataModel(data); + } + + await instance.save(); + } + + public async deleteAsync(userId: string): Promise { + return (await this.UserDataModel.findOneAndRemove({ id: userId }).exec()) != null + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/user-data.ts b/projects/aas-server/src/app/auth/user-data.ts new file mode 100644 index 00000000..e6257449 --- /dev/null +++ b/projects/aas-server/src/app/auth/user-data.ts @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { UserRole } from "common"; + +/** The user data. */ +export type UserData = { + /** The e-mail address. */ + id: string; + /** The name or alias. */ + name: string; + /** The role. */ + role: UserRole; + /** The password hash. */ + password: string; + /** The creation date. */ + created: Date; + /** The date and time of the last login. */ + lastLoggedIn: Date; +}; \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/user-storage-factory.ts b/projects/aas-server/src/app/auth/user-storage-factory.ts new file mode 100644 index 00000000..a39310a5 --- /dev/null +++ b/projects/aas-server/src/app/auth/user-storage-factory.ts @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { DependencyContainer } from 'tsyringe'; +import { UserStorage } from './user-storage.js'; +import { LocaleUserStorage } from './locale-user-storage.js'; +import { Variable } from '../variable.js'; +import { MongoDBUserStorage } from './mongo-db-user-storage.js'; +import { parseUrl } from '../convert.js'; +import { Logger } from '../logging/logger.js'; + +/* istanbul ignore next */ +export class UserStorageFactory { + constructor(private readonly container: DependencyContainer) { + } + + public create(): UserStorage { + const url = this.container.resolve(Variable).USER_STORAGE; + const logger = this.container.resolve('Logger'); + if (url) { + try { + const protocol = parseUrl(url).protocol; + if (protocol === 'mongodb:') { + return new MongoDBUserStorage(); + } else { + throw new Error(`"${url}" is a not supported user storage.`); + } + } catch (error) { + logger.error(error); + } + } + + return this.container.resolve(LocaleUserStorage); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/auth/user-storage.ts b/projects/aas-server/src/app/auth/user-storage.ts new file mode 100644 index 00000000..00df4ee5 --- /dev/null +++ b/projects/aas-server/src/app/auth/user-storage.ts @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { UserData } from "./user-data.js"; + +/** Defines user storage. */ +export abstract class UserStorage { + /** + * Determines, whether a user with the specified identification exists. + * @param userId The user identification. + */ + public abstract existAsync(userId: string): Promise; + + /** + * Reads the data of the user with the specified identification. + * @param userId The user identification (e-mail). + * @returns The data of the specified user or `undefined` if such a user does not exist. + */ + public abstract readAsync(userId: string): Promise; + + /** + * Writes the data of a new or already registered user with the specified identification. + * @param userId The user identification. + * @param data The user data. + */ + public abstract writeAsync(userId: string, data: UserData): Promise; + + /** + * Deletes the user with the specified identification. + * @param userId The user identification. + * @returns `true` if the specified user was successfully deleted; otherwise, `false`. + */ + public abstract deleteAsync(userId: string): Promise; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/configuration.ts b/projects/aas-server/src/app/configuration.ts new file mode 100644 index 00000000..526da685 --- /dev/null +++ b/projects/aas-server/src/app/configuration.ts @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASEndpointType } from 'common'; + +/** The AAS Server configuration. */ +export interface AASServerConfiguration { + endpoints: string[] +} + +/** + * Gets the endpoint name from the specified URL. + * @param url The endpoint URL. + * @returns The name. + */ +export function getEndpointName(url: string | URL): string { + if (typeof url === 'string') { + url = new URL(url); + } + + return url.searchParams.get('name') ?? url.href.split('?')[0]; +} + +/** + * Gets the endpoint type from the specified URL. + * @param url The URL. + * @returns The endpoint type. + */ +export function getEndpointType(url: string | URL): AASEndpointType { + if (typeof url === 'string') { + url = new URL(url); + } + + switch (url.protocol) { + case 'file:': + return 'AasxDirectory'; + case 'http:': + case 'https:': + return url.searchParams.get('type') as AASEndpointType ?? 'AasxServer'; + case 'opc.tcp:': + return 'OpcuaServer'; + default: + throw new Error(`Protocol "${url.protocol}" is not supported.`); + } +} + +/** + * Creates an AAS container endpoint URL with required search parameters. + * @param address The URL. + * @param options The container endpoint options or names. + * @returns The endpoint URL. + */ +export function createEndpointURL( + address: string | URL, + options?: string | { name?: string, type?: AASEndpointType, params?: [string, string][] }): URL { + const endpoint = typeof address === 'string' ? new URL(address) : address; + let name: string | undefined; + let type: AASEndpointType | undefined; + const params = [...endpoint.searchParams]; + params.forEach(param => endpoint.searchParams.delete(param[0])); + if (typeof options === 'string') { + name = options; + } else if (options) { + name = options.name; + type = options.type; + if (options.params) { + params.push(...options.params); + } + } + + if (!name) { + const tuple = params.find(item => item[0] === 'name'); + if (tuple) { + name = tuple[1]; + } + } + + if (!type) { + const tuple = params.find(item => item[0] === 'type'); + if (tuple) { + type = tuple[1] as AASEndpointType; + } + } + + if (type !== 'AASRegistry' || (endpoint.protocol !== 'http:' && endpoint.protocol !== 'https:')) { + type = undefined; + } + + if (name) { + endpoint.searchParams.append('name', name); + } + + if (type) { + endpoint.searchParams.append('type', type); + } + + params?.forEach(item => { + if (item[0] !== 'type' && item[1] !== 'name') { + endpoint.searchParams.append(item[0], item[1]); + } + }); + + return endpoint; +} + +/** + * Creates an AAS container endpoint URL with required search parameters. + * @param address The AAS container endpoint address (URL). + * @param options The container endpoint options or name. + * @returns The endpoint URL as string. + */ +export function createEndpoint( + address: string | URL, + options?: string | { name?: string, type?: AASEndpointType, params?: [string, string][] }): URL { + return createEndpointURL(address, options); +} diff --git a/projects/aas-server/src/app/controller/app-controller.ts b/projects/aas-server/src/app/controller/app-controller.ts new file mode 100644 index 00000000..6b940295 --- /dev/null +++ b/projects/aas-server/src/app/controller/app-controller.ts @@ -0,0 +1,62 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { Get, OperationId, Route, Security, Tags } from 'tsoa'; +import { ApplicationInfo } from '../application-info.js'; +import { Logger } from '../logging/logger.js'; +import { ControllerBase } from './controller-base.js'; +import { AuthService } from '../auth/auth-service.js'; +import { Variable } from '../variable.js'; +import { Message, PackageInfo } from 'common'; + +@injectable() +@Route('/api/v1/app') +@Tags('App') +export class AppController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable, + @inject(ApplicationInfo) private readonly applicationInfo: ApplicationInfo + ) { + super(logger, auth, variable); + } + + /** + * @summary Gets the license info. + * @returns ToDo + */ + @Get('info') + @Security('bearerAuth', ['guest']) + @OperationId('getInfo') + public async getInfo(): Promise { + try { + this.logger.start('getInfo'); + return await this.applicationInfo.getAsync(); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Gets the log messages from the AASServer. + * @returns The log messages. + */ + @Get('messages') + @Security('bearerAuth', ['guest']) + @OperationId('getMessages') + public async getMessages(): Promise { + try { + this.logger.start('getInfo'); + return await Promise.resolve(this.applicationInfo.getMessages()); + } finally { + this.logger.stop(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/auth-controller.ts b/projects/aas-server/src/app/controller/auth-controller.ts new file mode 100644 index 00000000..0299c4ea --- /dev/null +++ b/projects/aas-server/src/app/controller/auth-controller.ts @@ -0,0 +1,149 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { AuthResult, Cookie, Credentials, UserProfile } from 'common'; +import { Body, Delete, Get, Hidden, OperationId, Path, Post, Put, Route, Security, Tags } from 'tsoa'; + +import { AuthService } from '../auth/auth-service.js'; +import { Logger } from '../logging/logger.js'; +import { ControllerBase } from './controller-base.js'; +import { decodeBase64Url } from '../convert.js'; +import { Variable } from '../variable.js'; + +@injectable() +@Route('/api/v1') +@Tags('Authentication') +export class AuthController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable + ) { + super(logger, auth, variable); + } + + /** + * @summary Anonymous guest login. + * @returns A guest access token with read-only permission. + */ + @Post('guest') + @OperationId('guest') + public guest(): Promise { + return this.auth.loginAsync(); + } + + /** + * @summary Login a user. + * @param credentials The credentials of the user. + * @returns An access token. + */ + @Post('login') + @OperationId('login') + public login(@Body() credentials: Credentials): Promise { + return this.auth.loginAsync(credentials); + } + + /** + * @summary Registers a new user. + * @param profile The user profile. + * @returns An access token with read and write permissions. + */ + @Post('register') + @OperationId('register') + public register(@Body() profile: UserProfile): Promise { + return this.auth.registerUserAsync(profile); + } + + /** + * @summary Updates the profile of the user with the specified ID. + * @param id The user ID. + * @param profile The updated profile. + * @returns A new access token with read and write permissions. + */ + @Put('users/{id}') + @Security('bearerAuth', ['editor']) + @OperationId('updateProfile') + public updateProfile(@Path() id: string, @Body() profile: UserProfile + ): Promise { + return this.auth.updateProfileAsync(decodeBase64Url(id), profile); + } + + /** + * @summary Resets the password for the user with the specified ID. + * @param id The user ID. + */ + @Hidden() + @Delete('users/{id}/reset') + @Security('bearerAuth', ['guest']) + @OperationId('resetPassword') + public resetPassword(@Path() id: string): Promise { + return this.auth.resetPasswordAsync(decodeBase64Url(id)); + } + + /** + * @summary Deletes the user with the specified ID. + * @param id The user ID. + */ + @Delete('users/{id}') + @Security('bearerAuth', ['editor']) + @OperationId('deleteUser') + public deleteUser(@Path() id: string): Promise { + return this.auth.deleteUserAsync(decodeBase64Url(id)) + } + + /** + * @summary Gets the cookie with the specified name. + * @param id The user ID. + * @param name The cookie name. + * @returns The cookie with the specified name or `undefined`. + */ + @Get('users/{id}/cookies/{name}') + @Security('bearerAuth', ['editor']) + @OperationId('getCookie') + public getCookie(@Path() id: string, @Path() name: string): Promise { + return this.auth.getCookieAsync(decodeBase64Url(id), name) + } + + /** + * @summary Gets all cookies of the user with the specified ID. + * @param id The user ID. + * @returns All cookies. + */ + @Get('users/{id}/cookies') + @Security('bearerAuth', ['editor']) + @OperationId('getCookies') + public getCookies(@Path() id: string): Promise { + return this.auth.getCookiesAsync(decodeBase64Url(id)); + } + + /** + * @summary Sets a cookie. + * @param id The user ID. + * @param name The cookie name. + * @param cookie The current cookie. + */ + @Post('users/{id}/cookies/{name}') + @Security('bearerAuth', ['editor']) + @OperationId('setCookie') + public setCookie(@Path() id: string, @Path() name: string, @Body() cookie: Cookie): Promise { + return this.auth.setCookieAsync(decodeBase64Url(id), name, cookie.data); + } + + /** + * @summary Deletes the cookie with the specified name. + * @param id The user ID. + * @param name The cookie name. + */ + @Delete('users/{id}/cookies/{name}') + @Security('bearerAuth', ['editor']) + @OperationId('deleteCookie') + public deleteCookie(@Path() id: string, @Path() name: string): Promise { + return this.auth.deleteCookieAsync(decodeBase64Url(id), name); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/authentication.ts b/projects/aas-server/src/app/controller/authentication.ts new file mode 100644 index 00000000..4fc3a3b6 --- /dev/null +++ b/projects/aas-server/src/app/controller/authentication.ts @@ -0,0 +1,84 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { container, inject, singleton } from 'tsyringe'; +import { Request } from 'express'; +import { UserRole, ApplicationError, isUserAuthorized, JWTPayload } from 'common'; +import jwt from 'jsonwebtoken'; +import fs from 'fs'; + +import { AuthService } from '../auth/auth-service.js'; +import { Logger } from '../logging/logger.js'; +import { ERRORS } from '../errors.js'; +import { Variable } from '../variable.js'; + +@singleton() +export class Authentication { + private static instance?: Authentication; + private readonly publicKey: string; + + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(AuthService) private readonly auth: AuthService, + @inject(Variable) private readonly variable: Variable + ) { + if (this.variable.JWT_PUBLIC_KEY) { + this.publicKey = fs.readFileSync(this.variable.JWT_PUBLIC_KEY, 'utf8'); + } else { + this.publicKey = this.variable.JWT_SECRET; + } + } + + public static authentication(token: string, role: UserRole): Promise { + if (!Authentication.instance) { + Authentication.instance = container.resolve(Authentication); + } + + return Authentication.instance.checkAsync(token, role); + } + + public async checkAsync(token: string, role: UserRole): Promise { + const payload = jwt.verify(token, this.publicKey) as JWTPayload; + if (!payload.role) { + throw new ApplicationError('Unauthorized access.', ERRORS.UnauthorizedAccess); + } + + if (payload.role === 'admin' || payload.role === 'editor') { + if (!payload.sub || !await this.auth.hasUserAsync(payload.sub)) { + throw new ApplicationError('Unauthorized access.', ERRORS.UnauthorizedAccess); + } + } else if (payload.role !== 'guest') { + throw new ApplicationError('Unauthorized access.', ERRORS.UnauthorizedAccess); + } + + if (!isUserAuthorized(payload.role, role)) { + throw new ApplicationError('Unauthorized access.', ERRORS.UnauthorizedAccess); + } + + return payload; + } +} + +export async function expressAuthentication(req: Request, name: string, scopes?: string[]): Promise { + if (name === 'bearerAuth') { + if (scopes && scopes.length === 1) { + if (req.headers.authorization) { + const items = req.headers.authorization.split(' '); + if (items.length === 2) { + return Authentication.authentication(items[1], scopes[0] as UserRole); + } + } + } + } else if (name === 'api_key') { + if (req.query && req.query.access_token) { + return Authentication.authentication(req.query.access_token as string, 'guest'); + } + } + + throw new ApplicationError('Unauthorized access.', ERRORS.UnauthorizedAccess); +} diff --git a/projects/aas-server/src/app/controller/containers-controller.ts b/projects/aas-server/src/app/controller/containers-controller.ts new file mode 100644 index 00000000..ba00fd3e --- /dev/null +++ b/projects/aas-server/src/app/controller/containers-controller.ts @@ -0,0 +1,231 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { Body, Delete, Get, OperationId, Path, Post, Put, Queries, Route, Security, Tags, UploadedFiles } from 'tsoa'; +import { AASDocument, aas } from 'common'; + +import { AASProvider } from '../aas-provider/aas-provider.js'; +import { AuthService } from '../auth/auth-service.js'; +import { Logger } from '../logging/logger.js'; +import { decodeBase64Url } from '../convert.js'; +import { ControllerBase } from './controller-base.js'; +import { Variable } from '../variable.js'; + +@injectable() +@Route('/api/v1/containers') +@Tags('Containers') +export class ContainersController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable, + @inject(AASProvider) private readonly aasProvider: AASProvider + ) { + super(logger, auth, variable); + } + + /** + * @summary Gets all AAS documents (no content) of the specified AAS container. + * @param url The AAS container URL (Base64Url encoded). + * @returns All AAS documents ot the specified AAS container. + */ + @Get('{url}/documents') + @Security('bearerAuth', ['guest']) + @OperationId('getDocuments') + public async getDocuments(@Path() url: string): Promise { + try { + this.logger.start('getDocuments'); + return await Promise.resolve(this.aasProvider.getDocuments(decodeBase64Url(url))); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Downloads an AAS document from the specified AAS container. + * @param url The AAS container URL (Base64Url encoded). + * @param id The AAS identifier (Base64Url encoded). + * @returns A readable stream. + */ + @Get('{url}/documents/{id}') + @Security('bearerAuth', ['guest']) + @OperationId('getDocument') + public async getDocument(@Path() url: string, @Path() id: string): Promise { + try { + this.logger.start('getDocument'); + return await this.aasProvider.getDocumentAsync(decodeBase64Url(url), decodeBase64Url(id)); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Uploads one or more AAS documents to the specified AAS container. + * @param url The AAS container URL (Base64Url encoded). + * @param files The AAS Document. + */ + @Post('{url}/documents') + @Security('bearerAuth', ['editor']) + @OperationId('addDocuments') + public async addDocuments(@Path() url: string, @UploadedFiles() files: Express.Multer.File[]): Promise { + try { + this.logger.start('addDocuments'); + await this.aasProvider.addDocumentsAsync(decodeBase64Url(url), files); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Deletes an AAS document from its AAS container. + * @param url The AAS container URL (Base64Url encoded). + * @param id The AAS identifier (Base64Url encoded). + */ + @Delete('{url}/documents/{id}') + @Security('bearerAuth', ['editor']) + @OperationId('deleteDocument') + public async deleteDocument(@Path() url: string, @Path() id: string): Promise { + try { + this.logger.start('deletePackage'); + await this.aasProvider.deleteDocumentAsync(decodeBase64Url(url), decodeBase64Url(id)); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Gets the content of the specified AAS document. + * @param url The AAS container URL (Base64Url encoded). + * @param id The AAS identifier (Base64Url encoded). + * @returns The AAS environment or `undefined`. + */ + @Get('{url}/documents/{id}/content') + @Security('bearerAuth', ['guest']) + @OperationId('getDocumentContent') + public async getDocumentContent(@Path() url: string, @Path() id: string): Promise { + try { + this.logger.start('getDocumentContent'); + return await this.aasProvider.getContentAsync(decodeBase64Url(url), decodeBase64Url(id)); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Gets the thumbnail of the specified AAS document. + * @param url The AAS container URL (Base64Url encoded). + * @param id The AAS identifier (Base64Url encoded). + * @returns The thumbnail of the current AAS document. + */ + @Get('{url}/documents/{id}/thumbnail') + @Security('bearerAuth', ['guest']) + @OperationId('getDocumentThumbnail') + public async getDocumentThumbnail(@Path() url: string, @Path() id: string): Promise { + try { + this.logger.start('getDocumentThumbnail'); + return await this.aasProvider.getThumbnailAsync(decodeBase64Url(url), decodeBase64Url(id)); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Downloads the value of DataElement. + * @param url The URL of the AAS container (Base64Url encoded). + * @param id The document or AAS identifier (Base64Url encoded). + * @param smId The Submodel identifier (Base64Url encoded). + * @param path The idShort path to the DataElement. + * @param width The image width. + * @param height The image height. + */ + @Get('{url}/documents/{id}/submodels/{smId}/submodel-elements/{path}/value') + @Security('bearerAuth', ['guest']) + @Security('api_key') + @OperationId('getDataElementValue') + public async getDataElementValue( + @Path() url: string, + @Path() id: string, + @Path() smId: string, + @Path() path: string, + @Queries() queryParams: { width?: number, height?: number }, + ): Promise { + try { + this.logger.start('getDataElementValue'); + return await this.aasProvider.getDataElementValueAsync( + decodeBase64Url(url), + decodeBase64Url(id), + decodeBase64Url(smId), + path, + queryParams); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Resets the AASServer container configuration. + */ + @Delete('reset') + @Security('bearerAuth', ['editor']) + @OperationId('reset') + public async reset(): Promise { + try { + this.logger.start('reset'); + await this.aasProvider.resetAsync(); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Updates the content of an AAS document. + * @param url The URL of the AAS container (Base64Url encoded). + * @param id The document or AAS identifier (Base64Url encoded). + * @param content The new document content. + * @returns The messages of the update process. + */ + @Put('{url}/documents/{id}') + @Security('bearerAuth', ['editor']) + @OperationId('updateDocument') + public async updateDocument( + @Path() url: string, + @Path() id: string, + @Body() content: aas.Environment + ): Promise { + try { + this.logger.start('updateDocument'); + return await this.aasProvider.updateDocumentAsync(decodeBase64Url(url), decodeBase64Url(id), content); + } finally { + this.logger.stop(); + } + } + + /** + * @summary Invokes an Operation synchronously. + * @param url The URL of the AAS container (Base64Url encoded). + * @param id The document or AAS identifier (Base64Url encoded). + * @param operation The `Operation`. + * @returns The executed `Operation`. + */ + @Post('{url}/documents/{id}/invoke') + @Security('bearerAuth', ['editor']) + @OperationId('invokeOperation') + public async invokeOperation( + @Path() url: string, + @Path() id: string, + @Body() operation: aas.Operation + ): Promise { + try { + this.logger.start('invokeOperation'); + return await this.aasProvider.invoke(decodeBase64Url(url), decodeBase64Url(id), operation); + } finally { + this.logger.stop(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/controller-base.ts b/projects/aas-server/src/app/controller/controller-base.ts new file mode 100644 index 00000000..7625800a --- /dev/null +++ b/projects/aas-server/src/app/controller/controller-base.ts @@ -0,0 +1,22 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Controller } from 'tsoa'; +import { AuthService } from '../auth/auth-service.js'; +import { Logger } from '../logging/logger.js'; +import { Variable } from '../variable.js'; + +export abstract class ControllerBase extends Controller { + protected constructor( + protected readonly logger: Logger, + protected readonly auth: AuthService, + protected readonly variable: Variable + ) { + super(); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/documents-controller.ts b/projects/aas-server/src/app/controller/documents-controller.ts new file mode 100644 index 00000000..4a2999b4 --- /dev/null +++ b/projects/aas-server/src/app/controller/documents-controller.ts @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { Get, OperationId, Route, Security, Tags } from 'tsoa'; +import { Logger } from '../logging/logger.js'; +import { ControllerBase } from './controller-base.js'; +import { AuthService } from '../auth/auth-service.js'; +import { Variable } from '../variable.js'; +import { AASDocument } from 'common'; +import { AASProvider } from '../aas-provider/aas-provider.js'; +import { decodeBase64Url } from '../convert.js'; + +@injectable() +@Route('/api/v1/documents') +@Tags('Documents') +export class DocumentsController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable, + @inject(AASProvider) private readonly aasProvider: AASProvider + ) { + super(logger, auth, variable); + } + + /** + * Gets the first occurrence of an AAS document with the specified identifier. + * @param id The AAS identifier. + * @returns The first occurrence of an AAS document with the specified identifier. + */ + @Get('{id}') + @Security('bearerAuth', ['guest']) + @OperationId('getDocument') + public async getDocument(id: string): Promise { + try { + this.logger.start('getWorkspaces'); + return await Promise.resolve(this.aasProvider.getDocument(decodeBase64Url(id))); + } finally { + this.logger.stop(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/endpoints-controller.ts b/projects/aas-server/src/app/controller/endpoints-controller.ts new file mode 100644 index 00000000..59bfa949 --- /dev/null +++ b/projects/aas-server/src/app/controller/endpoints-controller.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { Body, Delete, OperationId, Path, Post, Route, Security, Tags } from 'tsoa'; + +import { AASProvider } from '../aas-provider/aas-provider.js'; +import { AuthService } from '../auth/auth-service.js'; +import { Logger } from '../logging/logger.js'; +import { ControllerBase } from './controller-base.js'; +import { Variable } from '../variable.js'; + +@injectable() +@Route('/api/v1/endpoints') +@Tags('Endpoints') +export class EndpointsController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable, + @inject(AASProvider) private readonly aasProvider: AASProvider + ) { + super(logger, auth, variable); + } + + /** + * @summary Adds a new endpoint to the AASServer container configuration. + * @param name The endpoint name. + * @param data The endpoint URL. + */ + @Post('{name}') + @Security('bearerAuth', ['editor']) + @OperationId('addEndpoint') + public addEndpoint(@Path() name: string, @Body() data: { url: string }): Promise { + return this.aasProvider.addEndpointAsync(name, new URL(data.url)) + } + + /** + * @summary Deletes the endpoint with the specified name from the AASServer container configuration. + * @param name The endpoint name. + */ + @Delete('{name}') + @Security('bearerAuth', ['editor']) + @OperationId('deleteEndpoint') + public deleteEndpoint(@Path() name: string): Promise { + return this.aasProvider.removeEndpointAsync(name); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/ioc-container.ts b/projects/aas-server/src/app/controller/ioc-container.ts new file mode 100644 index 00000000..e03cd928 --- /dev/null +++ b/projects/aas-server/src/app/controller/ioc-container.ts @@ -0,0 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { IocContainer } from '@tsoa/runtime'; +import { container } from 'tsyringe'; + +export const iocContainer: IocContainer = { + get: (controller: { prototype: T }): T => { + return container.resolve(controller as never); + }, +}; \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/templates-controller.ts b/projects/aas-server/src/app/controller/templates-controller.ts new file mode 100644 index 00000000..777fb711 --- /dev/null +++ b/projects/aas-server/src/app/controller/templates-controller.ts @@ -0,0 +1,49 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { Get, OperationId, Route, Security, Tags } from 'tsoa'; +import { Logger } from '../logging/logger.js'; +import { ControllerBase } from './controller-base.js'; +import { AuthService } from '../auth/auth-service.js'; +import { Variable } from '../variable.js'; +import { TemplateDescriptor } from 'common'; +import { TemplateStorage } from '../template/template-storage.js'; + +/** + * Asset Administration Shell referable templates. + */ +@injectable() +@Route('/api/v1/templates') +@Tags('Templates') +export class TemplatesController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable, + @inject('TemplateStorage') private readonly templateStorage: TemplateStorage + ) { + super(logger, auth, variable); + } + + /** + * @summary Gets all templates. + * @returns All available templates. + */ + @Get() + @Security('bearerAuth', ['guest']) + @OperationId('getTemplates') + public async getTemplates(): Promise { + try { + this.logger.start('templates'); + return await this.templateStorage.readAsync(); + } finally { + this.logger.stop(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/controller/workspaces-controller.ts b/projects/aas-server/src/app/controller/workspaces-controller.ts new file mode 100644 index 00000000..a546ff85 --- /dev/null +++ b/projects/aas-server/src/app/controller/workspaces-controller.ts @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, injectable } from 'tsyringe'; +import { Get, OperationId, Route, Security, Tags } from 'tsoa'; +import { Logger } from '../logging/logger.js'; +import { ControllerBase } from './controller-base.js'; +import { AuthService } from '../auth/auth-service.js'; +import { Variable } from '../variable.js'; +import { AASWorkspace } from 'common'; +import { AASProvider } from '../aas-provider/aas-provider.js'; + +@injectable() +@Route('/api/v1/workspaces') +@Tags('Workspaces') +export class WorkspacesController extends ControllerBase { + constructor( + @inject('Logger') logger: Logger, + @inject(AuthService) auth: AuthService, + @inject(Variable) variable: Variable, + @inject(AASProvider) private readonly aasProvider: AASProvider + ) { + super(logger, auth, variable); + } + + /** + * @summary Gets the workspaces. + * @returns All current available workspaces. + */ + @Get('') + @Security('bearerAuth', ['guest']) + @OperationId('getWorkspaces') + public async getWorkspaces(): Promise { + try { + this.logger.start('getWorkspaces'); + return await Promise.resolve(this.aasProvider.getWorkspaces()); + } finally { + this.logger.stop(); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/convert.ts b/projects/aas-server/src/app/convert.ts new file mode 100644 index 00000000..fe0e0b83 --- /dev/null +++ b/projects/aas-server/src/app/convert.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ApplicationError } from 'common'; +import { ERRORS } from "./errors.js"; + +export function decodeBase64Url(data: string): string { + return Buffer.from(data, 'base64url').toString('ascii'); +} + +export function encodeBase64Url(data: string): string { + return Buffer.from(data).toString('base64url'); +} + +export function parseUrl(url: string): URL { + try { + return new URL(url); + } catch (error) { + throw new ApplicationError( + `"${url}" is an invalid URL: ${error?.message}`, + ERRORS.InvalidURL, + url, + error?.message); + } +} + +export function toUint8Array(data: T): Uint8Array { + return Uint8Array.from(Buffer.from(JSON.stringify(data))); +} diff --git a/projects/aas-server/src/app/errors.ts b/projects/aas-server/src/app/errors.ts new file mode 100644 index 00000000..38359ede --- /dev/null +++ b/projects/aas-server/src/app/errors.ts @@ -0,0 +1,28 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export const ERRORS = { + Uncaught: 'ERROR_UNCAUGHT', + InvalidCredentials: 'ERROR_INVALID_CREDENTIALS', + UnknownUser: 'ERROR_UNKNOWN_USER', + InvalidPassword: 'ERROR_INVALID_PASSWORD', + InvalidEMail: 'ERROR_INVALID_EMAIL', + FileAlreadyExists: 'ERROR_FILE_ALREADY_EXISTS', + UploadFailed: 'ERROR_UPLOAD_FAILED', + UnauthorizedAccess: 'ERROR_UNAUTHORIZED_ACCESS', + UserAlreadyExists: 'ERROR_USER_ALREADY_EXISTS', + AASNotFound: 'ERROR_AAS_NOT_FOUND', + PasswordExpired: 'ERROR_PASSWORD_EXPIRED', + InvalidAASXPackage: 'ERROR_INVALID_AASX_PACKAGE', + ContainerUrlAlreadyExists: 'ERROR_CONTAINER_URL_ALREADY_EXISTS', + RegistryAlreadyExists: 'ERROR_ENDPOINT_ALREADY_EXISTS', + InvalidURL: 'ERROR_INVALID_URL', + DeleteAASNotSupported: 'ERROR_DELETE_AAS_NOT_SUPPORTED', + InvalidContainerUrl: 'ERROR_INVALID_CONTAINER_URL', + InvokeOperationFailed: 'ERROR_INVOKE_OPERATION_FAILED' +}; \ No newline at end of file diff --git a/projects/aas-server/src/app/file-storage/file-storage-factory.ts b/projects/aas-server/src/app/file-storage/file-storage-factory.ts new file mode 100644 index 00000000..cc4226ca --- /dev/null +++ b/projects/aas-server/src/app/file-storage/file-storage-factory.ts @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import path from 'path'; +import { inject, singleton } from 'tsyringe'; +import { FileStorage } from "./file-storage.js"; +import { LocalFileStorage } from "./local-file-storage.js"; +import { parseUrl } from '../convert.js'; +import { Variable } from '../variable.js'; + +@singleton() +export class FileStorageFactory { + constructor( + @inject(Variable) private readonly variable: Variable + ) { + } + + /** + * Creates a FileStorage for the specified URL. + * @param url The URL of the file storage. + * @returns A new FileStorage instance. + */ + public create(url: string | URL): FileStorage { + const temp = typeof url === 'string' ? parseUrl(url) : url; + if (temp.protocol === 'file:') { + return new LocalFileStorage(path.join(this.variable.ASSETS, temp.pathname)); + } + + throw new Error('Not implemented.') + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/file-storage/file-storage.ts b/projects/aas-server/src/app/file-storage/file-storage.ts new file mode 100644 index 00000000..6dfda46f --- /dev/null +++ b/projects/aas-server/src/app/file-storage/file-storage.ts @@ -0,0 +1,22 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +/** Defines a file based AASX package source. */ +export abstract class FileStorage { + public abstract readonly root: string; + public abstract mtime(path: string): Promise; + public abstract exists(path: string): Promise; + public abstract isDirectory(path: string): Promise; + public abstract mkdir(path: string, recursive?: boolean): Promise; + public abstract writeFile(path: string, data: string | Buffer): Promise; + public abstract readdir(path: string): Promise; + public abstract readFile(path: string): Promise; + public abstract unlink(path: string): Promise; + public abstract rename(oldPath: string, newPath: string): Promise; + public abstract createReadStream(path: string): NodeJS.ReadableStream; +} diff --git a/projects/aas-server/src/app/file-storage/local-file-storage.ts b/projects/aas-server/src/app/file-storage/local-file-storage.ts new file mode 100644 index 00000000..bc61d978 --- /dev/null +++ b/projects/aas-server/src/app/file-storage/local-file-storage.ts @@ -0,0 +1,61 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import fs from 'fs'; +import { resolve } from 'path'; +import { FileStorage } from './file-storage.js'; + +export class LocalFileStorage extends FileStorage { + constructor(root: string) { + super(); + + this.root = resolve(root); + } + + public readonly root: string; + + public async mtime(path: string): Promise { + return (await fs.promises.stat(resolve(this.root, path))).mtime; + } + + public exists(path: string): Promise { + return new Promise(res => res(fs.existsSync(resolve(this.root, path)))); + } + + public async isDirectory(path: string): Promise { + return (await fs.promises.stat(resolve(this.root, path))).isDirectory(); + } + + public mkdir(path: string, recursive = false): Promise { + return fs.promises.mkdir(resolve(this.root, path), { recursive: recursive }); + } + + public writeFile(path: string, data: string | Buffer): Promise { + return fs.promises.writeFile(resolve(this.root, path), data); + } + + public readdir(path: string): Promise { + return fs.promises.readdir(resolve(this.root, path)); + } + + public readFile(path: string): Promise { + return fs.promises.readFile(resolve(this.root, path)); + } + + public unlink(path: string): Promise { + return fs.promises.unlink(resolve(this.root, path)); + } + + public rename(oldPath: string, newPath: string): Promise { + return fs.promises.rename(resolve(this.root, oldPath), resolve(this.root, newPath)); + } + + public createReadStream(path: string): NodeJS.ReadableStream { + return fs.createReadStream(resolve(this.root, path)); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/file-storage/own-cloud-storage.ts b/projects/aas-server/src/app/file-storage/own-cloud-storage.ts new file mode 100644 index 00000000..0ea592cb --- /dev/null +++ b/projects/aas-server/src/app/file-storage/own-cloud-storage.ts @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { FileStorage } from './file-storage.js'; +import ownCloud, { OwnCloudOptions } from 'owncloud-sdk'; + +export class OwnCloudStorage extends FileStorage { + + public readonly root: string = '/'; + + public async connect(url: string): Promise { + const temp = new URL(url); + const username = temp.username; + const password = temp.password; + temp.username = ''; + temp.password = ''; + + const options: OwnCloudOptions = { + baseUrl: temp.href + } + + if (username && password) { + options.auth = { basic: { username, password } }; + } + + const oc = new ownCloud(options); + + await oc.login(); + } + + public mtime(path: string): Promise { + throw new Error('Method not implemented.'); + } + + public exists(path: string): Promise { + throw new Error('Method not implemented.'); + } + + public isDirectory(path: string): Promise { + throw new Error('Method not implemented.'); + } + public mkdir(path: string, recursive?: boolean | undefined): Promise { + throw new Error('Method not implemented.'); + } + + public writeFile(path: string, data: string | Buffer): Promise { + throw new Error('Method not implemented.'); + } + + public readdir(path: string): Promise { + throw new Error('Method not implemented.'); + } + + public readFile(path: string): Promise { + throw new Error('Method not implemented.'); + } + + public unlink(path: string): Promise { + throw new Error('Method not implemented.'); + } + + public rename(oldPath: string, newPath: string): Promise { + throw new Error('Method not implemented.'); + } + + public createReadStream(path: string): NodeJS.ReadableStream { + throw new Error('Method not implemented.'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/image-processing.ts b/projects/aas-server/src/app/image-processing.ts new file mode 100644 index 00000000..d3db143c --- /dev/null +++ b/projects/aas-server/src/app/image-processing.ts @@ -0,0 +1,83 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import jimp from 'jimp'; +import { Duplex } from 'stream'; + +export class ImageProcessing { + /** + * Resizes an image. + * @param source The source stream of the image. + * @param width The new with of the image. + * @param height The new height of the image. + * @param target The target stream. + * @returns The resized image. + */ + public static async resizeAsync( + source: NodeJS.ReadableStream, + width: number | undefined, + height: number | undefined): Promise { + const buffer: Buffer = await new Promise((resolve, reject) => { + const buffers: Uint8Array[] = []; + source.on('data', function (buffer: Uint8Array) { + buffers.push(buffer); + }); + + source.on('end', function () { + try { + resolve(Buffer.concat(buffers)); + } catch (error) { + reject(error); + } + }); + + source.resume(); + }); + + const image = await jimp.read(buffer); + await image.resize(width || jimp.AUTO, height || jimp.AUTO); + const outBuffer = await image.getBufferAsync(jimp.MIME_PNG); + + const stream = new Duplex(); + stream.push(outBuffer); + stream.push(null); + return stream; + } + + /** + * Converts the specified source image to the specified mime-type. + * @param source The source image. + * @param mimeType The target mime-type. + * @returns The converted image. + */ + public static async convertAsync(source: NodeJS.ReadableStream, mimeType: string): Promise { + const buffer: Buffer = await new Promise((resolve, reject) => { + const buffers: Uint8Array[] = []; + source.on('data', function (buffer: Uint8Array) { + buffers.push(buffer); + }); + + source.on('end', function () { + try { + resolve(Buffer.concat(buffers)); + } catch (error) { + reject(error); + } + }); + + source.resume(); + }); + + const image = await jimp.read(buffer); + const outBuffer = await image.getBufferAsync(mimeType); + const stream = new Duplex(); + stream.push(outBuffer); + stream.push(null); + return stream; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/lazy.ts b/projects/aas-server/src/app/lazy.ts new file mode 100644 index 00000000..421c9571 --- /dev/null +++ b/projects/aas-server/src/app/lazy.ts @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +/** + * @description + * Provides support for lazy initialization. + * @template T The type of the object that is being lazily initialized. + */ +export class Lazy { + private initialize: () => Promise; + private _value?: T; + + /** + * + * @param initialize The + */ + constructor(initialize: () => Promise) { + this.initialize = initialize; + } + + /** + * Indicates whether a value has been created. + * @returns {boolean} `true` if the value is created; otherwise, `false`. + */ + public get hasValue(): boolean { + return this._value !== undefined; + } + + /** + * Gets the lazily initialized value. + * @returns T + */ + public async getValueAsync(): Promise { + if (!this._value) { + this._value = await this.initialize(); + } + + return this._value; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/empty-subscription.ts b/projects/aas-server/src/app/live/empty-subscription.ts new file mode 100644 index 00000000..4ae17f5f --- /dev/null +++ b/projects/aas-server/src/app/live/empty-subscription.ts @@ -0,0 +1,21 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { noop } from 'lodash-es'; +import { SocketSubscription } from "./socket-subscription.js"; + +/** Provides an empty WebSocket subscription. */ +export class EmptySubscription extends SocketSubscription { + public open(): void { + noop(); + } + + public close(): void { + noop(); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/http/http-socket-item.ts b/projects/aas-server/src/app/live/http/http-socket-item.ts new file mode 100644 index 00000000..9f38a9f3 --- /dev/null +++ b/projects/aas-server/src/app/live/http/http-socket-item.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { LiveNode } from 'common'; +import { SocketItem } from '../socket-item.js'; +import { noop } from 'lodash-es'; + +export class HttpSocketItem implements SocketItem { + constructor( + public readonly node: LiveNode, + public readonly url: string) { + } + + public subscribe(): void { + noop(); + } + + public unsubscribe(): void { + noop(); + } + } \ No newline at end of file diff --git a/projects/aas-server/src/app/live/http/http-subscription.ts b/projects/aas-server/src/app/live/http/http-subscription.ts new file mode 100644 index 00000000..d48a0646 --- /dev/null +++ b/projects/aas-server/src/app/live/http/http-subscription.ts @@ -0,0 +1,75 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { noop } from "lodash-es"; +import { aas, changeType, LiveNode, LiveRequest } from "common"; +import { HttpSocketItem } from "./http-socket-item.js"; +import { Logger } from "../../logging/logger.js"; +import { SocketClient } from "../socket-client.js"; +import { AasxServer } from "../../packages/aasx-server/aasx-server.js"; +import { SocketSubscription } from "../socket-subscription.js"; + +export class HttpSubscription extends SocketSubscription { + private readonly items: HttpSocketItem[]; + private timeout = 300; + private timeoutId?: NodeJS.Timeout; + + constructor( + private readonly logger: Logger, + private readonly server: AasxServer, + private readonly client: SocketClient, + message: LiveRequest, + env: aas.Environment) { + super(); + + this.items = message.nodes.map(node => new HttpSocketItem( + node, + server.resolveNodeId(env.assetAdministrationShells[0], node.nodeId))); + } + + public open(): void { + if (!this.timeoutId) { + this.timeoutId = setTimeout(this.readValues.bind(this), 10); + } else { + this.logger.debug(`The subscription ${this.server.baseUrl} is already open.`); + } + } + + public close(): void { + if (this.timeoutId) { + clearTimeout(this.timeoutId); + this.timeoutId = undefined; + } + } + + private async readValues(): Promise { + this.timeoutId = undefined; + const nodes: Array = []; + for (const item of this.items) { + try { + item.node.value = changeType( + await this.server.readValueAsync(item.url, item.node.valueType), + item.node.valueType); + + item.node.timeStamp = Date.now(); + nodes.push(item.node); + } catch (error) { + noop(); + } + } + + if (nodes.length > 0) { + this.client.notify({ + type: "LiveNode[]", + data: nodes + }); + } + + this.timeoutId = setTimeout(this.readValues.bind(this), this.timeout); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/opcua/opcua-socket-item.ts b/projects/aas-server/src/app/live/opcua/opcua-socket-item.ts new file mode 100644 index 00000000..f1ce717d --- /dev/null +++ b/projects/aas-server/src/app/live/opcua/opcua-socket-item.ts @@ -0,0 +1,50 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ClientMonitoredItem, DataValue } from 'node-opcua'; +import { Logger } from '../../logging/logger.js'; +import { LiveNode } from 'common'; +import { SocketItem } from '../socket-item.js'; +import { SocketClient }from '../socket-client.js'; + +export class OpcuaSocketItem implements SocketItem { + private item?: ClientMonitoredItem; + + constructor( + private readonly logger: Logger, + private readonly client: SocketClient, + public readonly node: LiveNode) { + } + + public subscribe(item: ClientMonitoredItem): void { + this.item = item; + this.item.on('changed', this.valueChanged); + this.item.on('err', this.onError); + } + + public unsubscribe(): void { + if (this.item) { + this.item.off('changed', this.valueChanged); + this.item.off('err', this.onError); + this.item.terminate(); + } + } + + private valueChanged = (dataValue: DataValue): void => { + this.node.value = dataValue.value.value; + this.node.timeStamp = dataValue.serverTimestamp?.valueOf(); + this.client.notify({ + type: 'LiveNode[]', + data: [this.node] + }); + } + + private onError = (message: string): void => { + this.logger.error(message); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/opcua/opcua-subscription.ts b/projects/aas-server/src/app/live/opcua/opcua-subscription.ts new file mode 100644 index 00000000..6da00aca --- /dev/null +++ b/projects/aas-server/src/app/live/opcua/opcua-subscription.ts @@ -0,0 +1,105 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { LiveNode } from 'common'; +import { OpcuaSocketItem } from './opcua-socket-item.js'; +import { OpcuaServer } from '../../packages/opcua/opcua-server.js'; +import { Logger } from '../../logging/logger.js'; +import { SocketClient } from '../socket-client.js'; +import { SocketSubscription } from '../socket-subscription.js'; +import { + AttributeIds, + ClientMonitoredItem, + ClientSubscription, + MonitoringParametersOptions, + NodeId, + ReadValueIdOptions, + TimestampsToReturn +} from 'node-opcua'; + +export class OpcuaSubscription extends SocketSubscription { + private readonly server: OpcuaServer; + private readonly items: OpcuaSocketItem[]; + private subscription?: ClientSubscription; + + constructor(private readonly logger: Logger, client: SocketClient, server: OpcuaServer, nodes: LiveNode[]) { + super(); + + this.server = server; + this.items = nodes.map(node => new OpcuaSocketItem(logger, client, node)); + } + + public open(): void { + this.subscription = ClientSubscription.create(this.server.getSession(), { + requestedPublishingInterval: 1000, + requestedLifetimeCount: 100, + requestedMaxKeepAliveCount: 10, + maxNotificationsPerPublish: 100, + publishingEnabled: true, + priority: 10 + }); + + this.subscription.on('started', this.onSubscriptionStarted) + .on('keepalive', this.onSubscriptionKeepAlive) + .on('terminated', this.onSubscriptionTerminated) + .on('error', this.onSubscriptionError) + .on('internal_error', this.onSubscriptionError); + + for (const item of this.items as OpcuaSocketItem[]) { + const itemToMonitor: ReadValueIdOptions = { + nodeId: NodeId.resolveNodeId(item.node.nodeId), + attributeId: AttributeIds.Value + }; + + const parameters: MonitoringParametersOptions = { + samplingInterval: 100, + discardOldest: true, + queueSize: 10 + }; + + const monitoredItem = ClientMonitoredItem.create( + this.subscription, + itemToMonitor, + parameters, + TimestampsToReturn.Both + ); + + item.subscribe(monitoredItem); + } + } + + public close(): void { + this.items?.forEach(item => item.unsubscribe()); + + if (this.subscription) { + this.subscription.off('started', this.onSubscriptionStarted) + .off('keepalive', this.onSubscriptionKeepAlive) + .off('terminated', this.onSubscriptionTerminated) + .off('error', this.onSubscriptionError) + .off('internal_error', this.onSubscriptionError); + + this.subscription.terminate(); + } + } + + private onSubscriptionStarted = (subscriptionId: number): void => { + this.logger.debug(`Subscription ${subscriptionId} started.`); + } + + private onSubscriptionKeepAlive = (): void => { + this.logger.debug(`Subscription ${this.subscription?.subscriptionId} keep alive.`); + } + + private onSubscriptionTerminated = (): void => { + this.logger.debug(`Subscription ${this.subscription?.subscriptionId} terminated.`); + } + + private onSubscriptionError = (error: Error): void => { + this.logger.error(error); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/socket-client.ts b/projects/aas-server/src/app/live/socket-client.ts new file mode 100644 index 00000000..81ef2835 --- /dev/null +++ b/projects/aas-server/src/app/live/socket-client.ts @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import EventEmitter from 'events'; +import WebSocket from 'ws'; +import { WebSocketData } from 'common'; +import { SocketSubscription } from './socket-subscription.js'; + +export class SocketClient extends EventEmitter { + private readonly ws: WebSocket; + private readonly subscriptions = new Map(); + + constructor(ws: WebSocket) { + super(); + + this.ws = ws; + this.ws.on('message', this.onMessage); + this.ws.on('close', this.onClose); + this.ws.on('error', this.onError); + } + + public has(name: string): boolean { + return this.subscriptions.has(name); + } + + public subscribe(name: string, subscription: SocketSubscription) { + subscription.open(); + this.subscriptions.set(name, subscription); + } + + public notify(data: WebSocketData): void { + return this.ws.send(JSON.stringify(data)); + } + + public close(): void { + this.ws.off('message', this.onMessage); + this.ws.off('close', this.onClose); + this.ws.off('error', this.onError); + this.ws.close(); + } + + private onMessage = (rawData: WebSocket.RawData): void => { + let data: WebSocketData; + if (rawData instanceof Buffer) { + data = JSON.parse(rawData.toString()); + this.emit('message', data, this); + } + } + + private onClose = (code: number, reason: string): void => { + this.ws.removeAllListeners(); + + for (const subscription of this.subscriptions.values()) { + subscription.close(); + } + + this.subscriptions.clear(); + + this.emit('close', code, reason, this); + } + + private onError = (error: Error): void => { + this.emit('error', error, this); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/socket-item.ts b/projects/aas-server/src/app/live/socket-item.ts new file mode 100644 index 00000000..a37e826e --- /dev/null +++ b/projects/aas-server/src/app/live/socket-item.ts @@ -0,0 +1,15 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { LiveNode } from "common"; + +export interface SocketItem { + node: LiveNode; + subscribe(item: any): void; + unsubscribe(): void; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/live/socket-subscription.ts b/projects/aas-server/src/app/live/socket-subscription.ts new file mode 100644 index 00000000..84787a3f --- /dev/null +++ b/projects/aas-server/src/app/live/socket-subscription.ts @@ -0,0 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +/** Defines a WebSocket subscription. */ +export abstract class SocketSubscription { + /** Opens the subscription. */ + public abstract open(): void; + + /** Closes the subscription. */ + public abstract close(): void; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/logging/file-logger.ts b/projects/aas-server/src/app/logging/file-logger.ts new file mode 100644 index 00000000..7dda9a23 --- /dev/null +++ b/projects/aas-server/src/app/logging/file-logger.ts @@ -0,0 +1,183 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import winston from 'winston'; +import { stringFormat, Message } from 'common'; +import { createMessage, Logger } from './logger.js'; + +interface Record { + errors: Map; + warnings: Map; + messages: Map; +} + +/** + * Realizes the logger service. + */ +@singleton() +export class FileLogger extends Logger { + private readonly records = new Map(); + private readonly defaultRecord: Record = { + errors: new Map(), + warnings: new Map(), + messages: new Map() + }; + + private record = this.defaultRecord; + private recording = 0; + private context: string | null = null; + + constructor( + @inject('winston.Logger') private readonly logger: winston.Logger + ) { + super(); + } + + public override error(error: Error | string, ...args: any[]): void { + if (this.logger.isErrorEnabled()) { + let text: string | null = null; + if (error) { + if (error instanceof Error) { + text = error.message; + } else if (typeof error === 'string') { + text = stringFormat(error, args); + } + } + + if (text) { + if (!this.record.errors.has(text)) { + this.logger.error(text); + } + + this.record.errors.set(text, Date.now()); + } + } + } + + public override warning(message: string, ...args: any[]): void { + if (this.logger.isWarnEnabled()) { + let text: string | null = null; + if (typeof message === 'string') { + text = stringFormat(message, args); + } + + if (text) { + if (!this.record.warnings.has(text)) { + this.logger.warn(text); + } + + this.record.warnings.set(text, Date.now()); + } + } + } + + public override info(message: string, ...args: any[]): void { + if (this.logger.isInfoEnabled()) { + let text: string | null = null; + if (typeof message === 'string') { + text = stringFormat(message, args); + } + + if (text) { + if (!this.record.messages.has(text)) { + this.logger.info(text); + } + + this.record.messages.set(text, Date.now()); + } + } + } + + public override debug(message: Error | string, ...args: any[]): void { + if (this.logger.isDebugEnabled()) { + let text: string | null = null; + if (message) { + if (message instanceof Error) { + text = message.message; + } else if (typeof message === 'string') { + text = stringFormat(message, args); + } + } + + if (text) { + this.logger.debug(text) + } + } + } + + public override log(message: Message): void { + switch (message.type) { + case 'Error': + if (this.logger.isErrorEnabled()) { + this.record.errors.set(message.text, message.timestamp); + } + break; + case 'Warning': + if (this.logger.isWarnEnabled()) { + this.record.warnings.set(message.text, message.timestamp); + } + break; + default: + if (this.logger.isInfoEnabled()) { + this.record.messages.set(message.text, message.timestamp); + } + break + } + } + + public override start(context: string): boolean { + if (this.recording === 0) { + this.context = context; + let record = this.records.get(this.context); + if (!record) { + record = { + errors: new Map(), + warnings: new Map(), + messages: new Map() + }; + + this.records.set(context, record); + } + + this.record = record; + } + + ++this.recording; + + return this.recording === 1; + } + + public override stop(): void { + if (this.recording === 1) { + this.recording = 0; + this.record = this.defaultRecord; + } else if (this.recording > 1) { + --this.recording; + } + } + + public override getMessages(): Message[] { + const messages: Message[] = []; + for (const record of [...this.records.values(), this.defaultRecord]) { + for (const tuple of record.errors) { + messages.push(createMessage('Error', tuple[0], tuple[1])); + } + + for (const tuple of record.warnings) { + messages.push(createMessage('Warning', tuple[0], tuple[1])); + } + + for (const tuple of record.messages) { + messages.push(createMessage('Info', tuple[0], tuple[1])); + } + } + + return messages.sort((a, b) => a.timestamp - b.timestamp); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/logging/logger-factory.ts b/projects/aas-server/src/app/logging/logger-factory.ts new file mode 100644 index 00000000..1c4fd8cf --- /dev/null +++ b/projects/aas-server/src/app/logging/logger-factory.ts @@ -0,0 +1,65 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import path from 'path'; +import fs from 'fs'; +import winston from 'winston'; +import DailyRotateFile from 'winston-daily-rotate-file'; +import { isMainThread } from 'worker_threads'; +import { noop } from 'lodash-es'; +import { DependencyContainer } from 'tsyringe'; + +/* istanbul ignore next */ +export class LoggerFactory { + constructor(private readonly container: DependencyContainer) { + } + + public create(): winston.Logger { + const filename = path.resolve('.', 'aas-server-%DATE%.log'); + if (isMainThread) { + this.deleteLogFiles(); + } + + const transport: DailyRotateFile = new DailyRotateFile({ + filename: filename, + datePattern: 'YYYY-MM-DD', + zippedArchive: false, + maxSize: '20m', + maxFiles: '2d', + format: winston.format.combine( + winston.format.timestamp(), + winston.format.json()) + }); + + const logger = winston.createLogger({ + level: process.env.NODE_ENV === 'production' ? 'info' : 'debug', + transports: [transport], + }); + + if (process.env.NODE_ENV !== 'production') { + logger.add(new winston.transports.Console({ + format: winston.format.simple(), + })); + } + + return logger; + } + + private deleteLogFiles(): void { + const dir = path.resolve('.'); + for (const file of fs.readdirSync(dir, { withFileTypes: true })) { + if (file.isFile() && path.extname(file.name) === '.log' && file.name.startsWith('aas-server')) { + try { + fs.rmSync(path.join(dir, file.name)); + } catch (error) { + noop(); + } + } + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/logging/logger.ts b/projects/aas-server/src/app/logging/logger.ts new file mode 100644 index 00000000..f91cf995 --- /dev/null +++ b/projects/aas-server/src/app/logging/logger.ts @@ -0,0 +1,78 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Message, MessageType } from "common"; +import { singleton } from 'tsyringe'; + +/** + * Defines a logger interface. + */ +export abstract class Logger { + /** + * Logs an error. + * @param error + * @param args Additional arguments. + */ + public abstract error(error: Error | string, ...args: any[]): void; + + /** + * Logs a warning. + * @param message The message format. + * @param args The format items. + */ + public abstract warning(message: string, ...args: any[]): void; + + /** + * Logs an information. + * @param message The message format. + * @param args The format items. + */ + public abstract info(message: string, ...args: any[]): void; + + /** + * Logs a debug message. + * @param message The message format. + * @param args The format items. + */ + public abstract debug(message: Error | string, ...args: any[]): void; + + /** + * Logs the specified message. + * @param message The message. + */ + public abstract log(message: Message): void; + + /** + * Starts the message recording for the specified context. + * @param context The context name. + * @returns `true` if the recording is started. + */ + public abstract start(context: string): boolean; + + /** + * Stops the message recording. + */ + public abstract stop(): void; + + /** + * Returns all messages. + */ + public abstract getMessages(): Message[]; +} + +export function createMessage(type: MessageType, text: string, timestamp: number): Message { + return { type, text, timestamp }; +} + +/** Represents a console for debug messages. */ +@singleton() +export class DebugConsole { + public debug(message: string | Error): void { + console.debug(message); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/logging/memory-logger.ts b/projects/aas-server/src/app/logging/memory-logger.ts new file mode 100644 index 00000000..082aedc5 --- /dev/null +++ b/projects/aas-server/src/app/logging/memory-logger.ts @@ -0,0 +1,144 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { Message, stringFormat } from 'common'; +import { createMessage, DebugConsole, Logger } from './logger.js'; + +export enum MemoryLoggerLevel { + All = 0, + Debug = 1, + Info = 2, + Warning = 3, + Error = 4, + Non = 5 +} + +@singleton() +export class MemoryLogger extends Logger { + private readonly errors = new Map(); + private readonly warnings = new Map(); + private readonly messages = new Map(); + private recording = 0; + + constructor( + @inject('LOG_LEVEL') private readonly logLevel: MemoryLoggerLevel, + @inject(DebugConsole) private readonly console: DebugConsole + ) { + super(); + } + + public error(error: string | Error, ...args: any[]): void { + if (this.logLevel <= MemoryLoggerLevel.Error) { + let text: string | undefined; + if (error) { + if (error instanceof Error) { + text = error.message; + } else if (typeof error === 'string') { + text = stringFormat(error, args); + } + + if (text) { + this.errors.set(text, Date.now()); + } + } + } + } + + public warning(message: string, ...args: any[]): void { + if (this.logLevel <= MemoryLoggerLevel.Warning) { + if (typeof message === 'string') { + this.warnings.set(stringFormat(message, args), Date.now()); + } + } + } + + public info(message: string, ...args: any[]): void { + if (this.logLevel <= MemoryLoggerLevel.Info) { + if (typeof message === 'string') { + this.messages.set(stringFormat(message, args), Date.now()); + } + } + } + + public debug(message: string | Error, ...args: any[]): void { + if (this.logLevel <= MemoryLoggerLevel.Debug) { + { + let text: string | undefined; + if (message) { + if (message instanceof Error) { + text = message.message; + } else if (typeof message === 'string') { + text = stringFormat(message, args); + } + } + + if (text) { + this.console.debug(text); + } + } + } + } + + public log(message: Message): void { + switch (message.type) { + case 'Error': + if (this.logLevel <= MemoryLoggerLevel.Error) { + this.errors.set(message.text, message.timestamp); + } + break; + case 'Warning': + if (this.logLevel <= MemoryLoggerLevel.Warning) { + this.warnings.set(message.text, message.timestamp); + } + break; + default: + if (this.logLevel <= MemoryLoggerLevel.Info) { + this.messages.set(message.text, message.timestamp); + } + break + } + } + + public start(context: string): boolean { + if (this.recording === 0) { + this.errors.clear(); + this.warnings.clear(); + this.messages.clear(); + } + + ++this.recording; + + return this.recording === 1; + } + + public stop(): void { + if (this.recording === 1) { + this.recording = 0; + } else if (this.recording > 1) { + --this.recording; + } + } + + public getMessages(): Message[] { + const messages: Message[] = [] + for (const tuple of this.errors) { + messages.push(createMessage('Error', tuple[0], tuple[1])); + } + + for (const tuple of this.warnings) { + messages.push(createMessage('Warning', tuple[0], tuple[1])); + } + + for (const tuple of this.messages) { + messages.push(createMessage('Info', tuple[0], tuple[1])); + } + + return messages.sort((a, b) => a.timestamp - b.timestamp); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/mailer.ts b/projects/aas-server/src/app/mailer.ts new file mode 100644 index 00000000..272dd0ee --- /dev/null +++ b/projects/aas-server/src/app/mailer.ts @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import nodemailer from "nodemailer"; +import { Logger } from "./logging/logger.js"; + +@singleton() +export class Mailer { + private transporter: any; + + constructor( + @inject('Logger') private readonly logger: Logger) { + + this.transporter = nodemailer.createTransport({ + host: "smtp.example.com", + port: 587, + secure: false, + auth: { + user: "username", + pass: "password" + } + }); + } + + /** + * Sends a new password to the specified e-mail. + * @param email The e-mail address. + */ + public sendNewPassword(email: string, password: string): void { + throw new Error('Sending e-mails not implemented'); + } + + /** + * Sends an initial password to a new user withe the specified e-mail. + * @param email The e-mail of the new user. + */ + public sendPassword(email: string, password: string) { + throw new Error('Sending e-mails not implemented'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aas-package.ts b/projects/aas-server/src/app/packages/aas-package.ts new file mode 100644 index 00000000..97236ba8 --- /dev/null +++ b/projects/aas-server/src/app/packages/aas-package.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, aas } from "common"; +import { Logger } from "../logging/logger.js"; + +/** + * Represents a package that contains an Asset Administration Shell. + */ +export abstract class AASPackage { + protected readonly logger: Logger; + + constructor(logger: Logger) { + this.logger = logger; + } + + /** Gets the document that contains an Asset Administration Shell. */ + public abstract createDocumentAsync(): Promise; + + /** Gets the thumbnail of the current Asset Administration Shell */ + public abstract getThumbnailAsync(): Promise; + + /** + * Returns a read-only stream of a file in a package with the specified path. + * @param env The Asset Administration Shell Environment. + * @param file The File element. + * @returns A readable stream. + */ + public abstract openReadStreamAsync(env: aas.Environment, file: aas.File): Promise; + + /** + * Applies the state of the source document into the destination document. + * @param source The source document. + * @param content The new document content. + */ + public abstract commitDocumentAsync(source: AASDocument, content: aas.Environment): Promise; + + protected normalize(path: string): string { + path = path.replace(/\\/g, '/'); + if (path.charAt(0) === '/') { + path = path.slice(1); + } else if (path.startsWith('./')) { + path = path.slice(2); + } + + return path; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aas-reader.ts b/projects/aas-server/src/app/packages/aas-reader.ts new file mode 100644 index 00000000..38155223 --- /dev/null +++ b/projects/aas-server/src/app/packages/aas-reader.ts @@ -0,0 +1,49 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from 'common'; + +export abstract class AASReader { + + public abstract readEnvironment(): aas.Environment; + + public abstract read(data: string | object): aas.Referable; + + protected createIdShort(id: string): string { + if (id.startsWith('http')) { + return id.split('/')[0]; + } else if (id.startsWith('urn:')) { + return id.split(':')[0]; + } + + return id; + } + + protected normalize(path: string): string { + path = path.replace(/\\/g, '/'); + if (path.charAt(0) === '/') { + path = path.slice(1); + } else if (path.startsWith('./')) { + path = path.slice(2); + } + + return path; + } + + protected createReference(parent: aas.Reference, child: aas.Referable): aas.Reference { + return { + type: 'ModelReference', + keys: [ + ...parent.keys.map(key => ({ ...key })), + { + type: child.modelType as aas.KeyTypes, + value: child.idShort, + }] + }; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aas-resource-factory.ts b/projects/aas-server/src/app/packages/aas-resource-factory.ts new file mode 100644 index 00000000..8de53992 --- /dev/null +++ b/projects/aas-server/src/app/packages/aas-resource-factory.ts @@ -0,0 +1,101 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { ApplicationError } from 'common'; +import { Logger } from "../logging/logger.js"; +import { AASResource } from "./aas-resource.js"; +import { AasxDirectory } from "./aasx-directory/aasx-directory.js"; +import { AasxServerV0 } from "./aasx-server/aasx-server-v0.js"; +import { AasxServerV3 } from "./aasx-server/aasx-server-v3.js"; +import { OpcuaServer } from "./opcua/opcua-server.js"; +import { ERRORS } from '../errors.js'; +import { parseUrl } from '../convert.js'; +import { FileStorageFactory } from '../file-storage/file-storage-factory.js'; +import { FileStorage } from '../file-storage/file-storage.js'; + +@singleton() +export class AASResourceFactory { + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(FileStorageFactory) private readonly fileStorageFactory: FileStorageFactory + ) { } + + /** + * Creates a concrete realization of an `AASSource`. + * @param url The URL of the container. + * @returns A new instance of . + */ + public create(url: string | URL): AASResource { + let source: AASResource; + const temp = typeof url === 'string' ? parseUrl(url) : url; + switch (temp.protocol) { + case 'http:': + case 'https': + const version = temp.searchParams.get('version') ?? '3.0'; + if (version === '3.0') { + source = new AasxServerV3(this.logger, temp); + } else if (version === '0.0') { + source = new AasxServerV0(this.logger, temp); + } else { + throw new Error(`AASX server version ${version} is not supported.`); + } + break; + case 'opc.tcp:': + source = new OpcuaServer(this.logger, temp); + break; + case 'file:': + source = new AasxDirectory(this.logger, temp, this.createLocalFileStorage(temp)); + break; + default: + throw new Error('Not implemented.'); + } + + return source; + } + + /** + * Tests whether the specified URL is a valid and supported AAS resource. + * @param logger The logger. + * @param url The current URL. + */ + public async testAsync(url: URL): Promise { + try { + switch (url.protocol) { + case 'http:': + case 'https:': + const version = url.searchParams.get('version') ?? '3.0'; + if (version === '3.0') { + await new AasxServerV3(this.logger, url).testAsync(); + } else if (version === '0.0') { + await new AasxServerV0(this.logger, url).testAsync(); + } else { + throw new Error('Not implemented.'); + } + break; + case 'opc.tcp:': + await new OpcuaServer(this.logger, url).testAsync(); + break; + case 'file:': + await new AasxDirectory(this.logger, url, this.createLocalFileStorage(url)).testAsync(); + break; + default: + throw new Error('Not implemented.'); + } + } catch (error) { + throw new ApplicationError( + `"${url.href}" addresses an invalid or not supported AAS resource.`, + ERRORS.InvalidContainerUrl, + url.href); + } + } + + private createLocalFileStorage(url: URL): FileStorage { + return this.fileStorageFactory.create(`file:///endpoints` + url.pathname); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aas-resource.ts b/projects/aas-server/src/app/packages/aas-resource.ts new file mode 100644 index 00000000..7af441f7 --- /dev/null +++ b/projects/aas-server/src/app/packages/aas-resource.ts @@ -0,0 +1,110 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, LiveRequest } from "common"; +import { Logger } from "../logging/logger.js"; +import { SocketClient } from "../live/socket-client.js"; +import { AASPackage } from "./aas-package.js"; +import { SocketSubscription } from "../live/socket-subscription.js"; + +/** Represents a resource of Asset Administration Shells. */ +export abstract class AASResource { + constructor( + protected readonly logger: Logger, + url: string | URL) { + this.url = typeof url === 'string' ? new URL(url) : url; + + this.baseUrl = new URL(this.url); + this.baseUrl.hash = ''; + this.baseUrl.search = ''; + } + + /** Indicates whether an active connection is established. */ + public abstract readonly isOpen: boolean; + + /** The URL of the AAS source inclusive search parameters. */ + public readonly url: URL; + + /** The base URL of the AAS source without search parameters. */ + public readonly baseUrl: URL; + + /** Indicates whether the AAS source is read-only. */ + public abstract readonly readOnly: boolean; + + /** Indicates whether the AAS source provides live data. */ + public abstract readonly onlineReady: boolean; + + /** Tests the connection to the AAS source. */ + public abstract testAsync(): Promise; + + /** Opens the container. */ + public abstract openAsync(): Promise; + + /** Closes the container. */ + public abstract closeAsync(): Promise; + + /** ToDo */ + public abstract createPackage(address: string): AASPackage; + + /** + * Creates a WebSocket subscription. + * @param client The client. + * @param message The message. + * @param env The AAS environment. + */ + public abstract createSubscription( + client: SocketClient, + message: LiveRequest, + env: aas.Environment): SocketSubscription; + + /** + * Downloads an aasx package form the current source. + * @param aasIdentifier The AAS identifier. + * @returns A readable stream. + */ + public abstract getPackageAsync(aasIdentifier: string, name: string): Promise; + + /** + * Uploads an AASX package. + * @param file The AASX package file. + */ + public abstract postPackageAsync(file: Express.Multer.File): Promise; + + /** + * Delete an aasx package from the current source. + * @param aasIdentifier The AAS identifier. + * @param name The name of the package in the source. + */ + public abstract deletePackageAsync(aasIdentifier: string, name: string): Promise; + + /** + * Invokes the specified operation synchronously. + * @param env The current AAS environment. + * @param operation The operation to invoke. + * @returns The invoked operation. + */ + public abstract invoke(env: aas.Environment, operation: aas.Operation): Promise; + + /** + * Reads the value of the current Blob element. + * @param env The AAS environment. + * @param submodelId The Submodel to which the Blob belongs. + * @param idShortPath The path from the Submodel to the Blob element. + * @returns The Blob value. + */ + public abstract getBlobValueAsync(env: aas.Environment, submodelId: string, idShortPath: string): Promise; + + /** + * Resolves a new URL from the base URL and the specified URL. + * @param url The URL. + * @returns A new URL. + */ + protected resolve(url: string): URL { + return new URL(url, this.baseUrl); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aas-writer.ts b/projects/aas-server/src/app/packages/aas-writer.ts new file mode 100644 index 00000000..c0ea0cf6 --- /dev/null +++ b/projects/aas-server/src/app/packages/aas-writer.ts @@ -0,0 +1,15 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from 'common'; + +/** */ +export abstract class AASWriter { + public abstract writeEnvironment(env: aas.Environment): any; + public abstract write(referable: aas.Referable): any; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aasx-directory/aasx-directory.ts b/projects/aas-server/src/app/packages/aasx-directory/aasx-directory.ts new file mode 100644 index 00000000..e89bb4e2 --- /dev/null +++ b/projects/aas-server/src/app/packages/aasx-directory/aasx-directory.ts @@ -0,0 +1,122 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, ApplicationError, LiveRequest } from 'common'; +import { readFile } from 'fs/promises'; +import { ERRORS } from '../../errors.js'; +import { FileStorage } from '../../file-storage/file-storage.js'; +import { Logger } from '../../logging/logger.js'; +import { SocketClient } from '../../live/socket-client.js'; +import { AASPackage } from '../aas-package.js'; +import { AASResource } from '../aas-resource.js'; +import { AasxPackage } from './aasx-package.js'; +import { SocketSubscription } from '../../live/socket-subscription.js'; + +export class AasxDirectory extends AASResource { + private reentry = 0; + + constructor(logger: Logger, url: string | URL, private readonly fileStorage: FileStorage) { + super(logger, url); + } + + public get isOpen(): boolean { + return this.reentry > 0; + } + + public readonly readOnly = true; + + public readonly onlineReady = false; + + public getStorage(): FileStorage { + return this.fileStorage; + } + + public async testAsync(): Promise { + if (this.reentry === 0) { + try { + await this.openAsync(); + } finally { + await this.closeAsync(); + } + } + } + + public async openAsync(): Promise { + if (this.reentry === 0) { + if (!(await this.fileStorage.exists('.'))) { + throw new Error(`The directory '${this.baseUrl}' does not exist.`); + } + + ++this.reentry; + } + } + + public closeAsync(): Promise { + return new Promise(resolve => { + if (this.reentry > 0) { + --this.reentry; + } + + resolve(); + }); + } + + public createPackage(address: string): AASPackage { + return new AasxPackage(this.logger, this, address); + } + + public createSubscription( + client: SocketClient, + message: LiveRequest, + env: aas.Environment): SocketSubscription { + throw new Error('Not implemented.'); + } + + public async getPackageAsync(_: string, name: string): Promise { + if (!(await this.fileStorage.exists(name))) { + throw new Error(`The file '${name}' does not exist.`); + } + + return this.fileStorage.createReadStream(name); + } + + public async postPackageAsync(file: Express.Multer.File): Promise { + const exists = await this.fileStorage.exists(file.filename); + if (exists) { + throw new ApplicationError( + `A file with the name '${file.filename}' already exists.`, + ERRORS.FileAlreadyExists, + file.filename); + } + + try { + const buffer = await readFile(file.path); + await this.fileStorage.writeFile(file.filename, buffer); + const aasPackage = new AasxPackage(this.logger, this, file.filename); + return aasPackage; + } catch (error) { + if (await this.fileStorage.exists(file.filename)) { + await this.fileStorage.unlink(file.filename); + } + + throw error; + } + } + + public deletePackageAsync(_: string, name: string): Promise { + return this.fileStorage.unlink(name); + } + + public invoke(env: aas.Environment, operation: aas.Operation): Promise { + throw new Error('Not implemented.'); + } + + public getBlobValueAsync(env: aas.Environment, submodelId: string, idShortPath: string): Promise { + throw new Error('Not implemented.'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aasx-directory/aasx-package.ts b/projects/aas-server/src/app/packages/aasx-directory/aasx-package.ts new file mode 100644 index 00000000..562d7e89 --- /dev/null +++ b/projects/aas-server/src/app/packages/aasx-directory/aasx-package.ts @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { basename, extname } from 'path'; +import jszip from 'jszip'; +import xpath from 'xpath'; +import { DOMParser } from '@xmldom/xmldom'; +import { AasxDirectory } from './aasx-directory.js'; +import { AASDocument, aas } from 'common'; + +import { Lazy } from '../../lazy.js'; +import { AASPackage } from '../aas-package.js'; +import { AASResource } from '../aas-resource.js'; +import { Logger } from '../../logging/logger.js'; +import { XmlReader } from '../xml-reader.js'; +import { AASReader } from '../aas-reader.js'; +import { JsonReaderV2 } from '../json-reader-v2.js'; +import { JsonReader } from '../json-reader.js'; +import * as aasV2 from '../../types/aas-v2.js'; + +export class AasxPackage extends AASPackage { + private readonly file: string; + private readonly source: AasxDirectory; + private readonly zip: Lazy; + private originName: string | null = null; + + constructor(logger: Logger, handle: AASResource, file: string) { + super(logger); + + this.source = handle as AasxDirectory; + this.file = file; + this.zip = new Lazy(this.initializeZip.bind(this)); + } + + public async createDocumentAsync(): Promise { + let document: AASDocument; + const format = extname(this.file); + if (format === '.aasx') { + const reader = await this.createReaderAsync(); + const environment = reader.readEnvironment(); + const id = environment.assetAdministrationShells[0].id; + document = { + id: id, + container: this.source.url.href, + endpoint: { type: 'file', address: this.file }, + idShort: environment.assetAdministrationShells[0].idShort, + timeStamp: Date.now(), + readonly: this.source.readOnly, + onlineReady: this.source.onlineReady, + modified: false, + content: environment + }; + } else { + throw new Error(`Asset format ${format} is not supported.`); + } + + return document; + } + + public commitDocumentAsync(): Promise { + throw new Error('Method not implemented.'); + } + + public async openReadStreamAsync(_: aas.Environment, file: aas.File): Promise { + if (!file.value) { + throw new Error('Invalid operation.'); + } + + const name = this.normalize(file.value); + const stream = (await this.zip.getValueAsync()).file(name)?.nodeStream(); + if (!stream) { + throw Error(`ZIP entry '${name}' could not be opened.`); + } + + return stream; + } + + public async getThumbnailAsync(): Promise { + let stream: NodeJS.ReadableStream | undefined; + const relationships = await this.getRelationshipsAsync('_rels/.rels'); + for (const relationship of relationships) { + if (relationship.getAttribute('Type') === 'http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail') { + const value = relationship.getAttribute('Target'); + if (value) { + stream = (await this.zip.getValueAsync()).file(this.normalize(value))?.nodeStream(); + if (stream) { + break; + } + } + } + } + + if (!stream) { + throw new Error(`${this.file} has no thumbnail.`); + } + + return stream; + } + + private async createReaderAsync(): Promise { + const name = await this.getOriginNameAsync(); + const extension = extname(name); + switch (extension) { + case '.xml': + const xml = await this.getZipEntryAsync(name); + return new XmlReader(this.logger, xml); + case '.json': + const env = JSON.parse(await this.getZipEntryAsync(name)); + return this.createJsonReader(env); + default: + throw new Error(`The AAS origin ${extension} is not supported.`); + } + } + + private async initializeZip(): Promise { + const data = await this.source.getStorage().readFile(this.file); + return await jszip.loadAsync(data); + } + + private async getOriginNameAsync(): Promise { + if (this.originName === null) { + const relationships = await this.getRelationshipsAsync('aasx/_rels/aasx-origin.rels'); + for (const relationship of relationships) { + if (relationship.getAttribute('Type') === 'http://www.admin-shell.io/aasx/relationships/aas-spec') { + this.originName = relationship.getAttribute('Target'); + break; + } + } + + if (this.originName === null) { + throw new Error('Unable to determine origin name.'); + } + } + + return this.originName; + } + + private async getRelationshipsAsync(path: string): Promise { + const xml = await this.getZipEntryAsync(path); + const xmldoc = new DOMParser().parseFromString(xml); + const opnxml = xpath.useNamespaces({ opnxml: 'http://schemas.openxmlformats.org/package/2006/relationships' }); + return opnxml('/opnxml:Relationships/opnxml:Relationship', xmldoc) as Element[]; + } + + private async getZipEntryAsync(path: string, contentType?: jszip.OutputType): Promise { + if (path.charAt(0) === '/') { + path = path.slice(1); + } + + if (!contentType) { + contentType = this.getContentType(basename(path)); + } + + const zip = await this.zip.getValueAsync(); + const file = zip.file(path); + if (file === null) { + throw new Error(`${path} is not a valid ZIP file.`) + } + + return await file.async(contentType) as string; + } + + private getContentType(fileName: string): jszip.OutputType { + let contentType: jszip.OutputType; + const extension = this.getExtension(fileName); + switch (extension) { + case '.xml': + case '.rels': + case '.json': + contentType = 'string'; + break; + case '.png': + case '.jpeg': + case '.jpg': + contentType = 'uint8array'; + break; + default: + throw new Error('Not supported extension ' + extension); + } + + return contentType; + } + + private getExtension(fileName: string): string { + const index = fileName.lastIndexOf('.'); + return index >= 0 ? fileName.substr(index).toLowerCase() : ''; + } + + private createJsonReader(env: object): AASReader { + if ('assets' in env) { + return new JsonReaderV2(this.logger, env as aasV2.AssetAdministrationShellEnvironment); + } + + if ('assetAdministrationShells' in env && 'submodels' in env && 'conceptDescriptions' in env) { + return new JsonReader(this.logger, env as aas.Environment); + } + + throw new Error('Not implemented.'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aasx-server/aasx-server-package.ts b/projects/aas-server/src/app/packages/aasx-server/aasx-server-package.ts new file mode 100644 index 00000000..00a7d150 --- /dev/null +++ b/projects/aas-server/src/app/packages/aasx-server/aasx-server-package.ts @@ -0,0 +1,72 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument, diffAsync, aas } from 'common'; +import { AASPackage } from '../aas-package.js'; +import { AASResource } from '../aas-resource.js'; +import { Logger } from '../../logging/logger.js'; +import { AasxServer } from './aasx-server.js'; + +export class AasxServerPackage extends AASPackage { + private readonly source: AasxServer; + private readonly idShort: string; + + /** + * Creates a new AAS-Registry package. + * @param logger The logger service. + * @param source The handle. + * @param idShort The name of the AAS. + */ + constructor(logger: Logger, source: AASResource, idShort: string) { + super(logger); + + this.source = source as AasxServer; + this.idShort = idShort; + } + + public getThumbnailAsync(): Promise { + return Promise.reject(new Error('Not implemented.')); + } + + public openReadStreamAsync(env: aas.Environment, file: aas.File): Promise { + if (!file) { + throw new Error('Invalid operation.'); + } + + return this.source.openFileAsync(env.assetAdministrationShells[0], file); + } + + public async createDocumentAsync(): Promise { + const environment = await this.source.readEnvironmentAsync(this.idShort); + const document: AASDocument = { + id: environment.assetAdministrationShells[0].id, + container: this.source.url.href, + endpoint: { type: 'http', address: this.idShort }, + idShort: environment.assetAdministrationShells[0].idShort, + timeStamp: Date.now(), + readonly: this.source.readOnly, + modified: false, + onlineReady: true, + content: environment + }; + + return document; + } + + public async commitDocumentAsync(source: AASDocument, content: aas.Environment): Promise { + let messages: string[] | undefined; + if (source.content && content) { + const diffs = await diffAsync(source.content, content); + if (diffs.length > 0) { + messages = await this.source.commitAsync(source.content, content, diffs); + } + } + + return messages ?? []; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aasx-server/aasx-server-v0.ts b/projects/aas-server/src/app/packages/aasx-server/aasx-server-v0.ts new file mode 100644 index 00000000..3d3135c7 --- /dev/null +++ b/projects/aas-server/src/app/packages/aasx-server/aasx-server-v0.ts @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, DifferenceItem, selectSubmodel } from 'common'; +import { Logger } from '../../logging/logger.js'; +import { AASPackage } from '../aas-package.js'; +import { JsonReaderV2 } from '../json-reader-v2.js'; +import { AasxServer } from './aasx-server.js'; +import { JsonWriterV2 } from '../json-writer-v2.js'; +import * as aasV2 from '../../types/aas-v2.js'; + +interface AASList { + aaslist: string[]; +} + +export class AasxServerV0 extends AasxServer { + constructor(logger: Logger, url: string | URL) { + super(logger, url); + } + + public readonly readOnly = false; + + public readonly onlineReady = true; + + public async getShellsAsync(): Promise { + const value = await this.message.get(this.resolve('/server/listaas')); + return value.aaslist.map(item => item.split(' : ')[1].trim()) + } + + public async readEnvironmentAsync(id: string): Promise { + const url = this.resolve(`/aas/${id}/aasenv`); + const sourceEnv = await this.message.get(url); + return new JsonReaderV2(this.logger, sourceEnv).readEnvironment(); + } + + public async commitAsync( + source: aas.Environment, + destination: aas.Environment, + diffs: DifferenceItem[]): Promise { + const messages: string[] = []; + const updateSubmodels = new Set(); + const deleteSubmodels = new Set(); + for (const diff of diffs) { + if (diff.type === 'changed' || diff.type === 'inserted') { + if (diff.sourceElement) { + const submodel = selectSubmodel(source, diff.sourceElement); + if (submodel && !updateSubmodels.has(submodel)) { + updateSubmodels.add(submodel); + } + } + } else if (diff.type === 'deleted') { + if (diff.destinationElement) { + if (diff.destinationElement.modelType === 'Submodel') { + const submodel = diff.destinationElement as aas.Submodel; + if (!deleteSubmodels.has(submodel)) { + deleteSubmodels.add(submodel); + if (updateSubmodels.has(submodel)) { + updateSubmodels.delete(submodel); + } + } + } else { + const submodel = selectSubmodel(destination, diff.destinationElement); + if (submodel && !updateSubmodels.has(submodel) && !deleteSubmodels.has(submodel)) { + updateSubmodels.add(submodel); + } + } + } + } + } + + if (updateSubmodels.size > 0) { + messages.push(...await this.putSubmodelsAsync(destination, updateSubmodels.values())); + } + + if (deleteSubmodels.size > 0) { + messages.push(...await this.deleteSubmodelsAsync(destination, deleteSubmodels.values())); + } + + return messages; + } + + public resolveNodeId(shell: aas.AssetAdministrationShell, nodeId: string): string { + const items = nodeId.split('.')[1].split('/'); + const path = items.slice(1).join('/'); + return this.resolve(`/aas/${shell.idShort}/submodels/${items[0]}/elements/${path}/value`).href; + } + + public async openFileAsync(shell: aas.AssetAdministrationShell, file: aas.File): Promise { + const url = await this.getFileUrlAsync(shell.idShort, file.value!); + return await this.message.getResponse(url); + } + + public getPackageAsync(aasId: string, name: string): Promise { + throw new Error('Not implemented.'); + } + + public postPackageAsync(file: Express.Multer.File): Promise { + throw new Error('Not implemented.'); + } + + public deletePackageAsync(aasIdentifier: string): Promise { + throw new Error('Not implemented.'); + } + + public invoke(env: aas.Environment, operation: aas.Operation): Promise { + throw new Error('Not implemented.'); + } + + public getBlobValueAsync(env: aas.Environment, submodelId: string, idShortPath: string): Promise { + throw new Error('Not implemented.'); + } + + private async getFileUrlAsync(idShort: string, address: string): Promise { + const listAAS = await this.message.get(this.resolve('/server/listaas')); + for (const aas of listAAS.aaslist) { + const items = aas.split(':'); + if (items[1].trim() === idShort) { + const index = items[0].trim(); + return this.resolve('/server/getfile/' + index + address); + } + } + + throw new Error(`${idShort}: Unable to resolve image address '${address}'.`); + } + + private async putSubmodelsAsync( + destination: aas.Environment, + submodels: IterableIterator): Promise { + const messages: string[] = []; + const aas = destination.assetAdministrationShells[0].idShort; + for (const submodel of submodels) { + messages.push(await this.putSubmodelAsync(aas, new JsonWriterV2().write(submodel))); + } + + return messages; + } + + private async deleteSubmodelsAsync( + destination: aas.Environment, + elements: IterableIterator): Promise { + const messages: string[] = []; + const aas = destination.assetAdministrationShells[0].idShort; + for (const element of elements) { + messages.push(await this.deleteSubmodelAsync(aas, element.idShort)); + } + + return messages; + } + + private async putSubmodelAsync(aas: string, submodel: aas.Submodel): Promise { + return await this.message.put( + this.resolve('/aas/' + aas + '/submodels/'), + new JsonWriterV2().write(submodel)); + } + + private async deleteSubmodelAsync(aas: string, submodelId: string): Promise { + return await this.message.delete(this.resolve('/aas/' + aas + '/submodels/' + submodelId)); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aasx-server/aasx-server-v3.ts b/projects/aas-server/src/app/packages/aasx-server/aasx-server-v3.ts new file mode 100644 index 00000000..cf38977a --- /dev/null +++ b/projects/aas-server/src/app/packages/aasx-server/aasx-server-v3.ts @@ -0,0 +1,284 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import FormData from 'form-data'; +import { cloneDeep } from 'lodash-es'; +import { createReadStream } from 'fs'; +import { encodeBase64Url } from '../../convert.js'; +import { AasxServer } from './aasx-server.js'; +import { Logger } from '../../logging/logger.js'; +import { AASPackage } from '../aas-package.js'; +import { JsonReader } from '../json-reader.js'; +import { JsonWriter } from '../json-writer.js'; +import { + aas, + ApplicationError, + DifferenceItem, + getIdShortPath, + isAssetAdministrationShell, + isSubmodel, + isSubmodelElement, + selectSubmodel +} from 'common'; +import { ERRORS } from '../../errors.js'; + +interface PackageDescriptor { + aasIds: string[]; + packageId: string; +} + +interface OperationRequest { + inputVariables?: aas.OperationVariable[]; + inoutputVariables?: aas.OperationVariable[]; + clientTimeoutDuration?: string; +} + +export interface Message { + code?: string; + correlationId?: string; + messageType: 'Undefined' | 'Info' | 'Warning' | 'Error' | 'Exception'; + text: string; + timeStamp?: string; +} + +export interface OperationResult { + messages?: Message[]; + executionState: 'Initiated' | 'Running' | 'Completed' | 'Canceled' | 'Failed' | 'Timeout'; + success: boolean; + outputVariables?: aas.OperationVariable[]; + inoutputVariables?: aas.OperationVariable[]; +} + +interface PagedResultPagingMetadata { + cursor?: string; +} + +interface PagedResult { + result: T[]; + paging_metadata: PagedResultPagingMetadata; +} + +export class AasxServerV3 extends AasxServer { + constructor(logger: Logger, url: string | URL) { + super(logger, url); + } + + public readonly readOnly = false; + + public readonly onlineReady = true; + + public async getShellsAsync(): Promise { + const pagedResult = await this.message.get>( + this.resolve('/shells')); + + return pagedResult.result.map(shell => shell.id); + } + + public async readEnvironmentAsync(id: string): Promise { + const aasId = encodeBase64Url(id); + const shell = await this.message.get( + this.resolve(`/shells/${aasId}`)); + + const submodels: aas.Submodel[] = []; + if (shell.submodels) { + for (const reference of shell.submodels) { + const submodelId = encodeBase64Url(reference.keys[0].value); + try { + submodels.push(await this.message.get( + this.resolve(`/submodels/${submodelId}`))); + } catch (error) { + this.logger.error(`Unable to read Submodel "${reference.keys[0].value}": ${error?.message}`); + } + } + } + + const pagedResult = await this.message.get>( + this.resolve(`/concept-descriptions`)); + + const sourceEnv: aas.Environment = { + assetAdministrationShells: [shell], + submodels, + conceptDescriptions: pagedResult.result + }; + + return new JsonReader(this.logger, sourceEnv).readEnvironment(); + } + + public async commitAsync( + source: aas.Environment, + destination: aas.Environment, + diffs: DifferenceItem[]): Promise { + const messages: string[] = []; + const aasId = encodeBase64Url(destination.assetAdministrationShells[0].id); + for (const diff of diffs) { + if (diff.type === 'inserted') { + if (isSubmodel(diff.sourceElement)) { + messages.push(await this.postSubmodelAsync(aasId, diff.sourceElement)); + } else if (isSubmodelElement(diff.sourceElement)) { + const submodel = this.getSubmodel(destination, diff.destinationParent); + messages.push(await this.postSubmodelElementAsync(submodel, diff.sourceElement)); + } else { + throw new Error(`Inserting "${diff?.sourceElement?.modelType}" is not implemented.`); + } + } else if (diff.type === 'changed') { + if (isSubmodel(diff.sourceElement)) { + messages.push(await this.putSubmodelAsync(aasId, diff.sourceElement)); + } else if (isSubmodelElement(diff.sourceElement)) { + const submodel = this.getSubmodel(destination, diff.destinationElement); + messages.push(await this.putSubmodelElementAsync(submodel, diff.sourceElement as aas.SubmodelElement)); + } else if (isAssetAdministrationShell(diff.sourceElement)) { + messages.push(await this.putShellAsync(diff.sourceElement)); + } else { + throw new Error(`Updating "${diff?.sourceElement?.modelType}" is not implemented.`); + } + } else if (diff.type === 'deleted') { + if (isSubmodel(diff.destinationElement)) { + messages.push(await this.deleteSubmodelAsync(diff.destinationElement.id)); + } else if (isSubmodelElement(diff.destinationElement)) { + const submodel = this.getSubmodel(destination, diff.destinationParent); + messages.push(await this.deleteSubmodelElementAsync(submodel, diff.destinationElement)); + } else { + throw new Error(`Deleting "${diff?.destinationElement?.modelType}" is not implemented.`); + } + } + } + + return messages; + } + + public async openFileAsync(shell: aas.AssetAdministrationShell, file: aas.File): Promise { + const aasId = encodeBase64Url(shell.id); + const smId = encodeBase64Url(file.parent!.keys[0].value); + const path = getIdShortPath(file); + const url = this.resolve(`/shells/${aasId}/submodels/${smId}/submodel/submodelElements/${path}/attachment`); + return await this.message.getResponse(url); + } + + public resolveNodeId(shell: aas.AssetAdministrationShell, nodeId: string): string { + const aasId = encodeBase64Url(shell.id); + const items = nodeId.split('.'); + const path = items[1].split('/').slice(1).join('.'); + return this.resolve(`/shells/${aasId}/aas/submodels/${items[0]}/submodel/submodel-elements/${path}`).href; + } + + public async getPackageAsync(aasIdentifier: string): Promise { + const aasId = encodeBase64Url(aasIdentifier); + const descriptors: PackageDescriptor[] = await this.message.get(this.resolve(`/packages?aasId=${aasId}`)); + const packageId = encodeBase64Url(descriptors[0].packageId); + return await this.message.getResponse(this.resolve(`/packages/${packageId}`)); + } + + public async postPackageAsync(file: Express.Multer.File): Promise { + const formData = new FormData(); + formData.append('file', createReadStream(file.path)); + formData.append('fileName', file.filename); + await this.message.post(this.resolve(`/packages`), formData); + return undefined; + } + + public deletePackageAsync(aasIdentifier: string): Promise { + throw new Error('Not implemented.'); + } + + public async invoke(env: aas.Environment, operation: aas.Operation): Promise { + if (!operation.parent) { + throw new Error('Invalid operation.'); + } + + const aasId = encodeBase64Url(env.assetAdministrationShells[0].id); + const smId = encodeBase64Url(selectSubmodel(env, operation)!.id); + const path = getIdShortPath(operation); + const request: OperationRequest = { + inputVariables: cloneDeep(operation.inputVariables), + inoutputVariables: cloneDeep(operation.inoutputVariables), + }; + + const result: OperationResult = await this.message.post( + this.resolve(`/shells/${aasId}/submodels/${smId}/submodel-elements/${path}/invoke`), + request); + + if (!result.success) { + throw new ApplicationError( + `Invoking the operation ${operation.idShort} failed: {0}`, + ERRORS.InvokeOperationFailed, + result.messages?.map(message => message.text).join(' ') ?? 'No messages.'); + } + + return { ...operation, outputVariables: result.outputVariables, inoutputVariables: result.inoutputVariables }; + } + + public async getBlobValueAsync(env: aas.Environment, submodelId: string, idShortPath: string): Promise { + const blob = await this.message.get( + this.resolve(`/submodels/${submodelId}/submodel/submodel-elements/${idShortPath}/?extent=WithBlobValue`)); + + if (!blob) { + throw new Error(`Blob element "${submodelId}.${idShortPath}" does not exist.`) + } + + return blob.value; + } + + private async putShellAsync(shell: aas.AssetAdministrationShell): Promise { + const aasId = encodeBase64Url(shell.id); + return await this.message.put( + this.resolve(`/shells/${aasId}`), + new JsonWriter().write(shell)); + } + + private async putSubmodelAsync(aasId: string, submodel: aas.Submodel): Promise { + const smId = encodeBase64Url(submodel.id); + return await this.message.put( + this.resolve(`/shells/${aasId}/aas/submodels/${smId}/submodel`), + new JsonWriter().write(submodel)); + } + + private async postSubmodelAsync(aasId: string, submodel: aas.Submodel): Promise { + return await this.message.post( + this.resolve(`/submodels?aasIdentifier=${aasId}`), new JsonWriter().write(submodel)); + } + + private async deleteSubmodelAsync(smId: string): Promise { + return await this.message.delete(this.resolve(`/submodels/${encodeBase64Url(smId)}`)); + } + + private async putSubmodelElementAsync(submodel: aas.Submodel, submodelElement: aas.SubmodelElement): Promise { + const smId = encodeBase64Url(submodel.id); + const path = getIdShortPath(submodelElement); + return await this.message.put( + this.resolve(`/submodels/${smId}/submodel-elements/${path}`), + new JsonWriter().write(submodelElement)); + } + + private async postSubmodelElementAsync(submodel: aas.Submodel, submodelElement: aas.SubmodelElement): Promise { + const smId = encodeBase64Url(submodel.id); + const path = getIdShortPath(submodelElement); + return await this.message.post( + this.resolve(`/submodels/${smId}/submodel-elements/${path}`), + new JsonWriter().write(submodelElement)); + } + + private async deleteSubmodelElementAsync(submodel: aas.Submodel, submodelElement: aas.SubmodelElement): Promise { + const smId = encodeBase64Url(submodel.id); + const path = getIdShortPath(submodelElement); + return await this.message.delete( + this.resolve(`/submodels/${smId}/submodel/submodel-elements/${path}`)); + } + + private getSubmodel(env: aas.Environment, referable?: aas.Referable): aas.Submodel { + if (!referable) { + throw new Error('Argument undefined.'); + } + + const submodel = selectSubmodel(env, referable); + if (!submodel) { + throw new Error('Invalid operation.'); + } + + return submodel; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/aasx-server/aasx-server.ts b/projects/aas-server/src/app/packages/aasx-server/aasx-server.ts new file mode 100644 index 00000000..33aa07e5 --- /dev/null +++ b/projects/aas-server/src/app/packages/aasx-server/aasx-server.ts @@ -0,0 +1,129 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, convertFromString, DifferenceItem, LiveRequest } from 'common'; +import { ServerMessage } from '../server-message.js'; +import { Logger } from '../../logging/logger.js'; +import { HttpSubscription } from '../../live/http/http-subscription.js'; +import { SocketClient } from '../../live/socket-client.js'; +import { AASPackage } from '../aas-package.js'; +import { AASResource } from '../aas-resource.js'; +import { AasxServerPackage } from './aasx-server-package.js'; +import { SocketSubscription } from '../../live/socket-subscription.js'; + +interface PropertyValue { + value: string; +} + +/** Provides access to an AASX-Server. */ +export abstract class AasxServer extends AASResource { + private reentry = 0; + + /** + * @param url The URL of the AASX-Server. + */ + constructor(logger: Logger, url: string | URL) { + super(logger, url); + } + + protected readonly message = new ServerMessage(); + + public get isOpen(): boolean { + return this.reentry > 0; + } + + public async testAsync(): Promise { + if (this.reentry === 0) { + try { + await this.openAsync(); + } finally { + await this.closeAsync(); + } + } + } + + + public async openAsync(): Promise { + if (this.reentry === 0) { + await this.message.checkUrlExist(this.url.href); + } + + ++this.reentry; + } + + public closeAsync(): Promise { + return new Promise((resolve, _) => { + if (this.reentry > 0) { + --this.reentry; + } + + resolve(); + }); + } + + public createPackage(address: string): AASPackage { + return new AasxServerPackage(this.logger, this, address); + } + + public createSubscription( + client: SocketClient, + message: LiveRequest, + env: aas.Environment): SocketSubscription { + return new HttpSubscription(this.logger, this, client, message, env); + } + + /** + * Gets the names of the Asset Administration Shells contained in the current AASX server. + * @returns The names of the AASs contained in the current AASX server. + */ + public abstract getShellsAsync(): Promise; + + /** + * Reads the environment of the AAS with the specified identifier. + * @param id The AAS identifier. + * @returns + */ + public abstract readEnvironmentAsync(id: string): Promise; + + /** + * ToDo + * @param source The source AAS. + * @param destination The destination + * @param diffs + */ + public abstract commitAsync( + source: aas.Environment, + destination: aas.Environment, + diffs: DifferenceItem[]): Promise; + + /** + * Opens the specified file from the AASX server. + * @param env The environment of the AAS. + * @param address The file. + * @returns A readable stream. + */ + public abstract openFileAsync(shell: aas.AssetAdministrationShell, file: aas.File): Promise; + + /** + * Reads the current value from a submodel element. + * @param url The path of the submodel element value. + * @param valueType The + * @returns The current value. + */ + public async readValueAsync(url: string, valueType: aas.DataTypeDefXsd): Promise { + const property = await this.message.get(new URL(url)); + return convertFromString(property.value, valueType); + } + + /** + * Returns the URL to a Property. + * @param aas The Asset Administration Shell. + * @param nodeId The path from the Submodel to the Property. + */ + public abstract resolveNodeId(aas: aas.AssetAdministrationShell, nodeId: string): string; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/json-reader-v2.ts b/projects/aas-server/src/app/packages/json-reader-v2.ts new file mode 100644 index 00000000..8c93342d --- /dev/null +++ b/projects/aas-server/src/app/packages/json-reader-v2.ts @@ -0,0 +1,834 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Logger } from '../logging/logger.js'; +import { AASReader } from './aas-reader.js'; +import { determineType, aas, isSubmodelElement, isIdentifiable } from 'common'; +import { encodeBase64Url } from '../convert.js'; +import * as aasv2 from '../types/aas-v2.js'; + +export class JsonReaderV2 extends AASReader { + private readonly origin: aasv2.AssetAdministrationShellEnvironment; + + constructor( + private readonly logger: Logger, + origin?: aasv2.AssetAdministrationShellEnvironment | string) { + super(); + + if (origin) { + this.origin = typeof origin === 'string' ? JSON.parse(origin) : origin; + } else { + this.origin = { assetAdministrationShells: [], assets: [], conceptDescriptions: [], submodels: [] }; + } + } + + public readEnvironment(): aas.Environment { + const conceptDescriptions = this.readConceptDescriptions(); + const assetAdministrationShells = this.readAssetAdministrationShells(); + const submodels = this.readSubmodels(); + return { assetAdministrationShells, submodels, conceptDescriptions }; + } + + public read(data: string | object): aas.Referable { + const source: aasv2.Referable = typeof data === 'string' ? JSON.parse(data) : data; + switch (source.modelType.name) { + case 'Asset': + case 'AssetAdministrationShell': + throw new Error('Invalid operation.'); + case 'Submodel': + return this.readSubmodel(source as aasv2.Submodel); + default: + return this.readSubmodelElement(source as aasv2.SubmodelElement, [])!; + } + } + + private readConceptDescriptions(): aas.ConceptDescription[] { + const conceptDescriptions: aas.ConceptDescription[] = []; + if (this.origin?.conceptDescriptions) { + for (const source of this.origin?.conceptDescriptions) { + conceptDescriptions.push(this.readConceptDescription(source)); + } + } + + return conceptDescriptions; + } + + private readAssetAdministrationShells(): aas.AssetAdministrationShell[] { + const shells: aas.AssetAdministrationShell[] = []; + if (this.origin?.assetAdministrationShells) { + for (const source of this.origin?.assetAdministrationShells) { + shells.push(this.readAssetAdministrationShell(source)); + } + } + + return shells; + } + + private readAssetAdministrationShell(source: aasv2.AssetAdministrationShell): aas.AssetAdministrationShell { + if (!source.asset) { + throw new Error('AssetAdministrationShell.asset'); + } + + const shell: aas.AssetAdministrationShell = { + ...this.readIdentifiable(source), + ...this.readHasDataSpecification(source), + assetInformation: this.readAssetInformation(this.origin.assets[0]) + }; + + if (source.derivedFrom) { + shell.derivedFrom = this.readReference(source.derivedFrom); + } + + if (source.administration) { + shell.administration = this.readAdministrationInformation(source.administration); + } + + if (source.submodels) { + shell.submodels = source.submodels.map(item => this.readReference(item)); + } + + return shell; + } + + private readAdministrationInformation(source: aasv2.AdministrativeInformation): aas.AdministrativeInformation { + const info: aas.AdministrativeInformation = {}; + if (source.revision) { + info.revision = source.revision; + } + + if (source.version) { + info.version = source.version; + } + + return info; + } + + private readConceptDescription(source: aasv2.ConceptDescription): aas.ConceptDescription { + const conceptDescription: aas.ConceptDescription = { + ...this.readIdentifiable(source), + ...this.readHasDataSpecification(source) + }; + + if (source.isCaseOf) { + conceptDescription.isCaseOf = source.isCaseOf.map(item => this.readReference(item)); + } + + return conceptDescription; + } + + private readAssetInformation(source: aasv2.Asset): aas.AssetInformation { + const asset: aas.AssetInformation = { + assetKind: source.kind ?? 'Instance', + globalAssetId: source.identification.id + }; + + return asset; + } + + private readSubmodels(): aas.Submodel[] { + const submodels: aas.Submodel[] = []; + if (this.origin) { + for (const item of this.origin.submodels) { + submodels.push(this.readSubmodel(item)); + } + } + + return submodels; + } + + private readSubmodel(source: aasv2.Submodel): aas.Submodel { + const submodel: aas.Submodel = { + ...this.readIdentifiable(source), + ...this.readHasSemantic(source), + ...this.readQualifiable(source), + ...this.readHasKind(source), + ...this.readHasDataSpecification(source) + }; + + if (source.submodelElements) { + submodel.submodelElements = this.readSubmodelElements( + source.submodelElements, [submodel]); + } + + return submodel; + } + + private readSubmodelElements(sources: aasv2.SubmodelElement[], ancestors?: aas.Referable[]): aas.SubmodelElement[] { + const submodelElements: aas.SubmodelElement[] = []; + for (const source of sources) { + const submodelElement = this.readSubmodelElement(source, ancestors); + if (submodelElement) { + submodelElements.push(submodelElement); + } + } + + return submodelElements; + } + + private readSubmodelElement(source: aasv2.SubmodelElement, ancestors?: aas.Referable[]): aas.SubmodelElement | undefined { + switch (source.modelType.name) { + case 'AnnotatedRelationshipElement': + return this.readAnnotatedRelationshipElement(source as aasv2.AnnotatedRelationshipElement, ancestors); + case 'BasicEvent': + return this.readBasicEvent(source as aasv2.BasicEvent, ancestors); + case 'Blob': + return this.readBlob(source as aasv2.Blob, ancestors); + case 'Entity': + return this.readEntity(source as aasv2.Entity, ancestors); + case 'File': + return this.readFile(source as aasv2.File, ancestors); + case 'MultiLanguageProperty': + return this.readMultiLanguageProperty(source as aasv2.MultiLanguageProperty, ancestors); + case 'Operation': + return this.readOperation(source as aasv2.Operation, ancestors); + case 'Property': + return this.readProperty(source as aasv2.Property, ancestors); + case 'Range': + return this.readRange(source as aasv2.Range, ancestors); + case 'ReferenceElement': + return this.readReferenceElement(source as aasv2.ReferenceElement, ancestors); + case 'RelationshipElement': + return this.readRelationshipElement(source as aasv2.RelationshipElement, ancestors); + case 'SubmodelElementCollection': + return this.readSubmodelElementCollection(source as aasv2.SubmodelElementCollection, ancestors); + default: + return undefined; + } + } + + private readSubmodelElementType(source: aasv2.SubmodelElement, ancestors?: aas.Referable[]): aas.SubmodelElement { + return { + ...this.readReferable(source, undefined, ancestors), + ...this.readHasSemantic(source), + ...this.readHasKind(source), + ...this.readHasDataSpecification(source), + ...this.readQualifiable(source) + }; + } + + private readAnnotatedRelationshipElement( + source: aasv2.AnnotatedRelationshipElement, + ancestors?: aas.Referable[]): aas.AnnotatedRelationshipElement { + const relationship: aas.AnnotatedRelationshipElement = { + ...this.readRelationshipElement(source, ancestors), + annotations: source.annotation?.map(item => this.readSubmodelElementType(item)) ?? [] + }; + + return relationship; + } + + private readBasicEvent(source: aasv2.BasicEvent, ancestors?: aas.Referable[]): aas.BasicEventElement { + if (!source.observed) { + throw new Error('BasicEvent.observed'); + } + + const basicEvent: aas.BasicEventElement = { + ...this.readSubmodelElementType(source, ancestors), + observed: this.readReference(source.observed), + direction: 'input', + state: 'off' + }; + + return basicEvent; + } + + private readProperty(source: aasv2.Property, ancestors?: aas.Referable[]): aas.Property { + let valueType = this.readValueTypeDef(source.valueType); + if (!valueType && source.value != null) { + valueType = determineType(source.value); + } + + if (!valueType) { + throw new Error('Property.valueType'); + } + + const property: aas.Property = { + ...this.readSubmodelElementType(source, ancestors), + valueType + }; + + if (source.value) { + property.value = source.value; + } + + if (ancestors && (!property.category || property.category === 'VARIABLE')) { + const smId = encodeBase64Url((ancestors[0] as aas.Submodel).id); + property.nodeId = `${smId}.${[...ancestors, property].map(item => item.idShort).join('/')}`; + } + + return property; + } + + private readMultiLanguageProperty( + source: aasv2.MultiLanguageProperty, + ancestors?: aas.Referable[]): aas.MultiLanguageProperty { + const value = this.readLangStringSet(source.value.langString); + const property: aas.MultiLanguageProperty = { + ...this.readSubmodelElementType(source, ancestors), + value + }; + + return property; + } + + private readFile(source: aasv2.File, ancestors?: aas.Referable[]): aas.File { + let contentType = source.mimeType; + if (!contentType) { + contentType = ''; + } + + const file: aas.File = { + ...this.readSubmodelElementType(source, ancestors), + contentType + }; + + if (source.value) { + file.value = source.value; + } + + return file; + } + + private readBlob(source: aasv2.Blob, ancestors?: aas.Referable[]): aas.Blob { + let contentType = source.mimeType; + if (!contentType) { + contentType = ''; + } + + const blob: aas.Blob = { + ...this.readSubmodelElementType(source, ancestors), + contentType + }; + + if (source.value) { + blob.value = source.value; + } + + return blob; + } + + private readSubmodelElementCollection( + source: aasv2.SubmodelElementCollection, + ancestors?: aas.Referable[]): aas.SubmodelElementCollection { + const collection: aas.SubmodelElementCollection = { + ...this.readSubmodelElementType(source, ancestors) + }; + + if (source.value) { + collection.value = this.readSubmodelElements( + source.value, + ancestors ? [...ancestors, collection] : undefined); + } + + return collection; + } + + private readReferenceElement(source: aasv2.ReferenceElement, ancestors?: aas.Referable[]): aas.ReferenceElement { + if (!source.value) { + throw new Error('ReferenceElement.value'); + } + + const reference: aas.ReferenceElement = { + ...this.readSubmodelElementType(source, ancestors), + value: this.readReference(source.value) + }; + + return reference; + } + + private readRelationshipElement(source: aasv2.RelationshipElement, ancestors?: aas.Referable[]): aas.RelationshipElement { + if (!source.first) { + throw new Error('RelationshipElement.first') + } + + if (!source.second) { + throw new Error('RelationshipElement.second') + } + + const relationship: aas.RelationshipElement = { + ...this.readSubmodelElementType(source, ancestors), + first: this.readReference(source.first), + second: this.readReference(source.second) + }; + + return relationship; + } + + private readOperation(source: aasv2.Operation, ancestors?: aas.Referable[]): aas.Operation { + const operation: aas.Operation = { + ...this.readSubmodelElementType(source, ancestors) + }; + + if (source.inputVariable) { + operation.inputVariables = source.inputVariable.map(item => this.readOperationVariable(item)); + } + + if (source.inoutputVariable) { + operation.inoutputVariables = source.inoutputVariable.map(item => this.readOperationVariable(item)); + } + + if (source.outputVariable) { + operation.outputVariables = source.outputVariable.map(item => this.readOperationVariable(item)); + } + + return operation; + } + + private readOperationVariable(source: aasv2.OperationVariable): aas.OperationVariable { + let value: aas.SubmodelElement | undefined; + if (isSubmodelElement(source.value)) { + value = this.readSubmodelElementType(source.value); + } else if ('submodelElement' in source.value) { + const submodelElement = (source.value as any).submodelElement as aasv2.SubmodelElement; + if (isSubmodelElement(submodelElement)) { + value = this.readSubmodelElementType(submodelElement); + } + } + + if (!value) { + throw new Error('OperationVariable.value'); + } + + return { value }; + } + + private readEntity(source: aasv2.Entity, ancestors?: aas.Referable[]): aas.Entity { + if (!source.entityType) { + throw new Error('Entity.entityType'); + } + + const entity: aas.Entity = { + ...this.readSubmodelElementType(source, ancestors), + entityType: source.entityType + }; + + if (source.asset) { + entity.globalAssetId = source.asset.keys[0].value; + } + + if (source.statements) { + entity.statements = this.readSubmodelElements(source.statements); + } + + return entity; + } + + private readRange(source: aasv2.Range, ancestors?: aas.Referable[]): aas.Range { + if (!source.valueType) { + throw new Error('Range.valueType'); + } + + const range: aas.Range = { + ...this.readSubmodelElementType(source, ancestors), + valueType: this.readDataTypeDefXsd(source.valueType.dataObjectType.name) as aas.DataTypeDefXsd + }; + + if (source.min) { + range.min = source.min; + } + + if (source.max) { + range.max = source.max; + } + + return range; + } + + private readValueTypeDef(source: aasv2.ValueTypeDef): aas.DataTypeDefXsd | undefined { + return this.readDataTypeDefXsd(source.dataObjectType?.name) as aas.DataTypeDefXsd; + } + + private readHasSemantic(source: aasv2.HasSemantic): aas.HasSemantic { + const hasSemantic: aas.HasSemantic = {}; + if (source.semanticId) { + hasSemantic.semanticId = this.readReference(source.semanticId); + } + + return hasSemantic; + } + + private readHasKind(source: aasv2.HasKind): aasv2.HasKind { + return { kind: source.kind ?? 'Instance' }; + } + + private readQualifiable(source: aasv2.Qualifiable): aas.Qualifiable { + const qualifiable: aas.Qualifiable = {}; + + if (source.qualifiers) { + qualifiable.qualifiers = source.qualifiers.map(item => this.readQualifier(item)); + } + + return qualifiable; + } + + private readQualifier(source: aasv2.Constraint): aas.Qualifier { + let qualifier: aas.Qualifier; + if (source.modelType.name === 'Qualifier') { + const sourceQualifier = source as aasv2.Qualifier; + if (!sourceQualifier.valueType) { + throw new Error('Qualifier.valueType'); + } + + qualifier = { + type: sourceQualifier.type, + valueType: this.readDataTypeDefXsd(sourceQualifier.valueType) + }; + + if (sourceQualifier.value) { + qualifier.value = sourceQualifier.value; + } + + if (sourceQualifier.valueId) { + qualifier.valueId = this.readReference(sourceQualifier.valueId); + } + } else { + throw new Error('Not implemented.'); + } + + return qualifier; + } + + private readReferable(source: aasv2.Referable, id?: string, ancestors?: aas.Referable[]): aas.Referable { + let idShort = source.idShort; + if (!idShort) { + if (!id) { + throw Error(`Referable.idShort.`); + } + + idShort = this.createIdShort(id); + } + + if (!source.modelType?.name) { + throw Error(`Referable.modelType.name.`); + } + + const referable: aas.Referable = { + idShort, + modelType: this.readModelType(source.modelType.name) as aas.ModelType + }; + + if (ancestors) { + referable.parent = { + type: 'ModelReference', + keys: ancestors.map((ancestor, index) => { + if (isIdentifiable(ancestor)) { + return { + type: ancestor.modelType, + value: ancestor.id + } as aas.Key; + } else { + return { + type: ancestor.modelType, + value: ancestor.idShort + } as aas.Key; + } + }) + }; + } + + if (source.category) { + referable.category = source.category; + } + + if (source.descriptions) { + referable.descriptions = this.readLangStringSet(source.descriptions); + } + + if (source.parent) { + referable.parent = this.readReference(source.parent); + } + + return referable; + } + + private readIdentifiable(source: aasv2.Identifiable): aas.Identifiable { + if (!source.identification) { + throw new Error('Identifiable.identification'); + } + + const id = this.readIdentifier(source.identification); + const identifiable: aas.Identifiable = { + ...this.readReferable(source, id), + id: id + }; + + if (source.administration) { + identifiable.administration = source.administration; + } + + return identifiable; + } + + private readIdentifier(source: aasv2.Identifier): string { + if (!source.id) { + throw new Error('Identifier.id'); + } + + return source.id; + } + + private readReference(source: aasv2.Reference): aas.Reference { + return { + type: this.determineReferenceType(source), + keys: source.keys.map(key => { + if (!key.type) { + throw new Error(`Reference.type`); + } + + if (!key.value) { + throw new Error(`Reference.value`); + } + + return { type: key.type, value: key.value } as aas.Key; + }) + }; + } + + private determineReferenceType(reference: aasv2.Reference): aas.ReferenceTypes { + return reference.keys.length === 0 || reference.keys[0].local ? 'ModelReference' : 'ExternalReference'; + } + + private readHasDataSpecification(source: aasv2.HasDataSpecification): aas.HasDataSpecification { + const hasDataSpecification: aas.HasDataSpecification = {}; + if (source.embeddedDataSpecifications) { + hasDataSpecification.embeddedDataSpecifications = source.embeddedDataSpecifications + .map(item => this.readEmbeddedDatSpecification(item)); + } + + return hasDataSpecification; + } + + private readEmbeddedDatSpecification(source: aasv2.EmbeddedDataSpecification): aas.EmbeddedDataSpecification { + if (!source.dataSpecification) { + throw new Error('EmbeddedDataSpecification.dataSpecification'); + } + + if (!source.dataSpecificationContent) { + throw new Error('EmbeddedDataSpecification.dataSpecificationContent'); + } + + let dataSpecificationContent: aas.DataSpecificationContent; + if ((source.dataSpecificationContent as aasv2.DataSpecificationIEC61360Content).preferredName) { + dataSpecificationContent = this.readDataSpecificationIEC61360( + source.dataSpecificationContent as aasv2.DataSpecificationIEC61360Content); + } else { + throw new Error('Not implemented.'); + } + + const specification: aas.EmbeddedDataSpecification = { + dataSpecification: this.readReference(source.dataSpecification), + dataSpecificationContent + }; + + return specification; + } + + private readDataSpecificationIEC61360(source: aasv2.DataSpecificationIEC61360Content): aas.DataSpecificationIEC61360 { + if (!source.preferredName) { + throw new Error(`DataSpecificationIEC61360.preferredName`); + } + + const iec61360: aas.DataSpecificationIEC61360 = { + modelType: 'DataSpecificationIEC61360', + preferredName: this.readLangStringSet(source.preferredName) + } + + if (source.dataType) { + iec61360.dataType = this.readDataTypeIEC61360(source.dataType); + } + + if (source.definition) { + iec61360.definition = this.readLangStringSet(source.definition); + } + + if (source.levelType) { + iec61360.levelType = source.levelType; + } + + if (source.shortName) { + iec61360.shortName = this.readLangStringSet(source.shortName); + } + + if (source.sourceOfDefinition) { + iec61360.sourceOfDefinition = source.sourceOfDefinition; + } + + if (source.symbol) { + iec61360.symbol = source.symbol; + } + + if (source.unit) { + iec61360.unit = source.unit; + } + + if (source.unitId) { + iec61360.unitId = this.readReference(source.unitId); + } + + if (source.value) { + iec61360.value = source.value; + } + + if (source.valueFormat) { + iec61360.valueFormat = source.valueFormat; + } + + if (source.valueList) { + iec61360.valueList = this.readValueList(source.valueList); + } + + return iec61360; + } + + private readValueList(source: aasv2.ValueList): aas.ValueList { + if (!source.valueReferencePairTypes) { + throw new Error('ValueList.valueReferencePairTypes'); + } + + return { + valueReferencePairs: source.valueReferencePairTypes + .map(item => this.readValueReferencePairType(item)) + }; + } + + private readLangStringSet(source: aasv2.LangString[]): aas.LangString[] { + if (!source) { + return []; + } else if (typeof source === 'string') { + return [{ language: 'en', text: source }]; + } else { + return source.map(item => ({ language: item.language, text: item.text })); + } + } + + private readValueReferencePairType(source: aasv2.ValueReferencePairType): aas.ValueReferencePair { + if (!source.value) { + throw new Error('ValueObject.value'); + } + + if (!source.valueId) { + throw new Error('ValueObject.valueId') + } + + return { value: source.value, valueId: this.readReference(source.valueId) } as aas.ValueReferencePair; + } + + private readModelType(source: aasv2.ModelTypes): aas.ModelType { + return source === 'BasicEvent' ? 'BasicEventElement' : source as aas.ModelType; + } + + private readDataTypeDefXsd(source: aasv2.DataTypeDefXsd): aas.DataTypeDefXsd { + switch (source) { + case 'anyURI': + return 'xs:anyURI'; + case 'base64Binary': + return 'xs:base64Binary'; + case 'boolean': + return 'xs:boolean'; + case 'byte': + return 'xs:byte'; + case 'date': + return 'xs:date'; + case 'dateTime': + return 'xs:dateTime'; + case 'dateTimeStamp': + return 'xs:dateTime'; + case 'dayTimeDuration': + return 'xs:duration'; + case 'decimal': + return 'xs:decimal'; + case 'double': + return 'xs:double'; + case 'duration': + return 'xs:duration'; + case 'float': + return 'xs:float'; + case 'gDay': + return 'xs:gDay'; + case 'gMonth': + return 'xs:gMonth'; + case 'gMonthDay': + return 'xs:gMonthDay'; + case 'gYear': + return 'xs:gYear'; + case 'gYearMonth': + return 'xs:gYearMonth'; + case 'hexBinary': + return 'xs:hexBinary'; + case 'int': + return 'xs:int'; + case 'integer': + return 'xs:integer'; + case 'long': + return 'xs:long'; + case 'negativeInteger': + return 'xs:negativeInteger'; + case 'nonNegativeInteger': + return 'xs:nonNegativeInteger'; + case 'nonPositiveInteger': + return 'xs:nonPositiveInteger'; + case 'positiveInteger': + return 'xs:positiveInteger'; + case 'short': + return 'xs:short'; + case 'string': + return 'xs:string'; + case 'time': + return 'xs:time'; + case 'unsignedByte': + return 'xs:unsignedByte'; + case 'unsignedInt': + return 'xs:unsignedInt'; + case 'unsignedLong': + return 'xs:unsignedLong'; + case 'unsignedShort': + return 'xs:unsignedShort'; + case 'yearMonthDuration': + return 'xs:duration'; + default: + return source as aas.DataTypeDefXsd; + } + } + + private readDataTypeIEC61360(source: string): aas.DataTypeIEC61360 { + switch (source) { + case 'DATE': + return 'DATE'; + case 'STRING': + return 'STRING'; + case 'STRING_TRANSLATABLE': + return 'STRING_TRANSLATABLE'; + case 'INTEGER_MEASURE': + return 'INTEGER_MEASURE'; + case 'INTEGER_COUNT': + return 'INTEGER_COUNT'; + case 'INTEGER_CURRENCY': + return 'INTEGER_CURRENCY'; + case 'REAL_MEASURE': + return 'REAL_MEASURE'; + case 'REAL_COUNT': + return 'REAL_COUNT'; + case 'REAL_CURRENCY': + return 'REAL_CURRENCY'; + case 'BOOLEAN': + return 'BOOLEAN'; + case 'URL': + return 'IRI'; + case 'RATIONAL': + return 'RATIONAL'; + case 'RATIONAL_MEASURE': + return 'RATIONAL_MEASURE'; + case 'TIME': + return 'TIME'; + case 'TIMESTAMP': + return 'TIMESTAMP'; + default: + return source as aas.DataTypeIEC61360; + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/json-reader.ts b/projects/aas-server/src/app/packages/json-reader.ts new file mode 100644 index 00000000..4a55845b --- /dev/null +++ b/projects/aas-server/src/app/packages/json-reader.ts @@ -0,0 +1,801 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Logger } from '../logging/logger.js'; +import { AASReader } from './aas-reader.js'; +import { aas, determineType, isIdentifiable } from 'common'; +import { cloneDeep } from 'lodash-es'; +import { encodeBase64Url } from '../convert.js'; + +export class JsonReader extends AASReader { + private readonly origin: aas.Environment; + + constructor( + private readonly logger: Logger, + origin?: aas.Environment | string) { + super(); + + if (origin) { + if (typeof origin === 'string') { + this.origin = JSON.parse(origin); + } else { + this.origin = origin; + } + } else { + this.origin = { assetAdministrationShells: [], conceptDescriptions: [], submodels: [] }; + } + } + + public readEnvironment(): aas.Environment { + const conceptDescriptions = this.readConceptDescriptions(); + const assetAdministrationShells = this.readAssetAdministrationShells(); + const submodels = this.readSubmodels(); + return { assetAdministrationShells, submodels, conceptDescriptions }; + } + + /** + * Deserializes a Submodel or SubmodelElement from the specified source. + * @param data The serialized Submodel or SubmodelElement. + * @returns The deserialized Submodel or SubmodelElement. + */ + public read(data: string | object): aas.Referable { + const source: aas.Referable = typeof data === 'string' ? JSON.parse(data) : data; + switch (source.modelType) { + case 'AssetAdministrationShell': + throw new Error('Invalid operation.'); + case 'Submodel': + return this.readSubmodel(source as aas.Submodel); + default: + const element = this.readSubmodelElement(source as aas.SubmodelElement, []); + if (!element) { + throw new Error('Invalid operation.'); + } + + return element; + } + } + + private readConceptDescriptions(): aas.ConceptDescription[] { + const conceptDescriptions: aas.ConceptDescription[] = []; + if (this.origin?.conceptDescriptions) { + for (const source of this.origin.conceptDescriptions) { + conceptDescriptions.push(this.readConceptDescription(source)); + } + } + + return conceptDescriptions; + } + + private readAssetAdministrationShells(): aas.AssetAdministrationShell[] { + const shells: aas.AssetAdministrationShell[] = []; + if (this.origin?.assetAdministrationShells) { + for (const source of this.origin.assetAdministrationShells) { + shells.push(this.readAssetAdministrationShell(source)); + } + } + + return shells; + } + + private readAssetAdministrationShell(source: aas.AssetAdministrationShell): aas.AssetAdministrationShell { + if (!source.assetInformation) { + throw new Error('AssetAdministrationShell.asset'); + } + + const shell: aas.AssetAdministrationShell = { + ...this.readIdentifiable(source), + ...this.readHasDataSpecification(source), + assetInformation: this.readAssetInformation(source.assetInformation) + }; + + if (source.derivedFrom) { + shell.derivedFrom = this.readReference(source.derivedFrom); + } + + if (source.administration) { + shell.administration = this.readAdministrationInformation(source.administration); + } + + if (source.submodels) { + shell.submodels = source.submodels.map(item => this.readReference(item)); + } + + return shell; + } + + private readAssetInformation(source: aas.AssetInformation): aas.AssetInformation { + if (!source.assetKind) { + throw new Error('AssetInformation.assetKind'); + } + + const asset: aas.AssetInformation = { assetKind: source.assetKind }; + if (source.globalAssetId) { + asset.globalAssetId = source.globalAssetId; + } + + if (source.specificAssetIds) { + asset.specificAssetIds = source.specificAssetIds.map(item => this.readSpecificAssetId(item)); + } + + return asset; + } + + private readSpecificAssetId(source: aas.SpecificAssetId): aas.SpecificAssetId { + if (!source.name) { + throw new Error('SpecificAssetId.name'); + } + + if (!source.value) { + throw new Error('SpecificAssetId.value'); + } + + if (!source.externalSubjectId) { + throw new Error('SpecificAssetId.externalSubjectId'); + } + + return { + ...this.readHasSemantic, + name: source.name, + value: source.value, + externalSubjectId: this.readReference(source.externalSubjectId) + }; + } + + private readAdministrationInformation(source: aas.AdministrativeInformation): aas.AdministrativeInformation { + const info: aas.AdministrativeInformation = {}; + if (source.revision) { + info.revision = source.revision; + } + + if (source.version) { + info.version = source.version; + } + + return info; + } + + private readConceptDescription(source: aas.ConceptDescription): aas.ConceptDescription { + const conceptDescription: aas.ConceptDescription = { + ...this.readIdentifiable(source, 'ConceptDescription'), + ...this.readHasDataSpecification(source) + }; + + if (source.isCaseOf) { + conceptDescription.isCaseOf = source.isCaseOf.map(item => this.readReference(item)); + } + + return conceptDescription; + } + + private readSubmodels(): aas.Submodel[] { + const submodels: aas.Submodel[] = []; + if (this.origin && this.origin.submodels) { + for (const item of this.origin.submodels) { + submodels.push(this.readSubmodel(item)); + } + } + + return submodels; + } + + private readSubmodel(source: aas.Submodel): aas.Submodel { + const submodel: aas.Submodel = { + ...this.readIdentifiable(source), + ...this.readHasSemantic(source), + ...this.readQualifiable(source), + ...this.readHasKind(source), + ...this.readHasDataSpecification(source) + }; + + if (source.submodelElements) { + submodel.submodelElements = this.readSubmodelElements( + source.submodelElements, [submodel]); + } + + return submodel; + } + + private readSubmodelElements(sources: aas.SubmodelElement[], ancestors?: aas.Referable[]): aas.SubmodelElement[] { + const submodelElements: aas.SubmodelElement[] = []; + for (const source of sources) { + const submodelElement = this.readSubmodelElement(source, ancestors); + if (submodelElement) { + submodelElements.push(submodelElement); + } + } + + return submodelElements; + } + + private readSubmodelElement(source: aas.SubmodelElement, ancestors?: aas.Referable[]): aas.SubmodelElement | undefined { + switch (source.modelType) { + case 'AnnotatedRelationshipElement': + return this.readAnnotatedRelationshipElement(source as aas.AnnotatedRelationshipElement, ancestors); + case 'BasicEventElement': + return this.readBasicEventElement(source as aas.BasicEventElement, ancestors); + case 'Blob': + return this.readBlob(source as aas.Blob, ancestors); + case 'Entity': + return this.readEntity(source as aas.Entity, ancestors); + case 'File': + return this.readFile(source as aas.File, ancestors); + case 'MultiLanguageProperty': + return this.readMultiLanguageProperty(source as aas.MultiLanguageProperty, ancestors); + case 'Operation': + return this.readOperation(source as aas.Operation, ancestors); + case 'Property': + return this.readProperty(source as aas.Property, ancestors); + case 'Range': + return this.readRange(source as aas.Range, ancestors); + case 'ReferenceElement': + return this.readReferenceElement(source as aas.ReferenceElement, ancestors); + case 'RelationshipElement': + return this.readRelationshipElement(source as aas.RelationshipElement, ancestors); + case 'SubmodelElementCollection': + return this.readSubmodelElementCollection(source as aas.SubmodelElementCollection, ancestors); + case 'SubmodelElementList': + return this.readSubmodelElementList(source as aas.SubmodelElementList, ancestors); + default: + return undefined; + } + } + + private readSubmodelElementType(source: aas.SubmodelElement, ancestors?: aas.Referable[]): aas.SubmodelElement { + return { + ...this.readReferable(source, ancestors), + ...this.readHasSemantic(source), + ...this.readHasKind(source), + ...this.readHasDataSpecification(source), + ...this.readQualifiable(source) + }; + } + + private readAnnotatedRelationshipElement( + source: aas.AnnotatedRelationshipElement, + ancestors?: aas.Referable[]): aas.AnnotatedRelationshipElement { + if (!source.annotations) { + throw new Error('AnnotatedRelationshipElement.annotation') + } + + const relationship: aas.AnnotatedRelationshipElement = { + ...this.readRelationshipElement(source, ancestors), + annotations: this.readSubmodelElements(source.annotations), + }; + + return relationship; + } + + private readEventElement(source: aas.EventElement, ancestor?: aas.Referable[]): aas.EventElement { + return { ...this.readSubmodelElementType(source, ancestor) }; + } + + private readBasicEventElement(source: aas.BasicEventElement, ancestors?: aas.Referable[]): aas.BasicEventElement { + if (!source.observed) { + throw new Error('BasicEventElement.observed'); + } + + if (!source.direction) { + throw new Error('BasicEventElement.direction'); + } + + if (!source.state) { + throw new Error('BasicEventElement.state'); + } + + const eventElement: aas.BasicEventElement = { + ...this.readEventElement(source, ancestors), + observed: source.observed, + direction: source.direction, + state: source.state + }; + + if (source.messageTopic) { + eventElement.messageTopic = source.messageTopic; + } + + if (source.messageBroker) { + eventElement.messageBroker = this.readReference(source.messageBroker); + } + + if (source.lastUpdate) { + eventElement.lastUpdate = source.lastUpdate; + } + + if (source.minInterval) { + eventElement.minInterval = source.minInterval; + } + + if (source.maxInterval) { + eventElement.maxInterval = source.maxInterval; + } + + return eventElement; + } + + private readProperty(source: aas.Property, ancestors?: aas.Referable[]): aas.Property { + let valueType: aas.DataTypeDefXsd | undefined = source.valueType; + if (!valueType && source.value) { + valueType = determineType(source.value); + } + + if (!valueType) { + throw new Error('Property.valueType'); + } + + const property: aas.Property = { + ...this.readSubmodelElementType(source, ancestors), + valueType + }; + + if (source.value) { + property.value = source.value; + } + + if (ancestors && (!property.category || property.category === 'VARIABLE')) { + const smId = encodeBase64Url((ancestors[0] as aas.Submodel).id); + property.nodeId = `${smId}.${[...ancestors, property].map(item => item.idShort).join('/')}`; + } + + return property; + } + + private readMultiLanguageProperty( + source: aas.MultiLanguageProperty, + ancestors?: aas.Referable[]): aas.MultiLanguageProperty { + let value: aas.LangString[] | undefined; + if (Array.isArray(source.value)) { + value = source.value.map(item => ({ language: item.language, text: item.text })); + } + + if (!value) { + value = []; + } + + return { ...this.readSubmodelElementType(source, ancestors), value }; + } + + private readOperation(source: aas.Operation, ancestors: aas.Referable[] | undefined): aas.Operation { + const operation: aas.Operation = { + ...this.readSubmodelElementType(source, ancestors) + }; + + if (source.inputVariables) { + operation.inputVariables = source.inputVariables.map(item => this.readOperationVariable(item)); + } + + if (source.inoutputVariables) { + operation.inoutputVariables = source.inoutputVariables.map(item => this.readOperationVariable(item)); + } + + if (source.outputVariables) { + operation.outputVariables = source.outputVariables.map(item => this.readOperationVariable(item)); + } + + return operation; + } + + private readOperationVariable(source: aas.OperationVariable): aas.OperationVariable { + if (!source.value) { + throw new Error('OperationVariable.value'); + } + + return { value: this.readSubmodelElementType(source.value) }; + } + + private readFile(source: aas.File, ancestors?: aas.Referable[]): aas.File { + if (!source.contentType) { + throw new Error('File.contentType'); + } + + const file: aas.File = { + ...this.readSubmodelElementType(source, ancestors), + contentType: source.contentType + }; + + if (source.value) { + file.value = source.value; + } + + return file; + } + + private readBlob(source: aas.Blob, ancestors?: aas.Referable[]): aas.Blob { + const blob: aas.Blob = { + ...this.readSubmodelElementType(source, ancestors), + contentType: source.contentType ?? '' + }; + + if (source.value) { + blob.value = source.value; + } + + return blob; + } + + private readEntity(source: aas.Entity, ancestors: aas.Referable[] | undefined): aas.Entity { + if (!source.entityType) { + throw new Error('Entity.entityType'); + } + + const entity: aas.Entity = { + ...this.readSubmodelElementType(source, ancestors), + entityType: source.entityType + }; + + if (source.statements) { + entity.statements = source.statements.map(item => this.readSubmodelElement(item)!); + } + + if (source.globalAssetId) { + entity.globalAssetId = source.globalAssetId; + } + + if (source.specificAssetId) { + entity.specificAssetId = this.readSpecificAssetId(source.specificAssetId); + } + + return entity; + } + + private readSubmodelElementCollection( + source: aas.SubmodelElementCollection, + ancestors?: aas.Referable[]): aas.SubmodelElementCollection { + const collection: aas.SubmodelElementCollection = { + ...this.readSubmodelElementType(source, ancestors) + }; + + if (source.value) { + collection.value = this.readSubmodelElements( + source.value, + ancestors ? [...ancestors, collection] : undefined); + } + + return collection; + } + + private readSubmodelElementList( + source: aas.SubmodelElementList, + ancestors?: aas.Referable[]): aas.SubmodelElementCollection { + if (!source.typeValueListElement) { + throw new Error('SubmodelElement.typeValueListElement'); + } + + const list: aas.SubmodelElementList = { + ...this.readSubmodelElementType(source, ancestors), + typeValueListElement: source.typeValueListElement, + valueTypeListElement: source.valueTypeListElement + }; + + if (source.orderRelevant) { + list.orderRelevant = source.orderRelevant; + } + + if (source.semanticIdListElement) { + list.semanticIdListElement = this.readReference(source.semanticIdListElement); + } + + if (source.value) { + list.value = this.readSubmodelElements( + source.value, + ancestors ? [...ancestors, list] : undefined); + } + + return list; + } + + private readReferenceElement(source: aas.ReferenceElement, ancestors?: aas.Referable[]): aas.ReferenceElement { + if (!source.value) { + throw new Error('ReferenceElement.value'); + } + + const reference: aas.ReferenceElement = { + ...this.readSubmodelElementType(source, ancestors), + value: this.readReference(source.value) + }; + + return reference; + } + + private readRelationshipElement(source: aas.RelationshipElement, ancestors?: aas.Referable[]): aas.RelationshipElement { + if (!source.first) { + throw new Error('RelationshipElement.first') + } + + if (!source.second) { + throw new Error('RelationshipElement.second') + } + + const relationship: aas.RelationshipElement = { + ...this.readSubmodelElementType(source, ancestors), + first: this.readReference(source.first), + second: this.readReference(source.second) + }; + + return relationship; + } + + private readRange(source: aas.Range, ancestors?: aas.Referable[]): aas.Range { + if (!source.valueType) { + throw new Error('Range.valueType'); + } + + const range: aas.Range = { + ...this.readSubmodelElementType(source, ancestors), + valueType: source.valueType + }; + + if (source.min) { + range.min = source.min; + } + + if (source.max) { + range.max = source.max; + } + + return range; + } + + private readHasSemantic(source: aas.HasSemantic): aas.HasSemantic { + const hasSemantic: aas.HasSemantic = {}; + if (source.semanticId && source.semanticId.keys.length > 0) { + hasSemantic.semanticId = this.readReference(source.semanticId); + } + + return hasSemantic; + } + + private readHasKind(source: aas.HasKind): aas.HasKind { + return { kind: source.kind ?? 'Instance' }; + } + + private readQualifiable(source: aas.Qualifiable): aas.Qualifiable { + const qualifiable: aas.Qualifiable = {}; + if (source.qualifiers) { + qualifiable.qualifiers = source.qualifiers.map(item => this.readQualifier(item)); + } + + return qualifiable; + } + + private readQualifier(source: aas.Qualifier): aas.Qualifier { + if (!source.type) { + throw new Error('Qualifier.type'); + } + + if (!source.valueType) { + throw new Error('Qualifier.valueType'); + } + + const qualifier: aas.Qualifier = { + ...this.readHasSemantic(source), + type: source.type, + valueType: source.valueType + }; + + if (source.kind) { + qualifier.kind = source.kind; + } + + if (source.value) { + qualifier.value = source.value; + } + + if (source.valueId) { + qualifier.valueId = this.readReference(source.valueId); + } + + return qualifier; + } + + private readReferable( + source: aas.Referable, + ancestors?: aas.Referable[], + id?: string, + modelType?: aas.ModelType): aas.Referable { + let idShort = source.idShort; + if (!idShort) { + if (!id) { + throw Error(`Referable.idShort`); + } + + idShort = this.createIdShort(id); + } + + if (!source.modelType && !modelType) { + throw Error(`Referable.modelType`); + } + + const referable: aas.Referable = { idShort, modelType: source.modelType ?? modelType }; + + if (ancestors) { + referable.parent = { + type: 'ModelReference', + keys: ancestors.map((ancestor) => { + if (isIdentifiable(ancestor)) { + return { + type: ancestor.modelType, + value: ancestor.id + } as aas.Key; + } else { + return { + type: ancestor.modelType, + value: ancestor.idShort + } as aas.Key; + } + }) + }; + } + + if (source.category) { + referable.category = source.category as aas.Category; + } + + if (source.descriptions) { + referable.descriptions = cloneDeep(source.descriptions); + } + + if (source.parent) { + referable.parent = this.readReference(source.parent); + } + + return referable; + } + + private readIdentifiable(source: aas.Identifiable, modelType?: aas.ModelType): aas.Identifiable { + if (!source.id) { + throw new Error('Identifiable.id'); + } + + const identifiable: aas.Identifiable = { + ...this.readReferable(source, undefined, source.id, modelType), + id: source.id + }; + + if (source.administration) { + identifiable.administration = source.administration; + } + + return identifiable; + } + + private readReference(source: aas.Reference): aas.Reference { + return { + type: source.type, + keys: source.keys.map((key) => { + if (!key.type) { + throw new Error(`Reference.type`); + } + + if (!key.value) { + throw new Error(`Reference.value`); + } + + return { + type: key.type, + value: key.value, + } as aas.Key; + }) + }; + } + + private readHasDataSpecification(source: aas.HasDataSpecification): aas.HasDataSpecification { + const hasDataSpecification: aas.HasDataSpecification = {}; + if (source.embeddedDataSpecifications) { + hasDataSpecification.embeddedDataSpecifications = source.embeddedDataSpecifications + .map(item => this.readEmbeddedDatSpecification(item)); + } + + return hasDataSpecification; + } + + private readEmbeddedDatSpecification(source: aas.EmbeddedDataSpecification): aas.EmbeddedDataSpecification { + if (!source.dataSpecification) { + throw new Error('EmbeddedDataSpecification.dataSpecification'); + } + + if (!source.dataSpecificationContent) { + throw new Error('EmbeddedDataSpecification.dataSpecificationContent'); + } + + let dataSpecificationContent: aas.DataSpecificationContent; + if (!source.dataSpecificationContent.modelType || source.dataSpecificationContent.modelType === 'DataSpecificationIEC61360') { + dataSpecificationContent = this.readDataSpecificationIEC61360( + source.dataSpecificationContent as aas.DataSpecificationIEC61360); + } else { + throw new Error(`${source.dataSpecificationContent.modelType} is a not supported DataSpecificationContent.`); + } + + const specification: aas.EmbeddedDataSpecification = { + dataSpecification: this.readReference(source.dataSpecification), + dataSpecificationContent + }; + + return specification; + } + + private readDataSpecificationIEC61360(source: aas.DataSpecificationIEC61360): aas.DataSpecificationIEC61360 { + if (!source.preferredName) { + throw new Error(`DataSpecificationIEC61360.preferredName`); + } + + const iec61360: aas.DataSpecificationIEC61360 = { + modelType: source.modelType, + preferredName: source.preferredName + } + + if (source.dataType) { + iec61360.dataType = source.dataType; + } + + if (source.definition) { + iec61360.definition = source.definition; + } + + if (source.levelType) { + iec61360.levelType = source.levelType; + } + + if (source.shortName) { + iec61360.shortName = source.shortName; + } + + if (source.sourceOfDefinition) { + iec61360.sourceOfDefinition = source.sourceOfDefinition; + } + + if (source.symbol) { + iec61360.symbol = source.symbol; + } + + if (source.unit) { + iec61360.unit = source.unit; + } + + if (source.unitId) { + iec61360.unitId = this.readReference(source.unitId); + } + + if (source.value) { + iec61360.value = source.value; + } + + if (source.valueFormat) { + iec61360.valueFormat = source.valueFormat; + } + + if (source.valueList) { + iec61360.valueList = this.readValueList(source.valueList); + } + + return iec61360; + } + + private readValueList(source: aas.ValueList): aas.ValueList { + if (!source.valueReferencePairs) { + throw new Error('ValueList.valueReferencePairs'); + } + + const valueList: aas.ValueList = { + valueReferencePairs: source.valueReferencePairs.map(item => this.readValueReferencePair(item)) + }; + + return valueList; + } + + private readValueReferencePair(source: aas.ValueReferencePair): aas.ValueReferencePair { + if (!source.value) { + throw new Error('ValueReferencePair.value'); + } + + if (!source.valueId) { + throw new Error('ValueReferencePair.valueId'); + } + + return { value: source.value, valueId: this.readReference(source.valueId) }; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/json-writer-v2.ts b/projects/aas-server/src/app/packages/json-writer-v2.ts new file mode 100644 index 00000000..fde2c350 --- /dev/null +++ b/projects/aas-server/src/app/packages/json-writer-v2.ts @@ -0,0 +1,632 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASWriter } from './aas-writer.js'; +import { aas, isSubmodelElement } from 'common'; +import * as aasv2 from '../types/aas-v2.js'; + +export class JsonWriterV2 extends AASWriter { + public writeEnvironment(env: aas.Environment): any { + throw new Error('Method not implemented.'); + } + + public write(source: aas.Referable): any { + if (source.modelType === 'Submodel') { + return this.writeSubmodel(source as aas.Submodel); + } + + return this.writeSubmodelElement(source as aas.SubmodelElement); + } + + private writeSubmodel(source: aas.Submodel): aasv2.Submodel { + const submodel: aasv2.Submodel = { + ...this.writeIdentifiable(source), + ...this.writeHasDataSpecification(source), + ...this.writeHasSemantic(source), + ...this.writeQualifiable(source), + ...this.writeHasKind(source) + }; + + if (source.submodelElements) { + submodel.submodelElements = source.submodelElements.map(item => this.writeSubmodelElement(item)); + } + + return submodel; + } + + private writeSubmodelElement(source: aas.SubmodelElement): aasv2.SubmodelElement { + switch (source.modelType) { + case 'AnnotatedRelationshipElement': + return this.writeAnnotatedRelationshipElement(source as aas.AnnotatedRelationshipElement); + case 'BasicEventElement': + return this.writeBasicEvent(source as aas.BasicEventElement); + case 'Blob': + return this.writeBlob(source as aas.Blob); + case 'Entity': + return this.writeEntity(source as aas.Entity); + case 'File': + return this.writeFile(source as aas.File); + case 'MultiLanguageProperty': + return this.writeMultiLanguageProperty(source as aas.MultiLanguageProperty); + case 'Operation': + return this.writeOperation(source as aas.Operation); + case 'Property': + return this.writeProperty(source as aas.Property); + case 'Range': + return this.writeRange(source as aas.Range); + case 'ReferenceElement': + return this.writeReferenceElement(source as aas.ReferenceElement); + case 'RelationshipElement': + return this.writeRelationshipElement(source as aas.RelationshipElement); + case 'SubmodelElementCollection': + return this.writeSubmodelElementCollection(source as aas.SubmodelElementCollection); + default: + throw new Error(`Unable to write model type "${source.modelType}".`); + } + } + + private writeAnnotatedRelationshipElement(source: aas.AnnotatedRelationshipElement): aasv2.AnnotatedRelationshipElement { + if (!source.annotations) { + throw new Error('AnnotatedRelationshipElement.annotation') + } + + const relationship: aasv2.AnnotatedRelationshipElement = { + ...this.writeRelationshipElement(source), + annotation: source.annotations.map(item => this.writeSubmodelElement(item)), + }; + + return relationship; + } + + private writeBasicEvent(source: aas.BasicEventElement): aasv2.BasicEvent { + if (!source.observed) { + throw new Error('BasicEventElement.observed'); + } + + const basicEvent: aasv2.BasicEvent = { + ...this.writeSubmodelElementType(source), + observed: this.writeReference(source.observed) + }; + + return basicEvent; + } + + private writeBlob(source: aas.Blob): aasv2.Blob { + let mimeType = source.contentType; + if (!mimeType) { + mimeType = ''; + } + + const blob: aasv2.Blob = { + ...this.writeSubmodelElementType(source), + mimeType + }; + + if (source.value) { + blob.value = source.value; + } + + return blob; + } + + private writeEntity(source: aas.Entity): aasv2.Entity { + if (!source.entityType) { + throw new Error('Entity.entityType'); + } + + const entity: aasv2.Entity = { + ...this.writeSubmodelElementType(source), + entityType: source.entityType + }; + + if (source.globalAssetId) { + throw new Error('Not implemented.'); + //entity.asset = this.writeReference(source.globalAssetId); + } + + if (source.statements) { + entity.statements = source.statements.map(item => this.writeSubmodelElement(item)); + } + + return entity; + } + + private writeFile(source: aas.File): aasv2.File { + let mimeType = source.contentType; + if (!mimeType) { + mimeType = ''; + } + + const file: aasv2.File = { + ...this.writeSubmodelElementType(source), + mimeType + }; + + if (source.value) { + file.value = source.value; + } + + return file; + } + + private writeMultiLanguageProperty(source: aas.MultiLanguageProperty): aasv2.MultiLanguageProperty { + let langString: aasv2.LangString[] | undefined; + if (Array.isArray(source.value)) { + langString = source.value?.map(item => ({ language: item.language, text: item.text })); + } + + if (!langString) { + langString = []; + } + + const property: aasv2.MultiLanguageProperty = { + ...this.writeSubmodelElementType(source), + value: { langString } + } + + return property; + } + + private writeOperation(source: aas.Operation): aasv2.Operation { + const operation: aasv2.Operation = { + ...this.writeSubmodelElementType(source) + }; + + if (source.inputVariables) { + operation.inputVariable = source.inputVariables.map(item => this.writeOperationVariable(item)); + } + + if (source.inoutputVariables) { + operation.inoutputVariable = source.inoutputVariables.map(item => this.writeOperationVariable(item)); + } + + if (source.outputVariables) { + operation.outputVariable = source.outputVariables.map(item => this.writeOperationVariable(item)); + } + + return operation; + } + + + private writeOperationVariable(source: aas.OperationVariable): aasv2.OperationVariable { + let value: aasv2.SubmodelElement | undefined; + if (isSubmodelElement(source.value)) { + value = this.writeSubmodelElementType(source.value); + } else if ('submodelElement' in source.value) { + const submodelElement = (source.value as any).submodelElement; + if (isSubmodelElement(submodelElement)) { + value = this.writeSubmodelElement(submodelElement); + } + } + + if (!value) { + throw new Error('OperationVariable.value'); + } + + return { value }; + } + + private writeProperty(source: aas.Property): aasv2.Property { + const valueType = this.writeValueTypeDef(source.valueType); + if (!valueType) { + throw new Error('Property.valueType'); + } + + const property: aasv2.Property = { + ...this.writeSubmodelElementType(source), + valueType + }; + + if (source.value) { + property.value = source.value; + } + + if (source.valueId) { + property.valueId = this.writeReference(source.valueId); + } + + return property; + } + + private writeRange(source: aas.Range): aasv2.Range { + if (!source.valueType) { + throw new Error('Range.valueType'); + } + + const range: aasv2.Range = { + ...this.writeSubmodelElementType(source), + valueType: this.writeValueTypeDef(source.valueType)! + }; + + if (source.min) { + range.min = source.min; + } + + if (source.max) { + range.max = source.max; + } + + return range; + } + + private writeReferenceElement(source: aas.ReferenceElement): aasv2.ReferenceElement { + if (!source.value) { + throw new Error('ReferenceElement.value'); + } + + const reference: aasv2.ReferenceElement = { + ...this.writeSubmodelElementType(source), + value: this.writeReference(source.value) + }; + + return reference; + } + + private writeRelationshipElement(source: aas.RelationshipElement): aasv2.RelationshipElement { + if (!source.first) { + throw new Error('RelationshipElement.first') + } + + if (!source.second) { + throw new Error('RelationshipElement.second') + } + + const relationship: aasv2.RelationshipElement = { + ...this.writeSubmodelElementType(source), + first: this.writeReference(source.first), + second: this.writeReference(source.second) + }; + + return relationship; + } + + private writeSubmodelElementCollection(source: aas.SubmodelElementCollection): aasv2.SubmodelElementCollection { + const collection: aasv2.SubmodelElementCollection = { + ...this.writeSubmodelElementType(source), + }; + + if (source.value) { + collection.value = source.value.map(item => this.writeSubmodelElement(item)) + } + + return collection; + } + + private writeReference(source: aas.Reference): aasv2.Reference { + return { + keys: source.keys.map((key, index) => { + if (!key.type) { + throw new Error(`Reference.type`); + } + + if (!key.value) { + throw new Error(`Reference.value`); + } + + return { + idType: this.writeKeyType(key), + type: key.type as aasv2.KeyElements, + value: key.value, + index: index, + local: true + } as aasv2.Key; + }) + }; + } + + private writeSubmodelElementType(source: aas.SubmodelElement): aasv2.SubmodelElement { + return { + ...this.writeReferable(source), + ...this.writeHasSemantic(source), + ...this.writeHasDataSpecification(source), + ...this.writeQualifiable(source), + ...this.writeHasKind(source) + }; + } + + private writeIdentifiable(source: aas.Identifiable): aasv2.Identifiable { + if (!source.id) { + throw new Error('Identifiable.id'); + } + + const identification = this.writeIdentifier(source.id); + const identifiable: aasv2.Identifiable = { + ...this.writeReferable(source), + identification + }; + + if (source.administration) { + identifiable.administration = source.administration; + } + + return identifiable; + } + + private writeIdentifier(id: string): aasv2.Identifier { + let idType: aasv2.KeyType; + try { + const _ = new URL(id); + idType = 'IRI'; + } catch (_) { + idType = 'IRDI'; + } + + return { id, idType } + } + + private writeReferable(source: aas.Referable): aasv2.Referable { + const referable: aasv2.Referable = { + idShort: source.idShort, + modelType: { name: this.writeModelTypes(source.modelType) } + }; + + if (source.category) { + referable.category = source.category as aasv2.Category; + } + + if (source.descriptions) { + referable.descriptions = source.descriptions.map(item => ({ language: item.language, text: item.text })); + } + + return referable; + } + + private writeHasDataSpecification(source: aas.HasDataSpecification): aasv2.HasDataSpecification { + const hasDataSpecification: aasv2.HasDataSpecification = {}; + if (source.embeddedDataSpecifications) { + hasDataSpecification.embeddedDataSpecifications = source.embeddedDataSpecifications + .map(item => this.writeEmbeddedDatSpecification(item)); + } + + return hasDataSpecification; + } + + private writeEmbeddedDatSpecification(source: aas.EmbeddedDataSpecification): aasv2.EmbeddedDataSpecification { + if (!source.dataSpecification) { + throw new Error('EmbeddedDataSpecification.dataSpecification'); + } + + if (!source.dataSpecificationContent) { + throw new Error('EmbeddedDataSpecification.dataSpecificationContent'); + } + + const dataSpecificationContent = this.writeDataSpecificationIEC61360( + source.dataSpecificationContent as aas.DataSpecificationIEC61360); + + const specification: aasv2.EmbeddedDataSpecification = { + dataSpecification: this.writeReference(source.dataSpecification), + dataSpecificationContent + }; + + return specification; + } + + private writeDataSpecificationIEC61360(source: aas.DataSpecificationIEC61360): aasv2.DataSpecificationIEC61360Content { + if (!source.preferredName) { + throw new Error(`DataSpecificationIEC61360.preferredName`); + } + + const iec61360: aasv2.DataSpecificationIEC61360Content = { + preferredName: source.preferredName + } + + if (source.dataType) { + iec61360.dataType = this.writeDataTypeIEC61360(source.dataType); + } + + if (source.definition) { + iec61360.definition = source.definition; + } + + if (source.levelType) { + iec61360.levelType = source.levelType; + } + + if (source.shortName) { + iec61360.shortName = source.shortName; + } + + if (source.sourceOfDefinition) { + iec61360.sourceOfDefinition = source.sourceOfDefinition; + } + + if (source.symbol) { + iec61360.symbol = source.symbol; + } + + if (source.unit) { + iec61360.unit = source.unit; + } + + if (source.unitId) { + iec61360.unitId = this.writeReference(source.unitId); + } + + if (source.value) { + iec61360.value = source.value; + } + + if (source.valueFormat) { + iec61360.valueFormat = source.valueFormat; + } + + if (source.valueList) { + iec61360.valueList = this.writeValueList(source.valueList); + } + + return iec61360; + } + + private writeValueList(source: aas.ValueList): aasv2.ValueList { + if (!source.valueReferencePairs) { + throw new Error('ValueList.valueReferencePairs'); + } + + return { valueReferencePairTypes: source.valueReferencePairs.map(item => { + const pair: aasv2.ValueReferencePairType = {}; + if (item.value) { + pair.value = item.value; + } + + if (item.valueId) { + pair.valueId = this.writeReference(item.valueId); + } + + return pair; + }) }; + } + + private writeDataTypeIEC61360(source: aas.DataTypeIEC61360): aasv2.DataTypeIEC61360 { + switch (source) { + case 'IRDI': + case 'IRI': + return 'URL'; + default: + return source as aasv2.DataTypeIEC61360; + } + } + + private writeHasSemantic(source: aas.HasSemantic): aasv2.HasSemantic { + const hasSemantic: aasv2.HasSemantic = {}; + if (source.semanticId) { + hasSemantic.semanticId = this.writeReference(source.semanticId); + } + + return hasSemantic; + } + + private writeQualifiable(source: aas.Qualifiable): aasv2.Qualifiable { + const qualifiable: aasv2.Qualifiable = {}; + + if (source.qualifiers) { + qualifiable.qualifiers = source.qualifiers.map(item => this.writeQualifier(item)); + } + + return qualifiable; + } + + private writeQualifier(source: aas.Qualifier): aasv2.Qualifier { + if (!source.valueType) { + throw new Error('Qualifier.valueType'); + } + + const qualifier: aasv2.Qualifier = { + modelType: { name: 'Qualifier' }, + type: source.type, + valueType: this.writeDataTypeDefXsd(source.valueType) + }; + + if (source.value) { + qualifier.value = source.value; + } + + if (source.valueId) { + qualifier.valueId = this.writeReference(source.valueId); + } + + return qualifier; + } + + private writeValueTypeDef(source: aas.DataTypeDefXsd): aasv2.ValueTypeDef { + return { dataObjectType: { name: this.writeDataTypeDefXsd(source) } }; + } + + private writeDataTypeDefXsd(source: aas.DataTypeDefXsd): aasv2.DataTypeDefXsd { + switch (source) { + case 'xs:anyURI': + return 'anyURI'; + case 'xs:base64Binary': + return 'base64Binary'; + case 'xs:boolean': + return 'boolean'; + case 'xs:byte': + return 'byte'; + case 'xs:date': + return 'date'; + case 'xs:dateTime': + return 'dateTime'; + case 'xs:decimal': + return 'decimal'; + case 'xs:double': + return 'double'; + case 'xs:duration': + return 'duration'; + case 'xs:float': + return 'float'; + case 'xs:gDay': + return 'gDay'; + case 'xs:gMonth': + return 'gMonth'; + case 'xs:gMonthDay': + return 'gMonthDay'; + case 'xs:gYear': + return 'gYear'; + case 'xs:gYearMonth': + return 'gYearMonth'; + case 'xs:hexBinary': + return 'hexBinary'; + case 'xs:int': + return 'int'; + case 'xs:integer': + return 'integer'; + case 'xs:long': + return 'long'; + case 'xs:negativeInteger': + return 'negativeInteger'; + case 'xs:nonNegativeInteger': + return 'nonNegativeInteger'; + case 'xs:nonPositiveInteger': + return 'nonPositiveInteger'; + case 'xs:positiveInteger': + return 'positiveInteger'; + case 'xs:short': + return 'short'; + case 'xs:string': + return 'string'; + case 'xs:time': + return 'time'; + case 'xs:unsignedByte': + return 'unsignedByte'; + case 'xs:unsignedInt': + return 'unsignedInt'; + case 'xs:unsignedLong': + return 'unsignedLong'; + case 'xs:unsignedShort': + return 'unsignedShort'; + default: + return source as aasv2.DataTypeDefXsd; + } + } + + private writeHasKind(source: aas.HasKind): aasv2.HasKind { + return { kind: source.kind ?? 'Instance' }; + } + + private writeKeyType(source: aas.Key): aasv2.KeyType { + if (source.type === 'Submodel' || source.type === 'AssetAdministrationShell' || + source.type === 'ConceptDescription') { + try { + const _ = new URL(source.value); + return 'IRI'; + } catch (_) { + return 'IRDI'; + } + } + + return 'IdShort'; + } + + private writeModelTypes(source: aas.ModelType): aasv2.ModelTypes { + switch (source) { + case 'BasicEventElement': + return 'BasicEvent'; + default: + return source as aasv2.ModelTypes; + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/json-writer.ts b/projects/aas-server/src/app/packages/json-writer.ts new file mode 100644 index 00000000..7c7621f0 --- /dev/null +++ b/projects/aas-server/src/app/packages/json-writer.ts @@ -0,0 +1,724 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from 'common'; +import { AASWriter } from './aas-writer.js'; + +/** */ +export class JsonWriter extends AASWriter { + public writeEnvironment(env: aas.Environment): any { + const conceptDescriptions = this.writeConceptDescriptions(env); + const assetAdministrationShells = this.writeAssetAdministrationShells(env); + const submodels = this.writeSubmodels(env); + return { assetAdministrationShells, submodels, conceptDescriptions }; + } + + /** + * Deserializes a Submodel or SubmodelElement from the specified source. + * @param data The serialized Submodel or SubmodelElement. + * @returns The deserialized Submodel or SubmodelElement. + */ + public write(source: aas.Referable): any { + switch (source.modelType) { + case 'AssetAdministrationShell': + throw new Error('Invalid operation.'); + case 'Submodel': + return this.writeSubmodel(source as aas.Submodel); + default: + return this.writeSubmodelElement(source as aas.SubmodelElement)!; + } + } + + private writeConceptDescriptions(env: aas.Environment): aas.ConceptDescription[] { + const conceptDescriptions: aas.ConceptDescription[] = []; + if (env.conceptDescriptions) { + for (const source of env.conceptDescriptions) { + conceptDescriptions.push(this.writeConceptDescription(source)); + } + } + + return conceptDescriptions; + } + + private writeAssetAdministrationShells(env: aas.Environment): aas.AssetAdministrationShell[] { + const shells: aas.AssetAdministrationShell[] = []; + if (env.assetAdministrationShells) { + for (const source of env.assetAdministrationShells) { + shells.push(this.writeAssetAdministrationShell(source)); + } + } + + return shells; + } + + private writeAssetAdministrationShell(source: aas.AssetAdministrationShell): aas.AssetAdministrationShell { + if (!source.assetInformation) { + throw new Error('AssetAdministrationShell.asset'); + } + + const shell: aas.AssetAdministrationShell = { + ...this.writeIdentifiable(source), + ...this.writeHasDataSpecification(source), + assetInformation: this.writeAssetInformation(source.assetInformation) + }; + + if (source.derivedFrom) { + shell.derivedFrom = this.writeReference(source.derivedFrom); + } + + if (source.administration) { + shell.administration = this.writeAdministrationInformation(source.administration); + } + + if (source.submodels) { + shell.submodels = source.submodels.map(item => this.writeReference(item)); + } + + return shell; + } + + private writeAssetInformation(source: aas.AssetInformation): aas.AssetInformation { + if (!source.assetKind) { + throw new Error('AssetInformation.assetKind'); + } + + const asset: aas.AssetInformation = { assetKind: source.assetKind }; + if (source.globalAssetId) { + asset.globalAssetId = source.globalAssetId; + } + + if (source.specificAssetIds) { + asset.specificAssetIds = source.specificAssetIds.map(item => this.writeSpecificAssetId(item)); + } + + return asset; + } + + private writeSpecificAssetId(source: aas.SpecificAssetId): aas.SpecificAssetId { + if (!source.name) { + throw new Error('SpecificAssetId.name'); + } + + if (!source.value) { + throw new Error('SpecificAssetId.value'); + } + + if (!source.externalSubjectId) { + throw new Error('SpecificAssetId.externalSubjectId'); + } + + return { + ...this.writeHasSemantic, + name: source.name, + value: source.value, + externalSubjectId: this.writeReference(source.externalSubjectId) + }; + } + + private writeAdministrationInformation(source: aas.AdministrativeInformation): aas.AdministrativeInformation { + const info: aas.AdministrativeInformation = {}; + if (source.revision) { + info.revision = source.revision; + } + + if (source.version) { + info.version = source.version; + } + + return info; + } + + private writeConceptDescription(source: aas.ConceptDescription): aas.ConceptDescription { + const conceptDescription: aas.ConceptDescription = { + ...this.writeIdentifiable(source), + ...this.writeHasDataSpecification(source) + }; + + if (source.isCaseOf) { + conceptDescription.isCaseOf = source.isCaseOf.map(item => this.writeReference(item)); + } + + return conceptDescription; + } + + private writeSubmodels(env: aas.Environment): aas.Submodel[] { + const submodels: aas.Submodel[] = []; + if (env.submodels) { + for (const item of env.submodels) { + submodels.push(this.writeSubmodel(item)); + } + } + + return submodels; + } + + private writeSubmodel(source: aas.Submodel): aas.Submodel { + const submodel: aas.Submodel = { + ...this.writeIdentifiable(source), + ...this.writeHasSemantic(source), + ...this.writeQualifiable(source), + ...this.writeHasKind(source), + ...this.writeHasDataSpecification(source) + }; + + if (source.submodelElements) { + submodel.submodelElements = this.writeSubmodelElements(source.submodelElements); + } + + return submodel; + } + + private writeSubmodelElements(sources: aas.SubmodelElement[]): aas.SubmodelElement[] { + const submodelElements: aas.SubmodelElement[] = []; + for (const source of sources) { + const submodelElement = this.writeSubmodelElement(source); + if (submodelElement) { + submodelElements.push(submodelElement); + } + } + + return submodelElements; + } + + private writeSubmodelElement(source: aas.SubmodelElement): aas.SubmodelElement | undefined { + switch (source.modelType) { + case 'AnnotatedRelationshipElement': + return this.writeAnnotatedRelationshipElement(source as aas.AnnotatedRelationshipElement); + case 'BasicEventElement': + return this.writeBasicEventElement(source as aas.BasicEventElement); + case 'Blob': + return this.writeBlob(source as aas.Blob); + case 'Entity': + return this.writeEntity(source as aas.Entity); + case 'File': + return this.writeFile(source as aas.File); + case 'MultiLanguageProperty': + return this.writeMultiLanguageProperty(source as aas.MultiLanguageProperty); + case 'Operation': + return this.writeOperation(source as aas.Operation); + case 'Property': + return this.writeProperty(source as aas.Property); + case 'Range': + return this.writeRange(source as aas.Range); + case 'ReferenceElement': + return this.writeReferenceElement(source as aas.ReferenceElement); + case 'RelationshipElement': + return this.writeRelationshipElement(source as aas.RelationshipElement); + case 'SubmodelElementCollection': + return this.writeSubmodelElementCollection(source as aas.SubmodelElementCollection); + case 'SubmodelElementList': + throw this.writeSubmodelElementList(source as aas.SubmodelElementList); + default: + return undefined; + } + } + + private writeSubmodelElementType(source: aas.SubmodelElement): aas.SubmodelElement { + return { + ...this.writeReferable(source, undefined), + ...this.writeHasSemantic(source), + ...this.writeHasKind(source), + ...this.writeHasDataSpecification(source), + ...this.writeQualifiable(source) + }; + } + + private writeAnnotatedRelationshipElement( + source: aas.AnnotatedRelationshipElement, + ancestors?: aas.Referable[]): aas.AnnotatedRelationshipElement { + if (!source.annotations) { + throw new Error('AnnotatedRelationshipElement.annotation') + } + + const relationship: aas.AnnotatedRelationshipElement = { + ...this.writeRelationshipElement(source), + annotations: this.writeSubmodelElements(source.annotations), + }; + + return relationship; + } + + private writeEventElement(source: aas.EventElement, ancestor?: aas.Referable[]): aas.EventElement { + return { ...this.writeSubmodelElementType(source) }; + } + + private writeBasicEventElement(source: aas.BasicEventElement): aas.BasicEventElement { + if (!source.observed) { + throw new Error('BasicEventElement.observed'); + } + + if (!source.direction) { + throw new Error('BasicEventElement.direction'); + } + + if (!source.state) { + throw new Error('BasicEventElement.state'); + } + + const eventElement: aas.BasicEventElement = { + ...this.writeEventElement(source), + observed: source.observed, + direction: source.direction, + state: source.state + }; + + if (source.messageTopic) { + eventElement.messageTopic = source.messageTopic; + } + + if (source.messageBroker) { + eventElement.messageBroker = this.writeReference(source.messageBroker); + } + + if (source.lastUpdate) { + eventElement.lastUpdate = source.lastUpdate; + } + + if (source.minInterval) { + eventElement.minInterval = source.minInterval; + } + + if (source.maxInterval) { + eventElement.maxInterval = source.maxInterval; + } + + return eventElement; + } + + private writeProperty(source: aas.Property): aas.Property { + if (!source.valueType) { + throw new Error('Property.valueType'); + } + + const property: aas.Property = { + ...this.writeSubmodelElementType(source), + valueType: source.valueType + }; + + if (source.value) { + property.value = source.value; + } + + return property; + } + + private writeMultiLanguageProperty(source: aas.MultiLanguageProperty): aas.MultiLanguageProperty { + let value: aas.LangString[] | undefined; + if (Array.isArray(source.value)) { + value = source.value.map(item => ({ language: item.language, text: item.text })); + } + + if (!value) { + value = []; + } + + return { ...this.writeSubmodelElementType(source), value }; + } + + private writeOperation(source: aas.Operation): aas.Operation { + const operation: aas.Operation = { + ...this.writeSubmodelElementType(source) + }; + + if (source.inputVariables) { + operation.inputVariables = source.inputVariables.map(item => this.writeOperationVariable(item)); + } + + if (source.inoutputVariables) { + operation.inoutputVariables = source.inoutputVariables.map(item => this.writeOperationVariable(item)); + } + + if (source.outputVariables) { + operation.outputVariables = source.outputVariables.map(item => this.writeOperationVariable(item)); + } + + return operation; + } + + private writeOperationVariable(source: aas.OperationVariable): aas.OperationVariable { + if (!source.value) { + throw new Error('OperationVariable.value'); + } + + return { value: this.writeSubmodelElementType(source.value) }; + } + + private writeFile(source: aas.File): aas.File { + if (!source.contentType) { + throw new Error('Blob.contentType'); + } + + const file: aas.File = { + ...this.writeSubmodelElementType(source), + contentType: source.contentType + }; + + if (source.value) { + file.value = source.value; + } + + return file; + } + + private writeBlob(source: aas.Blob): aas.Blob { + if (!source.contentType) { + throw new Error('Blob.contentType'); + } + + const blob: aas.Blob = { + ...this.writeSubmodelElementType(source), + contentType: source.contentType + }; + + if (source.value) { + blob.value = source.value; + } + + return blob; + } + + private writeEntity(source: aas.Entity): aas.Entity { + if (!source.entityType) { + throw new Error('Entity.entityType'); + } + + const entity: aas.Entity = { + ...this.writeSubmodelElementType(source), + entityType: source.entityType + }; + + if (source.statements) { + entity.statements = source.statements.map(item => this.writeSubmodelElement(item)!); + } + + if (source.globalAssetId) { + entity.globalAssetId = source.globalAssetId; + } + + if (source.specificAssetId) { + entity.specificAssetId = this.writeSpecificAssetId(source.specificAssetId); + } + + return entity; + } + + private writeSubmodelElementCollection( + source: aas.SubmodelElementCollection, + ancestors?: aas.Referable[]): aas.SubmodelElementCollection { + const collection: aas.SubmodelElementCollection = { + ...this.writeSubmodelElementType(source) + }; + + if (source.value) { + collection.value = this.writeSubmodelElements(source.value); + } + + return collection; + } + + private writeSubmodelElementList(source: aas.SubmodelElementList): aas.SubmodelElementCollection { + if (!source.typeValueListElement) { + throw new Error('SubmodelElement.typeValueListElement'); + } + + const list: aas.SubmodelElementList = { + ...this.writeSubmodelElementType(source), + typeValueListElement: source.typeValueListElement, + valueTypeListElement: source.valueTypeListElement + }; + + if (source.orderRelevant) { + list.orderRelevant = source.orderRelevant; + } + + if (source.semanticIdListElement) { + list.semanticIdListElement = this.writeReference(source.semanticIdListElement); + } + + if (source.value) { + list.value = this.writeSubmodelElements(source.value); + } + + return list; + } + + private writeReferenceElement(source: aas.ReferenceElement): aas.ReferenceElement { + if (!source.value) { + throw new Error('ReferenceElement.value'); + } + + const reference: aas.ReferenceElement = { + ...this.writeSubmodelElementType(source), + value: this.writeReference(source.value) + }; + + return reference; + } + + private writeRelationshipElement(source: aas.RelationshipElement): aas.RelationshipElement { + if (!source.first) { + throw new Error('RelationshipElement.first') + } + + if (!source.second) { + throw new Error('RelationshipElement.second') + } + + const relationship: aas.RelationshipElement = { + ...this.writeSubmodelElementType(source), + first: this.writeReference(source.first), + second: this.writeReference(source.second) + }; + + return relationship; + } + + private writeRange(source: aas.Range): aas.Range { + if (!source.valueType) { + throw new Error('Range.valueType'); + } + + const range: aas.Range = { + ...this.writeSubmodelElementType(source), + valueType: source.valueType + }; + + if (source.min) { + range.min = source.min; + } + + if (source.max) { + range.max = source.max; + } + + return range; + } + + private writeHasSemantic(source: aas.HasSemantic): aas.HasSemantic { + const hasSemantic: aas.HasSemantic = {}; + if (source.semanticId) { + hasSemantic.semanticId = this.writeReference(source.semanticId); + } + + return hasSemantic; + } + + private writeHasKind(source: aas.HasKind): aas.HasKind { + return { kind: source.kind ?? 'Instance' }; + } + + private writeQualifiable(source: aas.Qualifiable): aas.Qualifiable { + const qualifiable: aas.Qualifiable = {}; + if (source.qualifiers) { + qualifiable.qualifiers = source.qualifiers.map(item => this.writeQualifier(item)); + } + + return qualifiable; + } + + private writeQualifier(source: aas.Qualifier): aas.Qualifier { + if (!source.type) { + throw new Error('Qualifier.type'); + } + + if (!source.valueType) { + throw new Error('Qualifier.valueType'); + } + + const qualifier: aas.Qualifier = { + ...this.writeHasSemantic(source), + type: source.type, + valueType: source.valueType + }; + + if (source.kind) { + qualifier.kind = source.kind; + } + + if (source.value) { + qualifier.value = source.value; + } + + if (source.valueId) { + qualifier.valueId = this.writeReference(source.valueId); + } + + return qualifier; + } + + private writeReferable(source: aas.Referable, id?: string): aas.Referable { + if (!source.modelType) { + throw Error(`Referable.modelType.`); + } + + const referable: aas.Referable = { idShort: source.idShort, modelType: source.modelType }; + + if (source.category) { + referable.category = source.category as aas.Category; + } + + if (source.descriptions) { + referable.descriptions = source.descriptions.map(item => ({ text: item.text, language: item.language })); + } + + return referable; + } + + private writeIdentifiable(source: aas.Identifiable): aas.Identifiable { + if (!source.id) { + throw new Error('Identifiable.identification'); + } + + const identifiable: aas.Identifiable = { + ...this.writeReferable(source, source.id), + id: source.id + }; + + if (source.administration) { + identifiable.administration = source.administration; + } + + return identifiable; + } + + private writeReference(source: aas.Reference): aas.Reference { + return { + type: source.type, + keys: source.keys.map((key, index) => { + if (!key.type) { + throw new Error(`Reference.type`); + } + + if (!key.value) { + throw new Error(`Reference.value`); + } + + return { + type: key.type, + value: key.value, + } as aas.Key; + }) + }; + } + + private writeHasDataSpecification(source: aas.HasDataSpecification): aas.HasDataSpecification { + const hasDataSpecification: aas.HasDataSpecification = {}; + if (source.embeddedDataSpecifications) { + hasDataSpecification.embeddedDataSpecifications = source.embeddedDataSpecifications + .map(item => this.writeEmbeddedDatSpecification(item)); + } + + return hasDataSpecification; + } + + private writeEmbeddedDatSpecification(source: aas.EmbeddedDataSpecification): aas.EmbeddedDataSpecification { + if (!source.dataSpecification) { + throw new Error('EmbeddedDataSpecification.dataSpecification'); + } + + if (!source.dataSpecificationContent) { + throw new Error('EmbeddedDataSpecification.dataSpecificationContent'); + } + + let dataSpecificationContent: aas.DataSpecificationContent; + if (source.dataSpecificationContent.modelType === 'DataSpecificationIEC61360') { + dataSpecificationContent = this.writeDataSpecificationIEC61360( + source.dataSpecificationContent as aas.DataSpecificationIEC61360); + } else { + throw new Error(`${source.dataSpecificationContent.modelType} is a not supported DataSpecificationContent.`); + } + + const specification: aas.EmbeddedDataSpecification = { + dataSpecification: this.writeReference(source.dataSpecification), + dataSpecificationContent + }; + + return specification; + } + + private writeDataSpecificationIEC61360(source: aas.DataSpecificationIEC61360): aas.DataSpecificationIEC61360 { + if (!source.preferredName) { + throw new Error(`DataSpecificationIEC61360.preferredName`); + } + + const iec61360: aas.DataSpecificationIEC61360 = { + modelType: source.modelType, + preferredName: source.preferredName + } + + if (source.dataType) { + iec61360.dataType = source.dataType; + } + + if (source.definition) { + iec61360.definition = source.definition; + } + + if (source.levelType) { + iec61360.levelType = source.levelType; + } + + if (source.shortName) { + iec61360.shortName = source.shortName; + } + + if (source.sourceOfDefinition) { + iec61360.sourceOfDefinition = source.sourceOfDefinition; + } + + if (source.symbol) { + iec61360.symbol = source.symbol; + } + + if (source.unit) { + iec61360.unit = source.unit; + } + + if (source.unitId) { + iec61360.unitId = this.writeReference(source.unitId); + } + + if (source.value) { + iec61360.value = source.value; + } + + if (source.valueFormat) { + iec61360.valueFormat = source.valueFormat; + } + + if (source.valueList) { + iec61360.valueList = this.writeValueList(source.valueList); + } + + return iec61360; + } + + private writeValueList(source: aas.ValueList): aas.ValueList { + if (!source.valueReferencePairs) { + throw new Error('ValueList.valueReferencePairs'); + } + + const valueList: aas.ValueList = { + valueReferencePairs: source.valueReferencePairs.map(item => this.writeValueReferencePair(item)) + }; + + return valueList; + } + + private writeValueReferencePair(source: aas.ValueReferencePair): aas.ValueReferencePair { + if (!source.value) { + throw new Error('ValueReferencePair.value'); + } + + if (!source.valueId) { + throw new Error('ValueReferencePair.valueId'); + } + + return { value: source.value, valueId: this.writeReference(source.valueId) }; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/client-file.ts b/projects/aas-server/src/app/packages/opcua/client-file.ts new file mode 100644 index 00000000..b1d83bf1 --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/client-file.ts @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { + BrowseDirection, + Byte, + ClientSession, + DataType, + Int32, + NodeId, + ResultMask, + StatusCodes, + VariantArrayType +} from 'node-opcua'; + +export enum OpenFileMode { + Read = 1 +} + +export class ClientFile { + private readonly fileNodeId: NodeId; + private fileHandle = 0; + private openMethodNodeId?: NodeId; + private closeMethodNodeId?: NodeId; + private readMethodNodeId?: NodeId; + + constructor(private session: ClientSession, fileNodeId: NodeId | string) { + this.fileNodeId = NodeId.resolveNodeId(fileNodeId); + } + + public async open(mode: OpenFileMode): Promise { + if (mode == null) { + throw new Error('Invalid mode.'); + } + + if (this.fileHandle) { + throw new Error('File is already open.'); + } + + if (!this.openMethodNodeId) { + await this.ensureInitialized(); + } + + const result = await this.session.call({ + inputArguments: [ + { dataType: DataType.Byte, value: mode as Byte } + ], + methodId: this.openMethodNodeId, + objectId: this.fileNodeId + }); + + if (result.statusCode !== StatusCodes.Good) { + throw new Error('cannot open file statusCode = ' + result.statusCode.toString() + ' mode = ' + OpenFileMode[mode]); + } + + this.fileHandle = result.outputArguments![0].value; + + return this.fileHandle; + } + + public async close(): Promise { + if (!this.fileHandle) { + throw new Error('File has not been opened yet'); + } + + if (!this.closeMethodNodeId) { + await this.ensureInitialized(); + } + + const result = await this.session.call({ + inputArguments: [ + { dataType: DataType.UInt32, value: this.fileHandle } + ], + methodId: this.closeMethodNodeId, + objectId: this.fileNodeId + }); + + if (result.statusCode !== StatusCodes.Good) { + throw new Error('Cannot close file: statusCode = ' + result.statusCode.toString()); + } + + this.fileHandle = 0; + } + + public async read(bytesToRead: Int32): Promise { + if (!this.readMethodNodeId) { + await this.ensureInitialized(); + } + + if (!this.fileHandle) { + throw new Error('File has not been opened yet.'); + } + + const result = await this.session.call({ + inputArguments: [ + { dataType: DataType.UInt32, value: this.fileHandle }, + { + arrayType: VariantArrayType.Scalar, + dataType: DataType.Int32, + value: bytesToRead + } + ], + methodId: this.readMethodNodeId, + objectId: this.fileNodeId + }); + + if (result.statusCode !== StatusCodes.Good) { + throw new Error(result.statusCode.toString()); + } + + if (!result.outputArguments || result.outputArguments[0].dataType !== DataType.ByteString) { + throw new Error('Invalid output arguments.'); + } + + return result.outputArguments![0].value as Buffer; + } + + private async ensureInitialized(): Promise { + const result = await this.session.browse({ + browseDirection: BrowseDirection.Forward, + nodeId: this.fileNodeId, + resultMask: ResultMask.BrowseName | ResultMask.TypeDefinition + }); + + if (result.references) { + for (const node of result.references) { + switch (node.browseName.name) { + case 'Open': + this.openMethodNodeId = node.nodeId; + break; + case 'Close': + this.closeMethodNodeId = node.nodeId; + break; + case 'Read': + this.readMethodNodeId = node.nodeId; + break; + } + } + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/opaque-structure-decoder.ts b/projects/aas-server/src/app/packages/opcua/opaque-structure-decoder.ts new file mode 100644 index 00000000..ddbaa188 --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/opaque-structure-decoder.ts @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { BinaryStream, DataValueOptions } from 'node-opcua'; +import { OpaqueStructure } from 'node-opcua-extension-object'; +import { aas } from 'common'; +import { UAKeyElements, UAKeyType } from './opcua.js'; + +export function decodeOpaqueStructure(value: OpaqueStructure, dataType: string): DataValueOptions { + if (dataType === 'AASKeyDataType') { + return { + value: { + arrayType: 'Array', + dimensions: [1], + value: decodeToKeyArray(value.buffer) + } + }; + } + + throw new Error('Invalid operation.'); + + function decodeToKeyArray(buffer: Buffer): aas.Key[] { + const keys: aas.Key[] = []; + const stream = new BinaryStream(buffer); + while (stream.length < stream.buffer.byteLength) { + const type = stream.readUInt32() as UAKeyElements; + const id = stream.readString() as string; + keys.push({ + type: toKeyTypes(type), + value: id + }); + } + + return keys; + + function toKeyTypes(value: UAKeyElements): aas.KeyTypes { + return UAKeyElements[value] as aas.KeyTypes; + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/opcua-data-type-dictionary.ts b/projects/aas-server/src/app/packages/opcua/opcua-data-type-dictionary.ts new file mode 100644 index 00000000..bad322f6 --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/opcua-data-type-dictionary.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from 'common'; +import { BrowseDescriptionLike, ClientSession, NodeClass, NodeIdLike, resolveNodeId } from 'node-opcua'; + +interface DataTypeEntry { + name: string; + baseType: string | null; +} + +export class OpcuaDataTypeDictionary { + private readonly dataTypes: Map = new Map(); + + public get(nodeId: NodeIdLike | null | undefined): aas.DataTypeDefXsd { + let entry: DataTypeEntry | undefined; + if (nodeId) { + entry = this.dataTypes.get(resolveNodeId(nodeId).toString()); + } + + return this.toDataTypeDefXsd(entry?.name); + } + + public async initializeAsync(session: ClientSession): Promise { + this.dataTypes.clear(); + await this.browseAsync(session, 'DataTypesFolder'); + } + + private async browseAsync(session: ClientSession, nodeToBrowse: BrowseDescriptionLike): Promise { + const result = await session.browse(nodeToBrowse); + if (result.references) { + for (const obj of result.references) { + if (obj.nodeClass === NodeClass.DataType && obj.browseName.name) { + this.dataTypes.set(obj.nodeId.toString(), { + name: obj.browseName.name, + baseType: null + }); + } + + if (obj.nodeClass === NodeClass.Object || obj.nodeClass === NodeClass.DataType) { + await this.browseAsync(session, obj.nodeId.toString()); + } + } + } + } + + private toDataTypeDefXsd(name: string | undefined): aas.DataTypeDefXsd { + throw new Error('Method not implemented.'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/opcua-package.ts b/projects/aas-server/src/app/packages/opcua/opcua-package.ts new file mode 100644 index 00000000..c1b0611c --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/opcua-package.ts @@ -0,0 +1,188 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AttributeIds, ClientSession, DataType, DataValue, NodeId, VariantArrayType } from 'node-opcua'; +import { NodeCrawler } from 'node-opcua-client-crawler'; +import { OpaqueStructure } from 'node-opcua-extension-object'; +import { Readable } from 'stream'; +import { OpcuaServer } from './opcua-server.js'; +import { OPCUAComponent, OPCUAProperty, readDataTypeAsync } from './opcua.js'; +import { AASPackage } from '../aas-package.js'; +import { Logger } from '../../logging/logger.js'; +import { decodeOpaqueStructure } from './opaque-structure-decoder.js'; +import { OpcuaDataTypeDictionary } from './opcua-data-type-dictionary.js'; +import { ClientFile, OpenFileMode } from './client-file.js'; +import { AASDocument, aas } from 'common'; +import { OpcuaReader } from './opcua-reader.js'; + +export class OpcuaPackage extends AASPackage { + private readonly server: OpcuaServer; + private readonly nodeId: string; + private readonly dataTypes: OpcuaDataTypeDictionary; + + constructor( + logger: Logger, + server: OpcuaServer, + nodeId: string, + dataTypes?: OpcuaDataTypeDictionary) { + super(logger); + + this.server = server; + this.nodeId = nodeId; + this.dataTypes = dataTypes ?? new OpcuaDataTypeDictionary(); + } + + public async createDocumentAsync(): Promise { + const component = await this.crawlAsync(); + const reader = new OpcuaReader(this.logger, component, this.dataTypes); + const environment = await reader.readEnvironment(); + + if (component.typeDefinition !== 'AASAssetAdministrationShellType') { + throw new Error(`${this.nodeId}: ${component.typeDefinition} is an unexpected type definition.`); + } + + const document: AASDocument = { + id: this.getIdentifier(component), + container: this.server.url.href, + endpoint: { type: 'opc', address: this.nodeId }, + idShort: component.browseName, + content: environment, + timeStamp: Date.now(), + readonly: this.server.readOnly, + onlineReady: this.server.onlineReady, + modified: false + }; + + return document; + } + + public getThumbnailAsync(): Promise { + return Promise.reject(new Error('Not implemented.')); + } + + public commitDocumentAsync(): Promise { + throw new Error('Method not implemented.'); + } + + public async openReadStreamAsync(_: aas.Environment, file: aas.File): Promise { + const session = this.server.getSession(); + if (!file.nodeId) { + throw new Error('Invalid operation.'); + } + + const clientFile = new ClientFile(session, file.nodeId); + await clientFile.open(OpenFileMode.Read) + try { + const buffer = await clientFile.read(0); + return Readable.from(buffer); + } finally { + await clientFile.close(); + } + } + + private async crawlAsync(): Promise { + const crawler = new NodeCrawler(this.server.getSession()); + const component = await crawler.read(NodeId.resolveNodeId(this.nodeId)) as OPCUAComponent; + await this.resolveAsync(component); + return component; + } + + private async resolveAsync(component: OPCUAComponent, visited: Set = new Set()): Promise { + const nodeId = component.nodeId.toString(); + if (!visited.has(nodeId)) { + visited.add(nodeId); + if (component.hasProperty) { + const session = this.server.getSession(); + for (const property of component.hasProperty) { + if (property.dataValue.value?.dataType === 'ExtensionObject') { + const dataValue = await this.readDataValueAsync(session, property); + const opaqueStructure = this.readOpaqueStructure(dataValue); + if (opaqueStructure) { + const dataType = await readDataTypeAsync(session, property.dataType); + property.dataValue = decodeOpaqueStructure(opaqueStructure[0], dataType); + } + } + } + } + + if (component.hasComponent) { + for (const child of component.hasComponent) { + await this.resolveAsync(child, visited); + } + } + + if (component.hasAddIn) { + for (const addIn of component.hasAddIn) { + await this.resolveAsync(addIn, visited); + } + } + } + } + + private async readDataValueAsync(session: ClientSession, property: OPCUAProperty): Promise { + return await session.read( + { + nodeId: property.nodeId, + attributeId: AttributeIds.Value + }); + } + + private readOpaqueStructure(dataValue: DataValue): OpaqueStructure[] | undefined { + if (dataValue.value?.dataType === DataType.ExtensionObject) { + const value = dataValue.value; + if (value.arrayType === VariantArrayType.Array) { + if (Array.isArray(value.value) && value.value.length > 0 && value.value[0] instanceof OpaqueStructure) { + return value.value as OpaqueStructure[]; + } + } + } + + return undefined; + } + + private getIdentifier(component: OPCUAComponent): string { + let id = this.readIdentifier(component); + if (!id) { + id = this.nodeId; + this.logger.debug(`Unable to read AAS identifier for '${component.browseName}' in '${this.server.url}'.'`); + } + + return id; + } + + private readIdentifier(component: OPCUAComponent): string | undefined { + const identification = this.selectComponent(component, 'Identification'); + return identification ? this.getPropertyValue(identification, 'Id', '') : undefined; + } + + private selectComponent(parent: OPCUAComponent, browseName: string): OPCUAComponent | undefined { + if (parent.hasComponent) { + for (const component of parent.hasComponent) { + if (component.browseName === browseName) { + return component; + } + } + } + + return undefined; + } + + private getPropertyValue(parent: OPCUAComponent, browseName: string, fallback: T): T { + let value: T = fallback; + if (parent.hasProperty) { + for (const property of parent.hasProperty) { + if (property.browseName === browseName) { + value = property.dataValue.value?.value as T; + break; + } + } + } + + return value; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/opcua-reader.ts b/projects/aas-server/src/app/packages/opcua/opcua-reader.ts new file mode 100644 index 00000000..aea4206e --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/opcua-reader.ts @@ -0,0 +1,693 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, convertToString, determineType } from "common"; +import { ArgumentOptions, LocalizedText, VariantArrayType, VariantOptions } from "node-opcua"; +import { Logger } from "../../logging/logger.js"; +import { AASReader } from "../aas-reader.js"; +import { OpcuaDataTypeDictionary } from "./opcua-data-type-dictionary.js"; +import { + OPCUAComponent, + OPCUAProperty, + TypeDefinition, + UAEntityType, + UAKey, + UAKeyElements, + ValueType +} from "./opcua.js"; +import { noop } from 'lodash-es'; + +export class OpcuaReader extends AASReader { + constructor( + private readonly logger: Logger, + private readonly origin: OPCUAComponent, + private readonly dataTypes: OpcuaDataTypeDictionary) { + super(); + } + + public readEnvironment(): aas.Environment { + const conceptDescriptions = this.readConceptDescriptions(); + const assetAdministrationShells = this.readAssetAdministrationShells(); + const submodels: aas.Submodel[] = this.readSubmodels(this.origin); + return { assetAdministrationShells, submodels, conceptDescriptions } + } + + public read(data: any): aas.Referable { + throw new Error('Not implemented.'); + } + + private readConceptDescriptions(): aas.ConceptDescription[] { + // ToDo + return []; + } + + private readAssetAdministrationShells(): aas.AssetAdministrationShell[] { + const shell = this.readAssetAdministrationShell(this.origin); + return [shell]; + } + + private readAssetAdministrationShell(component: OPCUAComponent): aas.AssetAdministrationShell { + const shell: aas.AssetAdministrationShell = { + ...this.readIdentifiable(component), + ...this.readHasDataSpecification(component), + assetInformation: this.readAssetInformation(component) + } + + const submodels = this.readReferenceList(component, 'Submodel'); + if (submodels) { + shell.submodels = submodels; + } + + return shell; + } + + private readAssetInformation(component: OPCUAComponent): aas.AssetInformation { + let assetKind: aas.AssetKind | undefined; + let globalAssetId: string | undefined; + const assetComponent = this.selectComponent(this.origin, 'Asset'); + if (assetComponent) { + assetKind = this.readPropertyValue(assetComponent, 'AssetKind') ?? 'Instance'; + globalAssetId = this.readIdentifier(assetComponent); + } else { + const infoComponent = this.selectComponent(component, undefined, 'AASAssetInformationType'); + if (infoComponent) { + assetKind = this.readPropertyValue(infoComponent, 'AssetKind') ?? 'Instance'; + globalAssetId = this.readReference(infoComponent, 'GlobalAssetId')?.keys[0].value; + } + } + + if (!assetKind) { + throw new Error('AssetInformation.assetKind'); + } + + return { assetKind, globalAssetId }; + } + + private readSubmodels(parent: OPCUAComponent): aas.Submodel[] { + let submodels: aas.Submodel[] | undefined; + const component = this.selectComponent(parent, 'Submodel', 'AASReferenceList'); + if (component?.hasComponent) { + submodels = []; + for (const item of component.hasComponent) { + if (item.typeDefinition === 'AASReferenceType' && item.hasAddIn) { + for (const addIn of item.hasAddIn) { + submodels.push(this.readSubmodel(addIn)); + } + } + } + } + + return submodels ?? []; + } + + private readSubmodel(component: OPCUAComponent): aas.Submodel { + const submodel: aas.Submodel = { + ...this.readIdentifiable(component), + ...this.readHasSemantic(component), + ...this.readQualifiable(component), + ...this.readHasKind(component), + ...this.readHasDataSpecification(component) + } + + const submodelElements = this.readSubmodelElements( + component, + { + type: 'ModelReference', + keys: [{ + type: 'Submodel', + value: submodel.id, + }] + }); + if (submodelElements.length > 0) { + submodel.submodelElements = submodelElements; + } + + return submodel; + } + + private readSubmodelElements(component: OPCUAComponent, parent?: aas.Reference): aas.SubmodelElement[] { + const results = this.where(component.hasComponent, + 'AASBlobType', + 'AASCapabilityType', + 'AASEventType', + 'AASFileType', + 'AASPropertyType', + 'AASRangeType', + 'AASSubmodelElementCollectionType', + 'AASOrderedSubmodelElementCollectionType', + 'AASMultiLanguagePropertyType', + 'AASEntityType', + 'AASReferenceElementType', + 'AASRelationshipElementType', + 'AASOperationType'); + + const submodelElements: aas.SubmodelElement[] = []; + for (const component of results) { + const submodelElement = this.readSubmodelElement(component, parent); + if (submodelElement) { + submodelElements.push(submodelElement); + } + } + + return submodelElements; + } + + private readSubmodelElement(component: OPCUAComponent, parent?: aas.Reference): aas.SubmodelElement | undefined { + switch (component.typeDefinition) { + case 'AASBlobType': + break; + case 'AASCapabilityType': + break; + case 'AASEntityType': + return this.readEntity(component, parent); + case 'AASEventType': + break; + case 'AASFileType': + return this.readFile(component, parent); + case 'AASMultiLanguagePropertyType': + return this.readMultiLanguageProperty(component, parent); + case 'AASOperationType': + return this.readOperation(component, parent); + case 'AASOrderedSubmodelElementCollectionType': + return this.readSubmodelElementCollection(component, parent); + case 'AASPropertyType': + return this.readProperty(component, parent); + case 'AASRangeType': + break; + case 'AASReferenceElementType': + return this.readReferenceElement(component, parent); + case 'AASRelationshipElementType': + break; + case 'AASSubmodelElementCollectionType': + return this.readSubmodelElementCollection(component, parent); + } + + return undefined; + } + + private readModelType(component: OPCUAComponent): aas.ModelType { + switch (component.typeDefinition) { + case 'AASAssetAdministrationShellType': + return 'AssetAdministrationShell'; + case 'AASSubmodelType': + return 'Submodel'; + case 'AASPropertyType': + return 'Property'; + case 'AASFileType': + return 'File'; + case 'AASSubmodelElementCollectionType': + return 'SubmodelElementCollection'; + case 'AASMultiLanguagePropertyType': + return 'MultiLanguageProperty'; + case 'AASEntityType': + return 'Entity'; + case 'AASReferenceElementType': + return 'ReferenceElement'; + case 'AASOperationType': + return 'Operation'; + default: + throw new Error(`Type '${component.typeDefinition}' is not supported.`); + } + } + + private readSubmodelElementCollection( + component: OPCUAComponent, + parent?: aas.Reference): aas.SubmodelElementCollection { + const base = this.readSubmodelElementType(component, parent); + const collection: aas.SubmodelElementCollection = { + ...base + } + + const value = this.readSubmodelElements(component, parent ? this.createReference(parent, base) : undefined); + if (value.length > 0) { + collection.value = value; + } + + return collection; + } + + private readProperty(component: OPCUAComponent, parent?: aas.Reference): aas.Property { + const value = this.readPropertyValue(component, 'Value'); + let valueType = this.readDataTypeDefXsd(this.readPropertyValue(component, 'ValueType')); + if (!valueType && value != null) { + valueType = determineType(value); + } + + if (!valueType) { + throw new Error('Property.valueType'); + } + + const property: aas.Property = { + ...this.readSubmodelElementType(component, parent), + valueType: valueType, + nodeId: this.findProperty(component, 'Value')?.nodeId.toString() + }; + + if (value) { + property.value = convertToString(value); + } + + return property; + } + + private readFile(component: OPCUAComponent, parent?: aas.Reference): aas.File { + const contentType: string = this.readPropertyValue(component, 'MimeType'); + if (!contentType) { + throw new Error('File.mimeType'); + } + + const file: aas.File = { + ...this.readSubmodelElementType(component, parent), + contentType + }; + + const value: string = this.readPropertyValue(component, 'Value'); + if (value) { + file.value = value; + } + + const fileType = this.selectComponent(component, undefined, 'FileType'); + if (fileType) { + file.nodeId = fileType.nodeId.toString(); + } + + return file; + } + + private readMultiLanguageProperty(component: OPCUAComponent, parent?: aas.Reference): aas.MultiLanguageProperty { + const langString = this.readLangStringSet(component, 'Value') ?? []; + return { ...this.readSubmodelElementType(component, parent), value: langString }; + } + + private readLangStringSet(component: OPCUAComponent, propertyName: string): aas.LangString[] | undefined { + let langStrings: aas.LangString[] | undefined; + const value: LocalizedText[] = this.readPropertyValue(component, propertyName); + if (value) { + langStrings = value.map(item => ({ language: item.locale, text: item.text } as aas.LangString)); + } + + return langStrings; + } + + private readEntity(component: OPCUAComponent, parent?: aas.Reference): aas.Entity { + const entityType: aas.EntityType | undefined = this.toEntityType(this.readPropertyValue(component, 'EntityType')); + if (!entityType) { + throw new Error('Entity.entityType'); + } + + const entity: aas.Entity = { + ...this.readSubmodelElementType(component, parent), + entityType + }; + + const asset = this.readReference(component, 'Asset'); + if (asset) { + entity.globalAssetId = asset.keys[0].value; + } + + //ToDo Entity.statements + + return entity; + } + + private readReferenceElement(component: OPCUAComponent, parent?: aas.Reference): aas.ReferenceElement { + const value = this.readReference(component, 'Value'); + if (!value) { + throw new Error('ReferenceElement.value'); + } + + return { + ...this.readSubmodelElementType(component, parent), + value + }; + } + + private readOperation(component: OPCUAComponent, parent?: aas.Reference): aas.Operation { + const inputVariables: aas.OperationVariable[] = []; + const outputVariables: aas.OperationVariable[] = []; + const inoutputVariables: aas.OperationVariable[] = []; + let methodId: string | undefined; + let objectId: string | undefined; + const opComponent = this.selectComponent(component, undefined, 'Operation') ?? this.findOperationNode(component); + if (opComponent) { + methodId = opComponent.nodeId?.toString(); + objectId = component.nodeId?.toString(); + + const inputArguments: ArgumentOptions[] = this.readPropertyValue(opComponent, 'InputArguments'); + if (inputArguments) { + for (const inputArgument of inputArguments) { + inputVariables.push(this.createOperationVariable(inputArgument)); + } + } + + const outputArguments: ArgumentOptions[] = this.readPropertyValue(opComponent, 'OutputArguments'); + if (outputArguments) { + for (const outputArgument of outputArguments) { + outputVariables.push(this.createOperationVariable(outputArgument)); + } + } + } + + const operation: aas.Operation = { ...this.readSubmodelElementType(component, parent) }; + + if (inputVariables) { + operation.inputVariables = inputVariables; + } + + if (inoutputVariables) { + operation.inoutputVariables = inoutputVariables; + } + + if (outputVariables) { + operation.outputVariables = outputVariables; + } + + if (objectId) { + operation.objectId = objectId; + } + + if (methodId) { + operation.methodId = methodId; + } + + return operation; + } + + private readReference(parent: OPCUAComponent, name: string): aas.Reference | undefined { + let reference: aas.Reference | undefined; + const component = this.selectComponent(parent, name, 'AASReferenceType'); + if (component) { + const value: UAKey[] = this.readPropertyValue(component, 'Keys'); + if (Array.isArray(value) && value.length > 0) { + reference = { type: 'ModelReference', keys: value.map(key => this.readKey(key)) }; + } + } + + return reference; + } + + private readReferenceList(parent: OPCUAComponent, name: string): aas.Reference[] | undefined { + let referenceList: aas.Reference[] | undefined; + const component = this.selectComponent(parent, name, 'AASReferenceList'); + if (component?.hasComponent) { + referenceList = []; + for (const item of component.hasComponent) { + if (item.typeDefinition === 'AASReferenceType') { + const value = this.findProperty(item, 'Keys')?.dataValue.value?.value; + if (Array.isArray(value) && value.length > 0) { + referenceList.push({ type: 'ModelReference', keys: value.map(key => this.readKey(key)) }); + } + } + } + } + + return referenceList; + } + + private readKey(value: UAKey): aas.Key { + return { + type: this.toKeyTypes(value.type), + value: value.value, + }; + } + + private findOperationNode(element: OPCUAComponent): OPCUAComponent | undefined { + if (element.hasComponent) { + for (const component of element.hasComponent) { + if (this.hasProperty(component, 'InputArguments') && this.hasProperty(component, 'OutputArguments')) { + return component; + } + } + } + + return undefined; + } + + private createOperationVariable(argument: ArgumentOptions): aas.OperationVariable { + const value: aas.Property = { + modelType: 'Property', + idShort: argument.name!, + kind: 'Instance', + valueType: this.dataTypes.get(argument.dataType) + }; + + return { value }; + } + + private readSubmodelElementType(component: OPCUAComponent, parent?: aas.Reference): aas.SubmodelElement { + return { + ...this.readReferable(component, parent), + ...this.readHasSemantic(component), + ...this.readHasKind(component), + ...this.readHasDataSpecification(component), + ...this.readQualifiable(component) + }; + } + + private readIdentifiable(component: OPCUAComponent): aas.Identifiable { + const idComponent = this.selectComponent(component, 'Identification'); + if (!idComponent) { + throw new Error('Identifiable.identification'); + } + + const id = this.readIdentifier(idComponent)!; + const identifiable: aas.Identifiable = { ...this.readReferable(component), id }; + const adminInfoComponent = this.selectComponent(component, 'Administration'); + if (adminInfoComponent) { + const administration = this.readAdministrativeInformation(adminInfoComponent); + + if (administration) { + identifiable.administration = administration; + } + } + + return identifiable; + } + + private readAdministrativeInformation(component: OPCUAComponent): aas.AdministrativeInformation | undefined { + const info: aas.AdministrativeInformation = {}; + + const version: string = this.readPropertyValue(component, 'Version'); + if (version) { + info.version = version; + } + + const revision: string = this.readPropertyValue(component, 'Revision'); + if (revision) { + info.revision = revision; + } + + return info; + } + + private readReferable(component: OPCUAComponent, parent?: aas.Reference): aas.Referable { + const referable: aas.Referable = { + idShort: component.browseName, + modelType: this.readModelType(component) + }; + + if (parent) { + referable.parent = parent; + } + + const category: aas.Category = this.readPropertyValue(component, 'Category'); + if (category) { + referable.category = category; + } + + const descriptions = this.readLangStringSet(component, 'Description'); + if (descriptions) { + referable.descriptions = descriptions; + } + + return referable; + } + + private readHasSemantic(component: OPCUAComponent): aas.HasSemantic { + const semanticId = this.readReference(component, 'SemanticId'); + return semanticId ? { semanticId } : {}; + } + + private readHasKind(component: OPCUAComponent): aas.HasKind { + return { kind: this.readPropertyValue(component, 'ModellingKind') ?? 'Instance' }; + } + + private readHasDataSpecification(component: OPCUAComponent): aas.HasDataSpecification { + const dataSpecification: aas.HasDataSpecification = {}; + const child = this.selectComponent(component, 'DataSpecification', 'AASReferenceList') + if (child?.hasComponent) { + // ToDo: + } + + return dataSpecification; + } + + private readQualifiable(component: OPCUAComponent): aas.Qualifiable { + const qualifiable: aas.Qualifiable = {}; + const child = this.selectComponent(component, 'Qualifier', 'AASQualifierList'); + if (child?.hasComponent) { + noop(); + } + + return qualifiable; + } + + private readIdentifier(component: OPCUAComponent): string { + const id: string = this.readPropertyValue(component, 'Id'); + if (!id) { + throw new Error('Identifier.id'); + } + + return id; + } + + private selectComponent(parent: OPCUAComponent, name?: string, type?: TypeDefinition): OPCUAComponent | undefined { + return parent.hasComponent?.find(component => + (!name || component.browseName === name) && (!type || type === component.typeDefinition)); + } + + private hasProperty(component: OPCUAComponent, browseName: string): boolean { + if (component.hasProperty) { + for (const property of component.hasProperty) { + if (property.browseName === browseName) { + return true; + } + } + } + + return false; + } + + private findProperty(component: OPCUAComponent, browseName: string): OPCUAProperty | undefined { + if (component.hasProperty) { + for (const property of component.hasProperty) { + if (property.browseName === browseName) { + return property; + } + } + } + + return undefined; + } + + private readPropertyValue(component: OPCUAComponent, propertyName: string): any { + const property = this.findProperty(component, propertyName); + return property?.dataValue.value?.value; + } + + private getConceptDescription(semanticId: aas.Key | null): aas.ConceptDescription | undefined { + const conceptDescription: aas.ConceptDescription | undefined = undefined; + if (semanticId) { + throw new Error('Not implemented'); + } + + return conceptDescription; + } + + private toReference(value: UAKey[]): aas.Reference { + return { + type: 'ModelReference', + keys: value.map(item => this.readKey(item)) + }; + } + + private where(components: OPCUAComponent[] | undefined, ...types: TypeDefinition[]): OPCUAComponent[] { + const items: OPCUAComponent[] = []; + if (components) { + const set = new Set(types); + for (const component of components) { + if (set.has(component.typeDefinition)) { + items.push(component); + } + else if (component.typeDefinition === 'AASReferenceList') { + if (component.browseName === 'Submodel' && component.hasComponent) { + for (const submodelReference of component.hasComponent) { + if (submodelReference.hasAddIn) { + for (const addInComponent of submodelReference.hasAddIn) { + if (set.has(addInComponent.typeDefinition)) { + items.push(addInComponent); + } + } + } + } + } + } + else if (component.typeDefinition === 'FolderType') { + if (component.hasComponent) { + for (const folderComponent of component.hasComponent) { + if (set.has(folderComponent.typeDefinition)) { + items.push(folderComponent); + } + } + } + } + } + } + + return items; + } + + private toKeyTypes(value: UAKeyElements): aas.KeyTypes { + return UAKeyElements[value] as aas.KeyTypes; + } + + private toEntityType(value?: UAEntityType | string): aas.EntityType | undefined { + if (typeof value === 'string') { + return value as aas.EntityType; + } + + return value ? UAEntityType[value] as aas.EntityType : undefined; + } + + private isArray(value: VariantOptions | undefined): boolean { + return value != null && (value.arrayType === VariantArrayType.Array || value.arrayType === 'Array'); + } + + private getArray(value: VariantOptions | undefined): T[] { + return value !== undefined ? value.value as T[] : []; + } + + private readDataTypeDefXsd(value?: ValueType | string): aas.DataTypeDefXsd | undefined { + if (value) { + const valueType = typeof value === 'string' ? value : ValueType[value]; + switch (valueType) { + case 'Boolean': + return 'xs:boolean'; + case 'SByte': + return 'xs:byte'; + case 'Byte': + return 'xs:unsignedByte'; + case 'Int16': + return 'xs:short'; + case 'UInt16': + return 'xs:unsignedShort'; + case 'Int32': + return 'xs:int'; + case 'UInt32': + return 'xs:unsignedInt'; + case 'Int64': + return 'xs:long'; + case 'UInt64': + return 'xs:unsignedLong'; + case 'Float': + return 'xs:float'; + case 'Double': + return 'xs:double'; + case 'LocalizedText': + case 'String': + return 'xs:string'; + case 'DateTime': + return 'xs:dateTime'; + default: + return valueType as aas.DataTypeDefXsd; + } + } + + return undefined; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/opcua-server.ts b/projects/aas-server/src/app/packages/opcua/opcua-server.ts new file mode 100644 index 00000000..12ebf94f --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/opcua-server.ts @@ -0,0 +1,255 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import fs from 'fs'; +import { LiveRequest, aas } from 'common'; +import { Logger } from '../../logging/logger.js'; +import { OpcuaSubscription } from '../../live/opcua/opcua-subscription.js'; +import { SocketClient } from '../../live/socket-client.js'; +import { SocketSubscription } from '../../live/socket-subscription.js'; +import { AASPackage } from '../aas-package.js'; +import { AASResource } from '../aas-resource.js'; +import { OpcuaPackage } from './opcua-package.js'; +import { + ClientSession, + ConnectionStrategyOptions, + DataType, + MessageSecurityMode, + OPCUAClient, + OPCUAClientOptions, + SecurityPolicy, + StatusCodes, + VariantArrayType, + VariantOptions, + coerceNodeId +} from 'node-opcua'; + +export class OpcuaServer extends AASResource { + private readonly options: OPCUAClientOptions; + private client: OPCUAClient | null = null; + private session: ClientSession | null = null; + private reentry = 0; + + constructor(logger: Logger, url: string | URL, options?: OPCUAClientOptions) { + super(logger, url); + + if (options) { + this.options = this.resolveOpcuaClientOptions(options); + } else { + this.options = { + applicationName: 'aas-server', + connectionStrategy: { + initialDelay: 1000, + maxRetry: 1 + }, + securityMode: MessageSecurityMode.None, + securityPolicy: SecurityPolicy.None, + endpointMustExist: false, + }; + } + } + + public readonly readOnly = true; + + public readonly onlineReady = true; + + public get isOpen(): boolean { + return this.reentry > 0; + } + + /** + * Gets the current client session. + **/ + public getSession(): ClientSession { + if (this.reentry <= 0 || this.session == null) { + throw new Error(`No session to ${this.baseUrl} established.`); + } + + return this.session; + } + + public async testAsync(): Promise { + if (this.reentry === 0) { + try { + await this.openAsync(); + } finally { + await this.closeAsync(); + } + } + } + + public async openAsync(): Promise { + if (this.reentry === 0) { + this.client = OPCUAClient.create(this.options as OPCUAClientOptions); + await this.client.connect(this.baseUrl.href); + this.session = await this.client.createSession(); + } + + ++this.reentry; + } + + public async closeAsync(): Promise { + if (this.reentry > 0) { + --this.reentry; + if (this.reentry === 0) { + if (this.client) { + if (this.session) { + await this.client.closeSession(this.session, true); + this.session = null; + } + + await this.client.disconnect(); + this.client = null; + } + } + } + } + + public createPackage(address: string): AASPackage { + return new OpcuaPackage(this.logger, this, address); + } + + public createSubscription(client: SocketClient, message: LiveRequest): SocketSubscription { + return new OpcuaSubscription(this.logger, client, this, message.nodes); + } + + public getPackageAsync(aasIdentifier: string, name: string): Promise { + throw new Error('Not implemented.'); + } + + public postPackageAsync(file: Express.Multer.File): Promise { + throw new Error('Not implemented.'); + } + + public deletePackageAsync(aasId: string, name: string): Promise { + throw new Error('Not implemented.'); + } + + public async invoke(env: aas.Environment, operation: aas.Operation): Promise { + const inputArguments: Array = []; + if (operation.inputVariables) { + for (let i = 0; i < operation.inputVariables.length; i++) { + inputArguments.push(await this.toVariantAsync(operation.inputVariables[i].value)); + } + } + + const result = await this.session!.call({ + inputArguments: inputArguments, + methodId: coerceNodeId(operation.methodId), + objectId: coerceNodeId(operation.objectId) + }); + + if (result.statusCode.value !== StatusCodes.Good.value) { + throw new Error(`Operation call returns with status code ${result.statusCode.toString()},`); + } + + if (result.outputArguments && operation.outputVariables) { + for (let index = 0; index < operation.outputVariables.length; ++index) { + operation.outputVariables[index].value = result.outputArguments[index].value; + } + } + + return operation; + } + + public getBlobValueAsync(env: aas.Environment, submodelId: string, idShortPath: string): Promise { + throw new Error('Not implemented.'); + } + + private resolveOpcuaClientOptions(options: OPCUAClientOptions): OPCUAClientOptions { + if (options) { + options = { + applicationName: options.applicationName, + connectionStrategy: this.resolveConnectionStrategy(options.connectionStrategy), + securityMode: this.resolveMode(options.securityMode), + securityPolicy: this.resolvePolicy(options.securityPolicy), + endpointMustExist: options.endpointMustExist, + } as OPCUAClientOptions; + } + + return options; + } + + private resolveConnectionStrategy(value?: ConnectionStrategyOptions): ConnectionStrategyOptions | undefined { + if (value) { + value = + { + initialDelay: value.initialDelay, + maxRetry: value.maxRetry + }; + } + + return value; + } + + private resolveMode(value?: string | MessageSecurityMode): MessageSecurityMode { + if (value) { + return typeof value === 'string' + ? MessageSecurityMode[value as keyof typeof MessageSecurityMode] + : value; + } + + return MessageSecurityMode.None; + } + + private resolvePolicy(value?: string | SecurityPolicy): SecurityPolicy { + if (value) { + return typeof value === 'string' + ? SecurityPolicy[value as keyof typeof SecurityPolicy] + : value; + } + + return SecurityPolicy.None; + } + + private async toVariantAsync(value: aas.SubmodelElement): Promise { + if (value.modelType === 'Property') { + const property = value as aas.Property; + switch (property.valueType) { + case 'xs:string': + let buffer: Buffer; + if (typeof property.value === 'string') { + buffer = await fs.promises.readFile(property.value); + } else if (property.value instanceof Buffer) { + buffer = property.value as Buffer; + } else { + throw new Error('Not supported File representation.'); + } + + return this.createVariantOptions(VariantArrayType.Scalar, DataType.ByteString, buffer); + default: + return this.createVariantOptions( + VariantArrayType.Scalar, + property.valueType, + property.value); + } + } else { + throw new Error('Not implemented.'); + } + } + + private createVariantOptions( + arrayType: VariantArrayType, + dataType: DataType | aas.DataTypeDefXsd | undefined, + value: any): VariantOptions { + if (typeof dataType === 'string') { + dataType = (DataType)[dataType]; + } + + if (typeof arrayType === 'string') { + arrayType = (VariantArrayType)[arrayType]; + } + + return { + arrayType: arrayType, + dataType: dataType, + value: value, + dimensions: Array.isArray(value) ? [1] : null + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/opcua/opcua.ts b/projects/aas-server/src/app/packages/opcua/opcua.ts new file mode 100644 index 00000000..79a20171 --- /dev/null +++ b/projects/aas-server/src/app/packages/opcua/opcua.ts @@ -0,0 +1,235 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Pojo } from 'node-opcua-client-crawler'; +import { aas, AASDocument, LiveValue } from 'common'; +import { + NodeIdLike, + DataValueOptions, + LocalizedTextOptions, + NodeId, + ClientSession, + AttributeIds, + QualifiedName +} from 'node-opcua'; + +export type BaseTypeDefinition = 'Operation' | 'FolderType' | 'FileType'; + +export type AASTypeDefinition = + 'AASEnvironmentType' | + 'AASAssetInformationType' | + 'AASAssetAdministrationShellType' | + 'AASAssetType' | + 'AASEventType' | + 'AASBlobType' | + 'AASCapabilityType' | + 'AASEntityType' | + 'AASSubmodelType' | + 'AASSubmodelElementCollectionType' | + 'AASOrderedSubmodelElementCollectionType' | + 'AASPropertyType' | + 'AASFileType' | + 'AASViewType' | + 'AASContainedElementRefType' | + 'AASQualifierList' | + 'AASRangeType' | + 'AASReferenceElementType' | + 'AASReferenceType' | + 'AASReferenceList' | + 'AASRelationshipElementType' | + 'AASMultiLanguagePropertyType' | + 'AASOperationType'; + +export interface AssetInformation { + kind: aas.AssetKind; + globalAssetId: aas.Reference; + category?: aas.Category; + billOfMaterial?: aas.Reference[]; + specificAssetId?: aas.Reference[]; +} + +export type TypeDefinition = BaseTypeDefinition | AASTypeDefinition; + +export interface OPCUANode extends Pojo { + nodeId: NodeId; + browseName: string; + typeDefinition: TypeDefinition; +} + +export interface OPCUAProperty extends OPCUANode { + dataType: NodeIdLike; + dataValue: DataValueOptions; +} + +export enum UAKeyElements { + AccessPermissionRule = 0, + AnnotatedRelationshipElement = 1, + Asset = 2, + AssetAdministrationShell = 3, + Blob = 4, + Capability = 5, + ConceptDescription = 6, + ConceptDictionary = 7, + DataElement = 8, + Entity = 9, + Event = 10, + File = 11, + FragmentReference = 12, + GlobalReference = 13, + MultiLanguageProperty = 14, + Operation = 15, + Property = 16, + Range = 17, + ReferenceElement = 18, + RelationshipElement = 19, + Submodel = 20, + SubmodelElement = 21, + SubmodelElementCollection = 22, + View = 23, +} + +export enum ValueType { + Boolean = 0, + SByte = 1, + Byte = 2, + Int16 = 3, + UInt16 = 4, + Int32 = 5, + UInt32 = 6, + Int64 = 7, + UInt64 = 8, + Float = 9, + Double = 10, + String = 11, + DateTime = 12, + ByteString = 13, + LocalizedText = 14, + UtcTime = 15 +} + +export enum PropertyValueType { + AnyType, + AllComplexTypes, + AnySimpleType, + AnyAtomicType, + AnyURI, + Base64Binary, + Boolean, + Date, + DateTime, + DateTimeStamp, + Decimal, + Integer, + Long, + Int, + Short, + Byte, + NonNegativeInteger, + PositiveInteger, + UnsignedLong, + UnsignedInt, + UnsignedShort, + UnsignedByte, + NonPositiveInteger, + NegativeInteger, + Double, + Duration, + DayTimeDuration, + YearMonthDuration, + Float, + GDay, + GMonth, + GMonthDay, + GYear, + GYearMonth, + HexBinary, + NOTATION, + QName, + String, + NormalizedString, + Token, + Language, + Name, + NCName, + ENTITY, + ID, + IDREF, + NMTOKEN, + Time, + ENTITIES, + IDREFS, + NMTOKENS +} + +export enum DataTypeIEC61360Type { + DATE, + STRING, + STRING_TRANSLATABLE, + INTEGER_MEASURE, + INTEGER_COUNT, + INTEGER_CURRENCY, + REAL_MEASURE, + REAL_COUNT, + REAL_CURRENCY, + BOOLEAN, + URL, + RATIONAL, + RATIONAL_MEASURE, + TIME, + TIMESTAMP +} + +export enum UAIdentifierType { IRDI = 0, IRI = 1, Custom = 2 } + +export enum UAKeyType { idShort = 0, FragmentId = 1, Custom = 2, IRDI = 3, IRI = 4 } + +export interface UAKey { + idType: UAKeyType; + type: UAKeyElements; + locale: boolean; + value: string; +} + +export enum UAEntityType { + CoManagedEntity, + SelfManagedEntity +} + +export interface OPCUAComponent extends OPCUANode { + displayName: LocalizedTextOptions; + hasComponent?: OPCUAComponent[]; + hasAddIn?: OPCUAComponent[]; + hasProperty: OPCUAProperty[]; + aaSReference?: OPCUAProperty[]; + nodeClass: string; +} + +export interface OPCUAReadRequest { + aas: AASDocument; + nodes: LiveValue[]; +} + +export interface AASKeyDataType { + type: UAKeyElements; + value: any; + idType: UAKeyType; +} + +export async function readDataTypeAsync(session: ClientSession, dataType: NodeIdLike): Promise { + const qualifiedName: QualifiedName = (await session.read( + { + nodeId: dataType, + attributeId: AttributeIds.BrowseName + })).value.value; + + if (typeof qualifiedName.name === 'string') { + return qualifiedName.name; + } + + throw new Error('Invalid operation.'); +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/server-message.ts b/projects/aas-server/src/app/packages/server-message.ts new file mode 100644 index 00000000..f8db2d4f --- /dev/null +++ b/projects/aas-server/src/app/packages/server-message.ts @@ -0,0 +1,281 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import http from 'http'; +import net from 'net'; +import FormData from 'form-data'; +import { parseUrl } from '../convert.js'; + +export class ServerMessage { + /** + * Gets an object of type `T` from a server. + * @param url The URL of the object. + * @template T The type of the object. + * @returns The requested object. + */ + public get(url: URL): Promise { + return new Promise((result, reject) => { + const options: http.RequestOptions = { + host: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: 'GET', + timeout: 3000 + }; + + const request = http.request(options, (response) => { + let data = ''; + response.on('data', (chunk: string) => { + data += chunk; + }); + + response.on('end', () => { + try { + ServerMessage.checkStatusCode(response); + result(JSON.parse(data)); + } catch (error) { + reject(error); + } + }); + + response.on('error', error => reject(error)); + }); + + request.on('timeout', () => request.destroy()) + .on('error', error => reject(error)) + .end(); + }); + } + + /** + * Gets the response of the request with the specified URL. + * @param url The URL of the request. + * @returns The request. + */ + public getResponse(url: URL): Promise { + return new Promise((result, reject) => { + const options: http.RequestOptions = { + host: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: 'GET', + timeout: 3000 + }; + + const request = http.request(options, response => result(response)); + request.on('timeout', () => request.destroy()) + .on('error', (error) => reject(error)) + .end(); + }); + } + + /** + * Updates the specified object. + * @param url The destination URL. + * @param obj The object to send. + */ + public put(url: URL, obj: object): Promise { + return new Promise((result, reject) => { + const data = JSON.stringify(obj); + const options: http.RequestOptions = { + hostname: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(data) + } + }; + + const request = http.request(options, (response) => { + let responseData = ''; + response.on('data', function (chunk: string) { + responseData += chunk; + }); + + response.on('end', function () { + try { + ServerMessage.checkStatusCode(response); + result(JSON.parse(responseData)); + } catch (error) { + reject(error); + } + }); + + response.on('error', function (error: Error) { + reject(error); + }); + }).on('error', error => reject(error)); + + request.write(data); + request.end(); + }); + } + + /** + * Inserts the specified object. + * @param url The destination URL. + * @param obj The object to send. + */ + public post(url: URL, obj: any): Promise { + return obj instanceof FormData ? this.postFormData(url, obj) : this.postObject(url, obj); + } + + /** + * Deletes an object. + * @param url The URL of the object to delete. + */ + public delete(url: URL): Promise { + return new Promise((result, reject) => { + const options: http.RequestOptions = { + hostname: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + } + }; + + http.request(options, (response) => { + let responseData = ''; + response.on('data', function (chunk: string) { + responseData += chunk; + }); + + response.on('end', function () { + try { + ServerMessage.checkStatusCode(response); + result(JSON.parse(responseData)); + } catch (error) { + reject(error); + } + }); + + response.on('error', function (error: Error) { + reject(error); + }); + }).on('error', error => reject(error)) + .end(); + }); + } + + /** + * Checks the connection to resource with the specified URL. + * @param url The current URL. + */ + public async checkUrlExist(url: string): Promise { + const temp = parseUrl(url); + const exist = await new Promise((resolve, _) => { + const socket = net.createConnection(Number(temp.port), temp.hostname); + socket.setTimeout(3000); + socket.on('connect', () => { + socket.end(); + resolve(true); + }); + + socket.on('timeout', () => { + socket.destroy(); + resolve(false); + }); + + socket.on('error', () => { + socket.destroy(); + resolve(false); + }); + }); + + if (!exist) { + throw new Error(`${url} does not exist.`); + } + } + + private postObject(url: URL, obj: object): Promise { + return new Promise((result, reject) => { + const data = JSON.stringify(obj); + const options: http.RequestOptions = { + hostname: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(data) + } + }; + + const request = http.request(options, (response) => { + let responseData = ''; + response.on('data', function (chunk: string) { + responseData += chunk; + }); + + response.on('end', function () { + try { + ServerMessage.checkStatusCode(response); + result(JSON.parse(responseData)); + } catch (error) { + reject(error); + } + }); + + response.on('error', function (error: Error) { + reject(error); + }); + }).on('error', error => reject(error)); + + request.write(data); + request.end(); + }); + } + + private postFormData(url: URL, formData: FormData): Promise { + return new Promise((result, reject) => { + const options: http.RequestOptions = { + hostname: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: 'POST', + headers: formData.getHeaders() + }; + + const request = http.request(options, (response) => { + let responseData = ''; + response.on('data', function (chunk: string) { + responseData += chunk; + }); + + response.on('end', function () { + try { + ServerMessage.checkStatusCode(response); + result(JSON.parse(responseData)); + } catch (error) { + reject(error); + } + }); + + response.on('error', function (error: Error) { + reject(error); + }); + }).on('error', error => reject(error)); + + formData.pipe(request); + }); + } + + private static checkStatusCode(response: http.IncomingMessage): void { + if (!response.statusCode) { + throw new Error('Unknown status code.'); + } + + if (response.statusCode < 200 || response.statusCode >= 300) { + throw new Error(`(${response.statusCode}) ${response.statusMessage}`); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/packages/xml-reader.ts b/projects/aas-server/src/app/packages/xml-reader.ts new file mode 100644 index 00000000..4d3451f8 --- /dev/null +++ b/projects/aas-server/src/app/packages/xml-reader.ts @@ -0,0 +1,713 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas, determineType } from 'common'; +import { useNamespaces, XPathSelect } from 'xpath'; +import { DOMParser } from '@xmldom/xmldom'; +import { Logger } from '../logging/logger.js'; +import { AASReader } from './aas-reader.js'; + +interface NamespaceMap { + _nsMap: { [key: string]: string }; +} + +export class XmlReader extends AASReader { + private readonly select: XPathSelect; + private readonly document: Document; + private iec61360 = 'IEC61360'; + + constructor( + private readonly logger: Logger, + xmlSource: string) { + super(); + + this.document = new DOMParser().parseFromString(xmlSource); + this.select = useNamespaces(this.getNamespaces()); + } + + public readEnvironment(): aas.Environment { + const conceptDescriptions = this.readConceptDescriptions(); + const assetAdministrationShells = this.readAssetAdministrationShells(); + const submodels = this.readSubmodels(); + return { assetAdministrationShells, submodels, conceptDescriptions } + } + + public read(data: any): aas.Referable { + throw new Error('Not implemented.'); + } + + private getNamespaces(): { [key: string]: string } { + let nsMap: { [key: string]: string }; + if ('_nsMap' in this.document.documentElement) { + nsMap = ((this.document.documentElement as any) as NamespaceMap)._nsMap; + } else { + nsMap = {}; + } + + const namespaces: { [key: string]: string } = {}; + for (const prefix in nsMap) { + const uri = nsMap[prefix]; + if (uri.startsWith('http://www.admin-shell.io/IEC61360/')) { + this.iec61360 = prefix; + namespaces[prefix] = uri; + } else if (uri.startsWith('http://www.admin-shell.io/aas/')) { + namespaces['aas'] = uri; + } + } + + return namespaces; + } + + private readAssetInformation(): aas.AssetInformation { + let assetKind: aas.AssetKind | undefined; + let globalAssetId: string | undefined; + const node = this.selectNode('/aas:aasenv/aas:assets/aas:asset', this.document); + if (node) { + assetKind = this.selectNode('./aas:kind', node)?.textContent as aas.AssetKind; + globalAssetId = this.readIdentifier(node); + } else { + assetKind = 'Instance'; + } + + return { assetKind, globalAssetId }; + } + + private readAssetAdministrationShells(): aas.AssetAdministrationShell[] { + const shells: aas.AssetAdministrationShell[] = []; + for (const node of this.selectNodes('/aas:aasenv/aas:assetAdministrationShells/aas:assetAdministrationShell', this.document)) { + const shell = this.readAssetAdministrationShell(node); + shells.push(shell); + } + + return shells; + } + + private readAssetAdministrationShell(node: Node): aas.AssetAdministrationShell { + const assetInformation = this.readAssetInformation(); + if (!assetInformation) { + throw new Error('AssetAdministrationShell.asset'); + } + + const shell: aas.AssetAdministrationShell = { + ...this.readIdentifiable(node), + ...this.readHasDataSpecification(node), + assetInformation + }; + + const submodels = this.readReferences('./aas:submodelRefs/aas:submodelRef', node); + if (submodels.length > 0) { + shell.submodels = submodels; + } + + const administration = this.readAdministrationInformation('./aas:administration', node); + if (administration) { + shell.administration = administration; + } + + return shell; + } + + private readAdministrationInformation(path: string, node: Node): aas.AdministrativeInformation | undefined { + return undefined; + } + + private readSubmodels(): aas.Submodel[] { + const submodels: aas.Submodel[] = []; + for (const node of this.selectNodes('/aas:aasenv/aas:submodels/aas:submodel', this.document)) { + const submodel = this.readSubmodel(node); + submodels.push(submodel); + } + + return submodels; + } + + private readSubmodel(node: Node): aas.Submodel { + const submodel: aas.Submodel = { + ...this.readIdentifiable(node), + ...this.readHaSemantic(node), + ...this.readQualifiable(node), + ...this.readHasKind(node), + ...this.readHasDataSpecification(node) + }; + + const submodelElements = this.readSubmodelElements( + node, + { + type: 'ModelReference', + keys: [{ + type: 'Submodel', + value: submodel.id, + }] + }); + if (submodelElements.length > 0) { + submodel.submodelElements = submodelElements; + } + + return submodel; + } + + private readSubmodelElements(node: Node, parent?: aas.Reference): aas.SubmodelElement[] { + const submodelElements: aas.SubmodelElement[] = []; + for (const child of this.selectNodes("./aas:submodelElements/aas:submodelElement/*[1]", node)) { + const submodelElement = this.readSubmodelElement(child, parent); + if (submodelElement) { + submodelElements.push(submodelElement); + } + } + + return submodelElements; + } + + private readCollectionValue(node: Node, parent?: aas.Reference): aas.SubmodelElement[] { + const submodelElements: aas.SubmodelElement[] = []; + for (const child of this.selectNodes("./aas:value/aas:submodelElement/*[1]", node)) { + const submodelElement = this.readSubmodelElement(child, parent); + if (submodelElement) { + submodelElements.push(submodelElement); + } + } + + return submodelElements; + } + + private readSubmodelElement(node: Node, parent?: aas.Reference): aas.SubmodelElement | undefined { + let submodelElement: aas.SubmodelElement | undefined; + const modelType = this.getModelTypeFromLocalName(node); + switch (modelType) { + case 'AnnotatedRelationshipElement': + submodelElement = this.readAnnotatedRelationshipElement(node, parent); + case 'BasicEventElement': + submodelElement = this.readBasicEventElement(node, parent); + break; + case 'Blob': + submodelElement = this.readBlob(node, parent); + break; + case 'File': + submodelElement = this.readFile(node, parent); + break; + case 'MultiLanguageProperty': + submodelElement = this.readMultiLanguageProperty(node, parent); + break; + case 'Property': + submodelElement = this.readProperty(node, parent); + break; + case 'Range': + submodelElement = this.readRange(node, parent); + break; + case 'ReferenceElement': + submodelElement = this.readReferenceElement(node, parent); + break; + case 'RelationshipElement': + submodelElement = this.readRelationshipElement(node, parent); + break; + case 'SubmodelElementCollection': + submodelElement = this.readSubmodelElementCollection(node, parent); + break; + default: + break; + } + + return submodelElement; + } + + private readAnnotatedRelationshipElement(node: Node, parent?: aas.Reference): aas.AnnotatedRelationshipElement { + throw new Error('Method not implemented.'); + } + + private readBasicEventElement(node: Node, parent?: aas.Reference): aas.BasicEventElement { + throw new Error('Method not implemented.'); + } + + private readBlob(node: Node, parent?: aas.Reference): aas.Blob { + const contentType = this.selectNode('./aas:mimeType', node)?.textContent; + if (!contentType) { + throw new Error('File.mimetype'); + } + + const blob: aas.Blob = { + ...this.readSubmodelElementType(node, parent), + contentType + }; + + const value = this.selectNode('./aas:value', node)?.textContent; + if (value) { + blob.value = value; + } + + return blob; + } + + private readSubmodelElementCollection(node: Node, parent?: aas.Reference): aas.SubmodelElementCollection { + const base = this.readSubmodelElementType(node, parent); + const collection: aas.SubmodelElementCollection = { + ...base, + value: this.readCollectionValue(node, parent ? this.createReference(parent, base) : undefined), + }; + + return collection; + } + + private readProperty(node: Node, parent?: aas.Reference): aas.Property { + const valueNode = this.selectNode('./aas:value', node); + let value = valueNode?.textContent; + + const valueTypeNode = this.selectNode('./aas:valueType', node); + let valueType: aas.DataTypeDefXsd | undefined; + if (valueTypeNode?.textContent) { + valueType = this.toDataTypeDefXsd(valueTypeNode.textContent); + } + + if (!valueType && value != null) { + valueType = determineType(value); + } + + if (!valueType) { + valueType = 'xs:string'; + value = '!!! Undefined value type !!!' + } + + const property: aas.Property = { ...this.readSubmodelElementType(node, parent), valueType }; + if (value) { + property.value = value; + } + + return property; + } + + private readRange(node: Node, parent?: aas.Reference): aas.Range { + throw new Error('Method not implemented.'); + } + + private readRelationshipElement(node: Node, parent?: aas.Reference): aas.RelationshipElement { + throw new Error('Method not implemented.'); + } + + private readFile(node: Node, parent?: aas.Reference): aas.File { + let contentType = this.selectNode('./aas:mimeType', node)?.textContent; + if (!contentType) { + contentType = ''; + } + + const file: aas.File = { + ...this.readSubmodelElementType(node, parent), + contentType + }; + + const value = this.selectNode('./aas:value', node)?.textContent; + if (value) { + file.value = value; + } + + return file; + } + + private readMultiLanguageProperty(node: Node, parent?: aas.Reference): aas.MultiLanguageProperty { + const langString = this.readLangString('./aas:value', node) ?? []; + return { ...this.readSubmodelElementType(node, parent), value: langString }; + } + + private readReferenceElement(node: Node, parent?: aas.Reference): aas.ReferenceElement { + const value = this.getReference(node); + return { ...this.readSubmodelElementType(node, parent), value }; + } + + private readSubmodelElementType(node: Node, parent?: aas.Reference): aas.SubmodelElement { + return { + ...this.readReferable(node, undefined, parent), + ...this.readHaSemantic(node), + ...this.readHasKind(node), + ...this.readHasDataSpecification(node), + ...this.readQualifiable(node) + }; + } + + private readIdentifiable(node: Node): aas.Identifiable { + const id = this.readIdentifier(node); + const identifiable: aas.Identifiable = { ...this.readReferable(node, id), id }; + const administration = this.readAdministrativeInformation(node); + if (administration) { + identifiable.administration = administration; + } + + return identifiable; + } + + private readReferable(node: Node, id?: string, parent?: aas.Reference): aas.Referable { + let idShort = this.selectNode('./aas:idShort', node)?.textContent; + if (!idShort) { + idShort = id ? this.createIdShort(id) : ''; + } + + const referable: aas.Referable = { + idShort, + modelType: this.getModelTypeFromLocalName(node) + }; + + if (parent) { + referable.parent = parent; + } + + const category = this.selectNode('./aas:category', node)?.textContent as aas.Category | undefined; + if (category) { + referable.category = category; + } + + return referable; + } + + private readHaSemantic(node: Node): aas.HasSemantic { + const semanticId = this.readReference('./aas:semanticId', node); + return semanticId ? { semanticId } : {}; + } + + private readHasKind(node: Node): aas.HasKind { + let kind = this.selectNode('aas:kind', node)?.textContent as aas.ModellingKind; + if (!kind) { + kind = 'Instance'; + } + + return { kind }; + } + + private readHasDataSpecification(node: Node): aas.HasDataSpecification { + const embeddedDataSpecifications: aas.EmbeddedDataSpecification[] = []; + for (const child of this.selectNodes('./aas:embeddedDataSpecification', node)) { + const dataSpecification = this.readReference('./aas:hasDataSpecification', child) ?? + this.readReference('./aas:dataSpecification', child); + + if (!dataSpecification) { + throw new Error('EmbeddedDataSpecification.dataSpecification'); + } + + const dataSpecificationContent = this.readDataSpecificationContent(child); + if (dataSpecificationContent) { + embeddedDataSpecifications.push({ dataSpecification, dataSpecificationContent }); + } + } + + return embeddedDataSpecifications.length > 0 ? { embeddedDataSpecifications } : {}; + } + + private readDataSpecificationContent(parent: Node): aas.DataSpecificationContent | undefined { + const node = this.selectNode('./aas:dataSpecificationContent/aas:dataSpecificationIEC61360', parent); + if (node) { + return this.readDataSpecificationIEC61360(node); + } + + return undefined; + } + + private readDataSpecificationIEC61360(node: Node): aas.DataSpecificationIEC61360 { + const preferredName = this.readLangString(`./${this.iec61360}:preferredName`, node); + if (!preferredName) { + throw new Error('DataSpecificationIEC61360Content.preferredName'); + } + + const dataSpecification: aas.DataSpecificationIEC61360 = { + modelType: this.getModelTypeFromLocalName(node), + preferredName + }; + + const shortName = this.readLangString(`./${this.iec61360}:shortName`, node); + if (shortName) { + dataSpecification.shortName = shortName; + } + + const unit = this.selectNode(`./${this.iec61360}:unit`, node)?.textContent; + if (unit) { + dataSpecification.unit = unit; + } + + const unitId = this.readReference(`./${this.iec61360}:unitId`, node); + if (unit) { + dataSpecification.unitId = unitId; + } + + const sourceOfDefinition = this.selectNode(`./${this.iec61360}:sourceOfDefinition`, node)?.textContent; + if (sourceOfDefinition) { + dataSpecification.sourceOfDefinition = sourceOfDefinition; + } + + const symbol = this.selectNode(`./${this.iec61360}:symbol`, node)?.textContent; + if (symbol) { + dataSpecification.symbol = symbol; + } + + const dataType = this.selectNode(`./${this.iec61360}:dataType`, node)?.textContent as aas.DataTypeIEC61360; + if (dataType) { + dataSpecification.dataType = dataType; + } + + const definition = this.readLangString(`./${this.iec61360}:definition`, node); + if (definition) { + dataSpecification.definition = definition; + } + + const valueFormat = this.selectNode(`./${this.iec61360}:valueFormat`, node)?.textContent; + if (valueFormat) { + dataSpecification.valueFormat = valueFormat; + } + + const valueList = this.readValueList(`./${this.iec61360}:valueList`, node); + if (valueList) { + dataSpecification.valueList = valueList; + } + + const value = this.selectNode(`./${this.iec61360}:value`, node)?.textContent; + if (value) { + dataSpecification.value = value; + } + + const levelType = this.selectNode(`./${this.iec61360}:levelType`, node)?.textContent as aas.LevelType; + if (levelType) { + dataSpecification.levelType = levelType; + } + + return dataSpecification; + } + + private readValueList(path: string, node: Node): aas.ValueList | undefined { + return undefined; + } + + private readQualifiable(node: Node): aas.Qualifiable { + const qualifiable: aas.Qualifiable = {}; + const qualifiers = this.readQualifiers('./aas.qualifier', node); + if (qualifiers) { + qualifiable.qualifiers = qualifiers; + } + + return qualifiable; + } + + private readQualifiers(path: string, parent: Node): aas.Qualifier[] | undefined { + let qualifiers: aas.Qualifier[] | undefined; + const node = this.selectNode(path, parent); + if (node) { + qualifiers = []; // ToDo. + } + + return qualifiers; + } + + private readReference(path: string, parent: Node): aas.Reference | undefined { + let reference: aas.Reference | undefined; + const node = this.selectNode(path, parent); + if (node) { + reference = { type: 'ModelReference', keys: [] }; + for (const keyNode of this.selectNodes('./aas:keys/aas:key', node)) { + reference.keys.push(this.getKey(keyNode)); + } + } + + return reference; + } + + private readReferences(path: string, parent: Node): aas.Reference[] { + const references: aas.Reference[] = []; + for (const node of this.selectNodes(path, parent)) { + const reference: aas.Reference = { type: 'ModelReference', keys: [] }; + for (const keyNode of this.selectNodes('./aas:keys/aas:key', node)) { + reference.keys.push(this.getKey(keyNode)); + } + + references.push(reference); + } + + return references; + } + + private readAdministrativeInformation(node: Node): aas.AdministrativeInformation | undefined { + let value: aas.AdministrativeInformation | undefined; + const version = this.selectNode('./aas.administration/aas.version', node)?.textContent; + const revision = this.selectNode('./aas.administration/aas.revision', node)?.textContent; + if (version || revision) { + value = {}; + if (version) { + value.version = version; + } + + if (revision) { + value.revision = revision; + } + } + + return value; + } + + private readLangString(path: string, parent: Node): aas.LangString[] | undefined { + let langString: aas.LangString[] | undefined; + const content = this.selectNode(path, parent); + if (content) { + langString = []; + for (const node of this.selectNodes('./aas:langString', content)) { + const language = (node as Element).getAttribute('lang')!.toLowerCase(); + const text = node.textContent ?? ''; + langString.push({ language, text }) + } + + if (langString.length === 0 && content.textContent) { + langString.push({ language: 'en', text: content.textContent }) + } + } + + return langString; + } + + private readConceptDescriptions(): aas.ConceptDescription[] { + const conceptDescriptions: aas.ConceptDescription[] = []; + for (const node of this.selectNodes( + '/aas:aasenv/aas:conceptDescriptions/aas:conceptDescription', + this.document)) { + conceptDescriptions.push(this.readConceptDescription(node)); + } + + return conceptDescriptions; + } + + private readConceptDescription(node: Node): aas.ConceptDescription { + const conceptDescription: aas.ConceptDescription = { + ...this.readIdentifiable(node), + ...this.readHasDataSpecification(node) + }; + + const isCaseOf: aas.Reference[] = []; + for (const refNode of this.selectNodes('./isCaseOf', node)) { + isCaseOf.push(this.readReference('.', node)!) + } + + if (isCaseOf.length > 0) { + conceptDescription.isCaseOf = isCaseOf; + } + + return conceptDescription; + } + + private getModelTypeFromLocalName(node: Node): aas.ModelType { + const localName: string = (node as Element).localName; + return localName.charAt(0).toUpperCase() + localName.substring(1) as aas.ModelType; + } + + private selectNode(query: string, node: Node): Node | undefined { + return this.select(query, node, true) as Node | undefined; + } + + private getNode(query: string, node: Node): Node { + const result = this.select(query, node, true); + if (!result) { + throw new Error(`Query '${query}' returns no result.`); + } + + return result as Node; + } + + private selectNodes(query: string, node: Node): Node[] { + return this.select(query, node) as Node[]; + } + + private getReference(node: Node): aas.Reference { + return { + type: 'ModelReference', + keys: this.selectNodes('./aas:value/aas:keys/aas:key', node).map(item => this.getKey(item)) + }; + } + + private getKey(node: Node): aas.Key { + const element = node as Element; + return { + type: element.getAttribute('type') as aas.KeyTypes, + value: element.textContent ?? '' + }; + } + + private readIdentifier(node: Node): string { + const id = this.selectNode('./aas:identification', node)?.textContent; + if (id == null) { + throw new Error('./aas:identification'); + } + + return id; + } + + private toDataTypeDefXsd(source: string): aas.DataTypeDefXsd { + switch (source) { + case 'anyURI': + return 'xs:anyURI'; + case 'base64Binary': + return 'xs:base64Binary'; + case 'boolean': + return 'xs:boolean'; + case 'byte': + return 'xs:byte'; + case 'Date': + case 'date': + return 'xs:date'; + case 'dateTime': + return 'xs:dateTime'; + case 'dateTimeStamp': + return 'xs:dateTime'; + case 'dayTimeDuration': + return 'xs:duration'; + case 'Decimal': + case 'decimal': + return 'xs:decimal'; + case 'double': + return 'xs:double'; + case 'duration': + return 'xs:duration'; + case 'float': + return 'xs:float'; + case 'gDay': + return 'xs:gDay'; + case 'gMonth': + return 'xs:gMonth'; + case 'gMonthDay': + return 'xs:gMonthDay'; + case 'gYear': + return 'xs:gYear'; + case 'gYearMonth': + return 'xs:gYearMonth'; + case 'hexBinary': + return 'xs:hexBinary'; + case 'int': + return 'xs:int'; + case 'integer': + return 'xs:integer'; + case 'long': + return 'xs:long'; + case 'negativeInteger': + return 'xs:negativeInteger'; + case 'nonNegativeInteger': + return 'xs:nonNegativeInteger'; + case 'nonPositiveInteger': + return 'xs:nonPositiveInteger'; + case 'positiveInteger': + return 'xs:positiveInteger'; + case 'short': + return 'xs:short'; + case 'langString': + case 'String': + case 'string': + return 'xs:string'; + case 'time': + return 'xs:time'; + case 'unsignedByte': + return 'xs:unsignedByte'; + case 'unsignedInt': + return 'xs:unsignedInt'; + case 'unsignedLong': + return 'xs:unsignedLong'; + case 'unsignedShort': + return 'xs:unsignedShort'; + case 'yearMonthDuration': + return 'xs:duration'; + default: + throw new Error(`${source} is an unknown value type.`); + } + } +} diff --git a/projects/aas-server/src/app/scan-container.ts b/projects/aas-server/src/app/scan-container.ts new file mode 100644 index 00000000..18d12e47 --- /dev/null +++ b/projects/aas-server/src/app/scan-container.ts @@ -0,0 +1,181 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { parentPort } from 'worker_threads'; +import { Logger } from './logging/logger.js'; +import { AASDocument, aas, isDeepEqual } from 'common'; +import { ScanContainerData } from './aas-provider/worker-data.js'; +import { AasxDirectory } from './packages/aasx-directory/aasx-directory.js'; +import { AASResource } from './packages/aas-resource.js'; +import { AasxServer } from './packages/aasx-server/aasx-server.js'; +import { OpcuaServer } from './packages/opcua/opcua-server.js'; +import { ScanContainerResult, ScanResultType } from './aas-provider/scan-result.js'; +import { toUint8Array } from './convert.js'; +import { UpdateStatistic } from './update-statistic.js'; +import { AASResourceScanFactory } from './aas-provider/aas-resource-scan-factory.js'; + +@singleton() +export class ScanContainer { + private data!: ScanContainerData; + private reference!: Map; + private source!: AASResource; + + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(UpdateStatistic) private readonly statistic: UpdateStatistic, + @inject(AASResourceScanFactory) private readonly resourceScanFactory: AASResourceScanFactory + ) { + } + + public async scanAsync(data: ScanContainerData): Promise { + this.data = data; + this.reference = new Map(data.container.documents!.map(item => [item.id, item])); + + let documents: AASDocument[]; + const scan = this.resourceScanFactory.create(data.container.url); + try { + scan.on('scanned', this.onDocumentScanned); + scan.on('error', this.onError); + documents = await scan.scanAsync(); + this.computeDeleted(documents); + } finally { + scan.off('scanned', this.onDocumentScanned); + scan.off('error', this.onError); + } + } + + private computeDeleted(documents: AASDocument[]) { + const current = new Map(documents.map(item => [item.id, item])); + for (const referenceDocument of this.reference.values()) { + if (!current.has(referenceDocument.id)) { + this.postDeleted(referenceDocument); + } + } + } + + private onDocumentScanned = (document: AASDocument): void => { + const referenceDocument = this.reference.get(document.id); + if (referenceDocument) { + if (this.documentChanged(document, referenceDocument)) { + this.postChanged(document); + } + } else { + this.postAdded(document); + } + } + + private onError = (error: Error, source: AASResource, arg: string): void => { + this.logger.error(error); + if (source instanceof AasxDirectory) { + const file = arg as string; + for (const referenceDocument of this.reference.values()) { + if (referenceDocument.container === source.url.href && referenceDocument.endpoint.address === file) { + this.postOffline(referenceDocument); + break; + } + } + } else if (source instanceof AasxServer) { + const idShort = arg; + for (const referenceDocument of this.reference.values()) { + if (referenceDocument.container === source.url.href && referenceDocument.idShort === idShort) { + this.postOffline(referenceDocument); + break; + } + } + } else if (source instanceof OpcuaServer) { + const nodeId = arg as string; + for (const referenceDocument of this.reference.values()) { + if (referenceDocument.container === source.url.href && referenceDocument.endpoint.address === nodeId) { + this.postOffline(referenceDocument); + break; + } + } + } + } + + private postChanged(document: AASDocument): void { + const value: ScanContainerResult = { + taskId: this.data.taskId, + type: ScanResultType.Changed, + container: this.data.container, + document: document, + statistic: this.statistic.update(this.data.statistic, ScanResultType.Changed) + }; + + const array = toUint8Array(value); + parentPort?.postMessage(array, [array.buffer]); + } + + private postDeleted(document: AASDocument): void { + const value: ScanContainerResult = { + taskId: this.data.taskId, + type: ScanResultType.Removed, + container: this.data.container, + document: document, + statistic: this.statistic.update(this.data.statistic, ScanResultType.Removed) + }; + + const array = toUint8Array(value); + parentPort?.postMessage(array, [array.buffer]); + } + + private postAdded(document: AASDocument): void { + const value: ScanContainerResult = { + taskId: this.data.taskId, + type: ScanResultType.Added, + container: this.data.container, + document: document, + statistic: this.statistic.update(this.data.statistic, ScanResultType.Added) + }; + + const array = toUint8Array(value); + parentPort?.postMessage(array, [array.buffer]); + } + + private postOffline(document: AASDocument): void { + const value: ScanContainerResult = { + taskId: this.data.taskId, + type: ScanResultType.Offline, + container: this.data.container, + document: { ...document, content: undefined }, + statistic: this.statistic.update(this.data.statistic, ScanResultType.Offline) + }; + + const array = toUint8Array(value); + parentPort?.postMessage(array, [array.buffer]); + } + + private documentChanged(document: AASDocument, reference: AASDocument): boolean { + let changed: boolean; + if (document.content === reference.content) { + changed = false; + } else if (document.content && reference.content) { + changed = !this.equalContent(document.content, reference.content); + } else { + changed = true; + } + + return changed; + } + + private equalContent( + a: aas.Environment | null, + b: aas.Environment | null): boolean { + let equals: boolean; + if (a === b) { + equals = true; + } else if (a !== null && b !== null) { + equals = isDeepEqual(a, b); + } else { + equals = false; + } + + return equals; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/scan-endpoint.ts b/projects/aas-server/src/app/scan-endpoint.ts new file mode 100644 index 00000000..3f94cf71 --- /dev/null +++ b/projects/aas-server/src/app/scan-endpoint.ts @@ -0,0 +1,74 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { parentPort } from 'worker_threads'; +import { Logger } from './logging/logger.js'; +import { ScanEndpointData } from './aas-provider/worker-data.js'; +import { ScanEndpointResult, ScanResultType } from './aas-provider/scan-result.js'; +import { toUint8Array } from './convert.js'; +import { AASEndpointScan } from './aas-provider/aas-endpoint-scan.js'; +import { AASContainer } from 'common'; +import { noop } from 'lodash-es'; +import { UpdateStatistic } from './update-statistic.js'; +import { AASEndpointScanFactory } from './aas-endpoint-scan-factory.js'; + +@singleton() +export class ScanEndpoint { + private data!: ScanEndpointData; + + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(AASEndpointScanFactory) private readonly endpointScanFactory: AASEndpointScanFactory, + @inject(UpdateStatistic) private readonly statistic: UpdateStatistic + ) { } + + public async scanAsync(data: ScanEndpointData): Promise { + this.data = data; + let scan: AASEndpointScan | undefined; + try { + scan = this.endpointScanFactory.create(data); + scan.on('added', this.onContainerAdded); + scan.on('removed', this.onContainerRemoved); + scan.on('error', this.onError); + await scan.scanAsync(); + } finally { + scan?.removeAllListeners(); + } + } + + private onContainerAdded = (endpoint: string, container: AASContainer): void => { + const value: ScanEndpointResult = { + taskId: this.data.taskId, + type: ScanResultType.ContainerAdded, + endpoint: endpoint, + container: container, + statistic: this.statistic.update(this.data.statistic, ScanResultType.ContainerAdded) + }; + + const array = toUint8Array(value); + parentPort?.postMessage(array, [array.buffer]); + } + + private onContainerRemoved = (endpoint: string, container: AASContainer) => { + const value: ScanEndpointResult = { + taskId: this.data.taskId, + type: ScanResultType.ContainerRemoved, + container: container, + endpoint: endpoint, + statistic: this.statistic.update(this.data.statistic, ScanResultType.ContainerRemoved) + }; + + const array = toUint8Array(value); + parentPort?.postMessage(array, [array.buffer]); + } + + private onError = (): void => { + noop(); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/send-error.ts b/projects/aas-server/src/app/send-error.ts new file mode 100644 index 00000000..a38048d3 --- /dev/null +++ b/projects/aas-server/src/app/send-error.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Response, Request } from "express"; +import { ErrorData, ApplicationError } from "common"; +import { ERRORS } from "./errors.js"; +import { Logger } from "./logging/logger.js"; + +export function sendError( + logger: Logger, + res: Response, + req: Request, + error: any, + errorId?: string, + ...args: any[] +) { + let errorData: ErrorData; + const method = `${req.method}: ${req.path}`; + if (error instanceof ApplicationError) { + errorData = createError(method, "ApplicationError", error.name, error.message, error.args); + } else if (error instanceof Error) { + if (errorId) { + errorData = createError(method, "Error", errorId, error.message, args ?? []); + } else { + errorData = createError(method, "Error", ERRORS.Uncaught, error.message, [error.message]); + } + } else { + const message = typeof error === "string" ? error : typeof error; + if (errorId) { + errorData = createError(method, typeof error, errorId, message, args ?? []); + } else { + errorData = createError(method, typeof error, ERRORS.Uncaught, message, [message]); + } + } + + res.status(500).json(errorData); + logger.error(`${method} failed: ${errorData.message}`); + + function createError(method: string, type: string, name: string, message: string, args: any[]): ErrorData { + return { + method: method, + type: type, + name: name, + message: message, + args: args ?? [] + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/template/locale-template-storage.ts b/projects/aas-server/src/app/template/locale-template-storage.ts new file mode 100644 index 00000000..e143d057 --- /dev/null +++ b/projects/aas-server/src/app/template/locale-template-storage.ts @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import fs from 'fs'; +import path from 'path'; +import { TemplateDescriptor, aas } from 'common'; +import { Logger } from '../logging/logger.js'; +import { readdir, readFile } from 'fs/promises'; +import { JsonReader } from '../packages/json-reader.js'; +import { AASReader } from '../packages/aas-reader.js'; +import { JsonReaderV2 } from '../packages/json-reader-v2.js'; +import * as aasV2 from '../types/aas-v2.js'; +import { TemplateStorage } from './template-storage.js'; +import { Variable } from '../variable.js'; + +@singleton() +export class LocalTemplateStorage extends TemplateStorage { + private readonly dir: string; + + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(Variable) variable: Variable + ) { + super(); + + this.dir = path.resolve(variable.ASSETS, 'templates'); + } + + public override async readAsync(): Promise { + const descriptors: TemplateDescriptor[] = []; + if (fs.existsSync(this.dir)) { + await this.readDirAsync(this.dir, descriptors) + } + + return descriptors; + } + + private async readDirAsync(dir: string, descriptors: TemplateDescriptor[]): Promise { + for (const entry of await readdir(dir, { withFileTypes: true })) { + if (entry.isFile()) { + const file = path.join(dir, entry.name); + const format = path.extname(file).toLowerCase(); + switch (format) { + case '.json': + descriptors.push({ + name: path.basename(file, path.extname(format)), + endpoint: { type: 'file', address: file }, + format: '.json', + template: await this.readTemplateAsync(file) + }); + break; + + case '.xml': + throw new Error(`Template format '${format}' is not implemented`); + } + } + else if (entry.isDirectory()) { + await this.readDirAsync(path.join(dir, entry.name), descriptors); + } + } + } + + private async readTemplateAsync(file: string): Promise { + const referable = JSON.parse((await readFile(file)).toString()); + const reader = this.createReader(referable); + return reader.read(referable); + } + + private createReader(referable: object): AASReader { + if (typeof (referable as aas.Referable).modelType === 'string') { + return new JsonReader(this.logger); + } + + if (typeof (referable as aasV2.Referable).modelType?.name === 'string') { + return new JsonReaderV2(this.logger); + } + + throw new Error('Not implemented.'); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/template/template-storage-factory.ts b/projects/aas-server/src/app/template/template-storage-factory.ts new file mode 100644 index 00000000..e9cd1164 --- /dev/null +++ b/projects/aas-server/src/app/template/template-storage-factory.ts @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { DependencyContainer } from 'tsyringe'; +import { TemplateStorage } from './template-storage.js'; +import { Variable } from '../variable.js'; +import { LocalTemplateStorage } from './locale-template-storage.js'; + +export class TemplateStorageFactory { + constructor(private readonly container: DependencyContainer) { } + + public create(): TemplateStorage { + const url = this.container.resolve(Variable).TEMPLATE_STORAGE; + if (url) { + throw new Error('Not implemented.'); + } + + return this.container.resolve(LocalTemplateStorage); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/template/template-storage.ts b/projects/aas-server/src/app/template/template-storage.ts new file mode 100644 index 00000000..59d74c2e --- /dev/null +++ b/projects/aas-server/src/app/template/template-storage.ts @@ -0,0 +1,13 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { TemplateDescriptor } from 'common'; + +export abstract class TemplateStorage { + public abstract readAsync(): Promise; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/types/aas-v2.ts b/projects/aas-server/src/app/types/aas-v2.ts new file mode 100644 index 00000000..7afb18ee --- /dev/null +++ b/projects/aas-server/src/app/types/aas-v2.ts @@ -0,0 +1,460 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +/** Defines the supported AAS element types. */ +export type ModelTypes = + 'Asset' | + 'AssetAdministrationShell' | + 'ConceptDescription' | + 'Submodel' | + 'AccessPermissionRule' | + 'AnnotatedRelationshipElement' | + 'BasicEvent' | + 'Blob' | + 'Capability' | + 'ConceptDictionary' | + 'DataElement' | + 'File' | + 'Entity' | + 'Event' | + 'MultiLanguageProperty' | + 'Operation' | + 'Property' | + 'Range' | + 'ReferenceElement' | + 'RelationshipElement' | + 'SubmodelElement' | + 'SubmodelElementCollection' | + 'View' | + 'GlobalReference' | + 'FragmentReference' | + 'Constraint' | + 'Formula' | + 'Qualifier'; + +/** Identifiable elements within an asset administration shell that are not identifiable (from AAS Metamodel). */ +export type IdentifiableElements = 'Asset' | 'AssetAdministrationShell' | 'ConceptDescription' | 'Submodel'; + +/** Referable elements within an asset administration shell (from AAS Metamodel). */ +export type ReferableElements = IdentifiableElements | + 'AccessPermissionRule' | + 'AnnotatedRelationshipElement' | + 'BasicEvent' | + 'Blob' | + 'Capability' | + 'DataElement' | + 'File' | + 'Entity' | + 'Event' | + 'MultiLanguageProperty' | + 'Operation' | + 'Property' | + 'Range' | + 'View' | + 'ReferenceElement' | + 'RelationshipElement' | + 'SubmodelElement' | + 'SubmodelElementCollection'; + +/** Different key value types within a key (from AAS Metamodel). */ +export type KeyElements = ReferableElements | 'GlobalReference' | 'FragmentReference'; + +/** Defines the different key value types within a key (from AAS Metamodel). */ +export type KeyType = 'IRI' | 'IRDI' | 'Custom' | 'IdShort' | 'FragmentId'; + +/** */ +export type DataTypeDefXsd = + 'anyURI' | + 'base64Binary' | + 'boolean' | + 'byte' | + 'date' | + 'dateTime' | + 'dateTimeStamp' | + 'dayTimeDuration' | + 'decimal' | + 'double' | + 'duration' | + 'float' | + 'gDay' | + 'gMonth' | + 'gMonthDay' | + 'gYear' | + 'gYearMonth' | + 'hexBinary' | + 'int' | + 'integer' | + 'long' | + 'negativeInteger' | + 'nonNegativeInteger' | + 'nonPositiveInteger' | + 'positiveInteger' | + 'short' | + 'string' | + 'time' | + 'unsignedByte' | + 'unsignedInt' | + 'unsignedLong' | + 'unsignedShort' | + 'yearMonthDuration'; + +/** Enumeration of simple data types for a IEC61360 concept description + * using the data specification template DataSpecificationIEC61360 */ +export type DataTypeIEC61360 = + 'DATE' | + 'STRING' | + 'STRING_TRANSLATABLE' | + 'INTEGER_MEASURE' | + 'INTEGER_COUNT' | + 'INTEGER_CURRENCY' | + 'REAL_MEASURE' | + 'REAL_COUNT' | + 'REAL_CURRENCY' | + 'BOOLEAN' | + 'URL' | + 'RATIONAL' | + 'RATIONAL_MEASURE' | + 'TIME' | + 'TIMESTAMP'; + +/** Reference to an element by its id (from AAS Metamodel). */ +export interface Key { + type: KeyElements; + idType: KeyType; + value: string; + local: boolean; + index: number; +} + +/** Denotes, whether reference is a global reference or a model reference. */ +export type ReferenceTypes = 'GlobalReference' | 'ModelReference'; + +/** Reference to either a model element of the same or another AAS or to an external entity. */ +export interface Reference { + keys: Key[]; +} + +/** Represents a localizable text. */ +export interface LangString { + language: string; + text: string; +} + +export interface ModelType { + name: ModelTypes; +} + +/** Element that can have a semantic definition. */ +export interface HasSemantic { + semanticId?: Reference; +} + +export type ModellingKind = 'Template' | 'Instance'; + +/** An element with a kind is an element that can either represent a template or an instance. */ +export interface HasKind { + kind?: ModellingKind; +} + +/** Element that can be extended by using data specification templates. */ +export interface HasDataSpecification { + embeddedDataSpecifications?: EmbeddedDataSpecification[]; +} + +export interface ValueObject { + valueType?: DataTypeDefXsd; + value?: string; + valueId?: Reference; +} + +/** A constraint is used to further qualify or restrict an element. */ +export interface Constraint { + modelType: ModelType; +} + +/** A qualifier is a type-value-pair that makes additional statements w.r.t. the value of the element. */ +export interface Qualifier extends Constraint, HasSemantic, ValueObject { + type: string; +} + +/** A formula is used to describe constraints by a logical expression. */ +export interface Formula extends Constraint { + dependsOn?: Reference[]; +} + +/** The value of a qualifiable element may be further qualified by one or more qualifiers or complex formulas. */ +export interface Qualifiable { + qualifiers?: Constraint[]; +} + +/** Metainformation of a property (from AAS Metamodel). */ +export type Category = 'CONSTANT' | 'PARAMETER' | 'VARIABLE'; + +/** An element that is referable by its idShort. This id is not globally unique. + * This id is unique within the name space of the element. */ +export interface Referable { + modelType: ModelType; + idShort: string; + category?: Category; + descriptions?: LangString[]; + parent?: Reference; +} + +/** Used to uniquely identify an element by using an identifier (from AAS Metamodel). */ +export interface Identifier { + idType: KeyType; + id: string; +} + +/** Administrative metainformation for an element like version information (from AAS Metamodel). */ +export interface AdministrativeInformation { + /** Version of the element. */ + version?: string; + /** Revision of the element. */ + revision?: string; +} + +/** An element that has a globally unique identifier. */ +export interface Identifiable extends Referable { + administration?: AdministrativeInformation; + identification: Identifier; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface DataSpecificationContent { +} + +/** Content of data specification template for concept descriptions for properties, + * values and value lists conformant to IEC 61360. */ +export interface DataSpecificationIEC61360Content extends DataSpecificationContent { + preferredName: LangString[]; + shortName?: LangString[]; + unit?: string; + unitId?: Reference; + sourceOfDefinition?: string; + symbol?: string; + dataType?: DataTypeIEC61360; + definition?: LangString[]; + valueFormat?: string; + valueList?: ValueList; + value?: string; + levelType?: LevelType; +} + +export type LevelType = 'Max' | 'Min' | 'Nom' | 'Typ'; + +/** Content of data specification template for concept descriptions for physical units + * conformant to IEC 61360. */ +export interface DataSpecificationPhysicalUnitContent extends DataSpecificationContent { + unitName: string; + unitSymbol: string; + definition: LangString[]; + siNotation?: string; + siName?: string; + dinNotation?: string; + eceName?: string; + eceCode?: string; + nistName?: string; + sourceOfDefinition?: string; + conversionFactor?: string; + registrationAuthorityId?: string; + supplier?: string +} + +export interface ValueList { + valueReferencePairTypes: ValueReferencePairType[] +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface ValueReferencePairType extends ValueObject { +} + +export interface EmbeddedDataSpecification { + dataSpecification: Reference; + dataSpecificationContent: DataSpecificationContent; +} + +/** An Asset describes meta data of an asset that is represented by an AAS and + is identical for all AAS representing this asset. */ +export interface Asset extends Identifiable, HasDataSpecification { + kind: AssetKind; + assetIdentificationModel?: Reference; + billOfMaterial?: Reference; +} + +export type AssetKind = 'Type' | 'Instance'; + +/** A submodel element is an element suitable for the description and differentiation of assets. */ +export interface SubmodelElement extends Referable, HasDataSpecification, HasSemantic, Qualifiable, HasKind { +} + +export interface SubmodelElementCollection extends SubmodelElement { + ordered?: boolean; + allowDuplicates?: boolean; + value?: SubmodelElement[]; +} + +/** An event element. */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Event extends SubmodelElement { +} + +/** A basic event element. */ +export interface BasicEvent extends Event { + observed: Reference; +} + +/** A data element is a submodel element that has a value. The type of value differs for +different subtypes of data elements. */ +export interface DataElement extends SubmodelElement { + /** OPC UA */ + nodeId?: string; +} + +/** A property is a data element that has a single value. */ +export interface Property extends DataElement { + valueType: ValueTypeDef; + value?: string; + valueId?: Reference; +} + +/** A range data element is a data element that defines a range with min and max. */ +export interface Range extends DataElement { + valueType: ValueTypeDef; + min?: string; + max?: string; +} + +export interface ValueTypeDef { + dataObjectType: DataObjectType; +} + +export interface DataObjectType { + name: DataTypeDefXsd; +} + +/** A property is a data element that has a multi-language value. */ +export interface MultiLanguageProperty extends DataElement { + value: LangStringSet; + valueId?: Reference; +} + +export type LangStringSet = { + langString: LangString[]; +} + +/** A File is a data element that represents an address to a file. + * The value is an URI that can represent an absolute or relative path. */ +export interface File extends DataElement { + mimeType: string; + value?: string; +} + +/** A BLOB is a data element that represents a file that is contained with its source code in the + * value attribute. */ +export interface Blob extends DataElement { + mimeType: string; + value?: string; +} + +/** A reference element is a data element that defines a logical reference to another element + * within the same or another AAS or a reference to an external object or entity. */ +export interface ReferenceElement extends DataElement { + value: Reference; +} + +/** A relationship element is used to define a relationship between two referable elements. */ +export interface RelationshipElement extends SubmodelElement { + first: Reference; + second: Reference; +} + +/** An annotated relationship element is a relationship element that can be annotated + * with additional data elements.*/ +export interface AnnotatedRelationshipElement extends RelationshipElement { + annotation: DataElement[]; +} + +/** Enumeration for denoting whether an entity is a self-managed entity or a co-managed entity. */ +export type EntityType = + /** For co-managed entities there is no separate AAS. Co-managed entities need to be part of a self-managed entity. */ + 'CoManagedEntity' | + /** Self-Managed Entities have their own AAS but can be part of the bill of material of a composite self-managed entity. */ + 'SelfManagedEntity'; + +/** An IdentifierKeyValuePair describes a generic identifier as key-value pair. */ +export interface IdentifierKeyValuePair { + key: string; + value: string; + externalSubjectId: Reference; +} + +/** An entity is a submodel element that is used to model entities. */ +export interface Entity extends SubmodelElement { + entityType: EntityType; + asset?: Reference; + statements?: SubmodelElement[]; +} + +/** A capability is the implementation-independent description of the potential of an + * asset to achieve a certain effect in the physical or virtual world. */ +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Capability extends SubmodelElement { +} + +/** An operation variable is a submodel element that is used as input or output variable of an operation. */ +export interface OperationVariable { + value: SubmodelElement; +} + +/** An operation is a submodel element with input and output variables. */ +export interface Operation extends SubmodelElement { + inputVariable?: OperationVariable[]; + outputVariable?: OperationVariable[]; + inoutputVariable?: OperationVariable[]; + /** The node ID of the operation node. */ + methodId?: string; + /** The node ID of the operation submodel element. */ + objectId?: string; +} + +/** A submodel defines a specific aspect of the asset represented by the AAS. */ +export interface Submodel extends Identifiable, HasDataSpecification, HasSemantic, Qualifiable, HasKind { + submodelElements?: SubmodelElement[]; +} + +export interface View extends Referable, HasDataSpecification, HasSemantic { + containedElements?: Reference[]; +} + +/** The semantics of a property or other elements that may have a semantic description is defined by + * a concept description. */ +export interface ConceptDescription extends Identifiable, HasDataSpecification { + isCaseOf?: Reference[]; +} + +export interface ConceptDictionary extends Referable, HasDataSpecification { + conceptDescriptions?: Reference[]; +} + +/** The Asset Administration Shell. */ +export interface AssetAdministrationShell extends Identifiable, HasDataSpecification { + asset: Reference; + derivedFrom?: Reference; + submodels?: Reference[]; + views?: View[]; + conceptDictionaries?: ConceptDictionary[]; +} + +/** Asset Administration Shell environment */ +export interface AssetAdministrationShellEnvironment { + assetAdministrationShells: AssetAdministrationShell[], + assets: Asset[]; + submodels: Submodel[]; + conceptDescriptions: ConceptDescription[]; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/types/owncloud-sdk.d.ts b/projects/aas-server/src/app/types/owncloud-sdk.d.ts new file mode 100644 index 00000000..e798937c --- /dev/null +++ b/projects/aas-server/src/app/types/owncloud-sdk.d.ts @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +declare module 'owncloud-sdk' { + + export interface OwnCloudAuthentication { + basic?: { username: string; password: string; } + } + + export interface OwnCloudOptions { + baseUrl: string; + auth?: OwnCloudAuthentication; + } + + export default class ownCloud { + constructor(options?: OwnCloudOptions); + + public login(): Promise; + } +} diff --git a/projects/aas-server/src/app/types/registry.ts b/projects/aas-server/src/app/types/registry.ts new file mode 100644 index 00000000..730064e9 --- /dev/null +++ b/projects/aas-server/src/app/types/registry.ts @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Endpoint } from 'common'; +import * as aasv2 from './aas-v2.js'; + +export interface AASRegistryModelType { + name: 'AssetAdministrationShellDescriptor' | 'Asset' +} + +/** The self-describing information of a network resource. */ +export interface AASRegistryDescriptor { + endpoints: Endpoint[]; +} + +/** Descriptor of a Submodel. */ +export interface SubmodelDescriptor extends AASRegistryDescriptor { + identification: aasv2.Identifier; + idShort: string; +} + +/** Descriptor of an Asset. */ +export interface AssetDescriptor extends AASRegistryDescriptor { + modelType: AASRegistryModelType; + identification: aasv2.Identifier; + idShort: string; +} + +/** Descriptor of an Asset Administration Shell */ +export interface AssetAdministrationShellDescriptor extends AASRegistryDescriptor { + modelType: AASRegistryModelType; + identification: aasv2.Identifier; + idShort: string; + asset: AssetDescriptor; + submodels: SubmodelDescriptor[]; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/types/uuid.d.ts b/projects/aas-server/src/app/types/uuid.d.ts new file mode 100644 index 00000000..0a8f6df0 --- /dev/null +++ b/projects/aas-server/src/app/types/uuid.d.ts @@ -0,0 +1,11 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +declare module 'uuid' { + export function v4(): string; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/update-statistic.ts b/projects/aas-server/src/app/update-statistic.ts new file mode 100644 index 00000000..50437cab --- /dev/null +++ b/projects/aas-server/src/app/update-statistic.ts @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { singleton } from 'tsyringe'; +import { ScanResultType, ScanStatistic } from './aas-provider/scan-result.js'; + +@singleton() +export class UpdateStatistic { + public update(statistic: ScanStatistic, type: ScanResultType): ScanStatistic { + switch (type) { + case ScanResultType.Changed: + ++statistic.changed; + break; + case ScanResultType.Added: + if (statistic.counter > 0) { + ++statistic.new; + } + break; + case ScanResultType.Removed: + ++statistic.deleted; + break; + case ScanResultType.Offline: + ++statistic.offline; + break; + case ScanResultType.End: + ++statistic.counter; + break; + } + + statistic.end = Date.now(); + + return statistic; + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/variable.ts b/projects/aas-server/src/app/variable.ts new file mode 100644 index 00000000..beeb1cb3 --- /dev/null +++ b/projects/aas-server/src/app/variable.ts @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { singleton } from 'tsyringe'; +import path from 'path'; + +@singleton() +export class Variable { + constructor() { + this.JWT_SECRET = process.env.JWT_SECRET ?? 'The quick brown fox jumps over the lazy dog.'; + this.JWT_PUBLIC_KEY = process.env.JWT_PUBLIC_KEY; + this.JWT_EXPIRES_IN = process.env.JWT_EXPIRED_IN ? Number(process.env.JWT_EXPIRED_IN) : 7 * 24 * 60 * 60; + this.NODE_SERVER_PORT = Number(process.env.NODE_SERVER_PORT); + this.MAX_WORKERS = process.env.MAX_WORKERS ? Number(process.env.MAX_WORKERS) : 8; + this.USER_STORAGE = process.env.USER_STORAGE; + this.TEMPLATE_STORAGE = process.env.TEMPLATE_STORAGE; + this.CORS_ORIGIN = process.env.CORS_ORIGIN ? JSON.parse(process.env.CORS_ORIGIN) : '*'; + this.CONTENT_ROOT = path.resolve(process.env.CONTENT_ROOT ?? './'); + this.WEB_ROOT = path.resolve(process.env.WEB_ROOT ?? './wwwroot'); + this.ASSETS = path.resolve(process.env.ASSETS ?? './assets'); + this.ENDPOINTS = process.env.ENDPOINTS ? JSON.parse(process.env.ENDPOINTS) : ['file:///samples?name=Samples']; + this.TIMEOUT = process.env.TIMEOUT ? Number(process.env.TIMEOUT) : 5000; + this.HTTPS_CERT_FILE = process.env.HTTPS_CERT_FILE; + this.HTTPS_KEY_FILE = process.env.HTTPS_KEY_FILE; + } + + /** The secret for HS256 encryption or the private key file for RS256 encryption. */ + public readonly JWT_SECRET: string; + + /** The public key file for RS256 encryption. */ + public readonly JWT_PUBLIC_KEY?: string; + + /** The validity of the JSON web token in seconds (bearer token). */ + public readonly JWT_EXPIRES_IN: number; + + /** The validity of the JSON web token in seconds (query parameter). */ + public readonly JWT_SHORT_EXP = 5; + + /** The port of the AASServer. */ + public readonly NODE_SERVER_PORT: number; + + /** The number of worker threads. */ + public readonly MAX_WORKERS: number; + + /** The URL of the user storage. */ + public readonly USER_STORAGE?: string; + + /** The URL of the template storage. */ + public readonly TEMPLATE_STORAGE?: string; + + /** */ + public readonly CORS_ORIGIN: string | string[]; + + /** The directory where the AASServer app is located. */ + public readonly CONTENT_ROOT: string; + + /** The root directory for static files. */ + public readonly WEB_ROOT: string; + + /** The assets directory. */ + public readonly ASSETS: string; + + /** The URLs of the initial AAS container endpoints. */ + public readonly ENDPOINTS: string[]; + + /** */ + public readonly TIMEOUT: number; + + /** The key file if AASServer supports HTTPS. */ + public readonly HTTPS_KEY_FILE?: string; + + /** The certificate file if AASServer supports HTTPS. */ + public readonly HTTPS_CERT_FILE?: string; +} \ No newline at end of file diff --git a/projects/aas-server/src/app/worker-app.ts b/projects/aas-server/src/app/worker-app.ts new file mode 100644 index 00000000..eccc3b01 --- /dev/null +++ b/projects/aas-server/src/app/worker-app.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { inject, singleton } from 'tsyringe'; +import { parentPort } from 'worker_threads'; +import { Logger } from './logging/logger.js'; +import { WorkerData, isScanContainerData, isScanEndpointData } from './aas-provider/worker-data.js'; +import { ScanResult, ScanResultType } from './aas-provider/scan-result.js'; +import { toUint8Array } from './convert.js'; +import { ScanEndpoint } from './scan-endpoint.js'; +import { UpdateStatistic } from './update-statistic.js'; +import { ScanContainer } from './scan-container.js'; + +@singleton() +export class WorkerApp { + constructor( + @inject('Logger') private readonly logger: Logger, + @inject(ScanEndpoint) private scanEndpoint: ScanEndpoint, + @inject(ScanContainer) private readonly scanContainer: ScanContainer, + @inject(UpdateStatistic) private readonly statistic: UpdateStatistic + ) { + } + + public run(): void { + parentPort?.on('message', this.parentPortOnMessage); + } + + private parentPortOnMessage = async (data: WorkerData) => { + try { + this.logger.start(`Scan ${data.taskId}`); + if (isScanContainerData(data)) { + await this.scanContainer.scanAsync(data); + } else if (isScanEndpointData(data)) { + await this.scanEndpoint.scanAsync(data); + } + } catch (error) { + this.logger.error(error); + } finally { + this.logger.stop(); + const result: ScanResult = { + taskId: data.taskId, + type: ScanResultType.End, + statistic: this.statistic.update(data.statistic, ScanResultType.End), + messages: this.logger.getMessages() + }; + + parentPort?.postMessage(toUint8Array(result)); + } + } +} \ No newline at end of file diff --git a/projects/aas-server/src/app/ws-server.ts b/projects/aas-server/src/app/ws-server.ts new file mode 100644 index 00000000..01a242cf --- /dev/null +++ b/projects/aas-server/src/app/ws-server.ts @@ -0,0 +1,110 @@ +import { inject, singleton } from 'tsyringe'; +import { WebSocket, WebSocketServer } from 'ws'; +import http from 'http'; +import https from 'https'; +import { WebSocketData } from 'common'; +import EventEmitter from 'events'; +import fs from 'fs'; + +import { App } from './app.js'; +import { Variable } from './variable.js'; +import { SocketClient } from './live/socket-client.js'; +import { Logger } from './logging/logger.js'; + +/* istanbul ignore next */ +@singleton() +export class WSServer extends EventEmitter { + private readonly wss: WebSocketServer; + private readonly clients: Set = new Set(); + private readonly server: http.Server | https.Server; + + constructor( + @inject(App) app: App, + @inject(Variable) private readonly variable: Variable, + @inject('Logger') private readonly logger: Logger + ) { + super(); + + if (this.variable.HTTPS_KEY_FILE && this.variable.HTTPS_CERT_FILE) { + this.server = https.createServer({ + key: fs.readFileSync(this.variable.HTTPS_KEY_FILE), + cert: fs.readFileSync(this.variable.HTTPS_CERT_FILE), + }); + } else { + this.server = http.createServer(); + } + + this.wss = new WebSocketServer({ server: this.server }); + this.server.on('request', app.app); + + this.wss.on('connection', this.onConnection); + this.wss.on('close', this.onClose); + this.wss.on('error', this.onError); + } + + public run(): void { + this.server.listen(this.variable.NODE_SERVER_PORT, () => { + console.log(`AAS-Server listening on ${this.variable.NODE_SERVER_PORT}`); + }) + } + + public notify(name: string, data: WebSocketData): void { + for (const client of this.clients.values()) { + if (client.has(name)) { + client.notify(data); + } + } + } + + public close(): Promise { + return new Promise((resolve, reject) => { + this.clients.forEach(client => client.close()); + this.wss.close((error) => { + if (error) { + reject(error); + } else { + resolve(); + } + }); + }); + } + + private onConnection = (ws: WebSocket): void => { + const client = new SocketClient(ws); + client.on('message', this.onClientMessage); + client.on('close', this.onClientClose); + client.on('error', this.onClientError); + this.clients.add(client); + } + + private onClose = (): void => { + this.wss.clients.forEach(ws => ws.close()); + this.wss.off('connection', this.onConnection); + this.wss.off('close', this.onClose); + this.wss.off('error', this.onError); + } + + private onError = (error: Error): void => { + this.logger.error(`WebSocket server error: ${error?.message}`); + } + + private onClientClose = (code: number, reason: string, client: SocketClient): void => { + this.emit('close', client); + + client.off('message', this.onClientMessage); + client.off('close', this.onClientClose); + client.off('error', this.onClientError); + + if (!this.clients.delete(client)) { + this.logger.error(`Unknown WebSocket client detected.`); + } + } + + private onClientMessage = (data: WebSocketData, client: SocketClient): void => { + this.emit('message', data, client); + } + + private onClientError = (error: Error, client: SocketClient): void => { + this.emit('error', error, client); + } +} \ No newline at end of file diff --git a/projects/aas-server/src/assets/endpoints/samples/01_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/01_Festo.aasx new file mode 100644 index 00000000..9ecf60e4 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/01_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/02_Bosch.aasx b/projects/aas-server/src/assets/endpoints/samples/02_Bosch.aasx new file mode 100644 index 00000000..2cd2b865 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/02_Bosch.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/03_Bosch.aasx b/projects/aas-server/src/assets/endpoints/samples/03_Bosch.aasx new file mode 100644 index 00000000..709f7ad7 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/03_Bosch.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/04_Bosch.aasx b/projects/aas-server/src/assets/endpoints/samples/04_Bosch.aasx new file mode 100644 index 00000000..848d9ac3 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/04_Bosch.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/05_Bosch.aasx b/projects/aas-server/src/assets/endpoints/samples/05_Bosch.aasx new file mode 100644 index 00000000..b44dd8e9 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/05_Bosch.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/06_Bosch.aasx b/projects/aas-server/src/assets/endpoints/samples/06_Bosch.aasx new file mode 100644 index 00000000..951c7c18 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/06_Bosch.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/07_PhoenixContact.aasx b/projects/aas-server/src/assets/endpoints/samples/07_PhoenixContact.aasx new file mode 100644 index 00000000..e13218bf Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/07_PhoenixContact.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/08_SchneiderElectric.aasx b/projects/aas-server/src/assets/endpoints/samples/08_SchneiderElectric.aasx new file mode 100644 index 00000000..ee86a06b Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/08_SchneiderElectric.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/09_SchneiderElectric.aasx b/projects/aas-server/src/assets/endpoints/samples/09_SchneiderElectric.aasx new file mode 100644 index 00000000..c276a195 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/09_SchneiderElectric.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/10_SchneiderElectric.aasx b/projects/aas-server/src/assets/endpoints/samples/10_SchneiderElectric.aasx new file mode 100644 index 00000000..88b5d791 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/10_SchneiderElectric.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/11_SchneiderElectric.aasx b/projects/aas-server/src/assets/endpoints/samples/11_SchneiderElectric.aasx new file mode 100644 index 00000000..7d364d26 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/11_SchneiderElectric.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/12_Pepperl+Fuchs.aasx b/projects/aas-server/src/assets/endpoints/samples/12_Pepperl+Fuchs.aasx new file mode 100644 index 00000000..26af8a08 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/12_Pepperl+Fuchs.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/13_DKE.aasx b/projects/aas-server/src/assets/endpoints/samples/13_DKE.aasx new file mode 100644 index 00000000..0be84202 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/13_DKE.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/14_Siemens.aasx b/projects/aas-server/src/assets/endpoints/samples/14_Siemens.aasx new file mode 100644 index 00000000..f303d148 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/14_Siemens.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/15_Siemens.aasx b/projects/aas-server/src/assets/endpoints/samples/15_Siemens.aasx new file mode 100644 index 00000000..67438d36 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/15_Siemens.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/16_Lenze.aasx b/projects/aas-server/src/assets/endpoints/samples/16_Lenze.aasx new file mode 100644 index 00000000..99c7038e Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/16_Lenze.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/17_ABB.aasx b/projects/aas-server/src/assets/endpoints/samples/17_ABB.aasx new file mode 100644 index 00000000..64e9e222 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/17_ABB.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/18_Hitachi.aasx b/projects/aas-server/src/assets/endpoints/samples/18_Hitachi.aasx new file mode 100644 index 00000000..7f97ca81 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/18_Hitachi.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/19_Balluff.aasx b/projects/aas-server/src/assets/endpoints/samples/19_Balluff.aasx new file mode 100644 index 00000000..bd8c3b89 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/19_Balluff.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/20_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/20_Festo.aasx new file mode 100644 index 00000000..04a5bf5d Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/20_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/21_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/21_Festo.aasx new file mode 100644 index 00000000..81ff1bf9 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/21_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/22_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/22_Festo.aasx new file mode 100644 index 00000000..42f56dfb Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/22_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/23_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/23_Festo.aasx new file mode 100644 index 00000000..43751377 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/23_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/24_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/24_Festo.aasx new file mode 100644 index 00000000..93e8ee7d Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/24_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/25_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/25_Festo.aasx new file mode 100644 index 00000000..9b3f7536 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/25_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/26_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/26_Festo.aasx new file mode 100644 index 00000000..5e589159 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/26_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/27_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/27_Festo.aasx new file mode 100644 index 00000000..a73d1c4f Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/27_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/30_Wittenstein.aasx b/projects/aas-server/src/assets/endpoints/samples/30_Wittenstein.aasx new file mode 100644 index 00000000..8f775a31 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/30_Wittenstein.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/31_SICK.aasx b/projects/aas-server/src/assets/endpoints/samples/31_SICK.aasx new file mode 100644 index 00000000..f197399c Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/31_SICK.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/32_SICK.aasx b/projects/aas-server/src/assets/endpoints/samples/32_SICK.aasx new file mode 100644 index 00000000..33f05ca5 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/32_SICK.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/33_SICK.aasx b/projects/aas-server/src/assets/endpoints/samples/33_SICK.aasx new file mode 100644 index 00000000..576f95e0 Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/33_SICK.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/34_Festo.aasx b/projects/aas-server/src/assets/endpoints/samples/34_Festo.aasx new file mode 100644 index 00000000..f1305d1e Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/34_Festo.aasx differ diff --git a/projects/aas-server/src/assets/endpoints/samples/36_Murrelektronik.aasx b/projects/aas-server/src/assets/endpoints/samples/36_Murrelektronik.aasx new file mode 100644 index 00000000..3543ccbc Binary files /dev/null and b/projects/aas-server/src/assets/endpoints/samples/36_Murrelektronik.aasx differ diff --git a/projects/aas-server/src/assets/templates/submodel-element/multi-language-property.json b/projects/aas-server/src/assets/templates/submodel-element/multi-language-property.json new file mode 100644 index 00000000..7874b175 --- /dev/null +++ b/projects/aas-server/src/assets/templates/submodel-element/multi-language-property.json @@ -0,0 +1,21 @@ +{ + "modelType": { + "name": "MultiLanguageProperty" + }, + "idShort": "MultiLanguageProperty", + "constraints": [], + "value": { + "langString": [ + { + "language": "de", + "text": "deutsch" + }, + { + "language": "en", + "text": "english" + } + ] + }, + "kind": "Instance", + "category": "CONSTANT" +} \ No newline at end of file diff --git a/projects/aas-server/src/assets/templates/submodel-element/property.json b/projects/aas-server/src/assets/templates/submodel-element/property.json new file mode 100644 index 00000000..123c4474 --- /dev/null +++ b/projects/aas-server/src/assets/templates/submodel-element/property.json @@ -0,0 +1,15 @@ +{ + "modelType": { + "name": "Property" + }, + "idShort": "Property", + "constraints": [], + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "value": "Lorem ipsum dolor", + "kind": "Instance", + "category": "CONSTANT" +} \ No newline at end of file diff --git a/projects/aas-server/src/assets/templates/submodel-element/submodel-element-collection.json b/projects/aas-server/src/assets/templates/submodel-element/submodel-element-collection.json new file mode 100644 index 00000000..2795b3cd --- /dev/null +++ b/projects/aas-server/src/assets/templates/submodel-element/submodel-element-collection.json @@ -0,0 +1,11 @@ +{ + "modelType": { + "name": "SubmodelElementCollection" + }, + "ordered": false, + "allowDuplicates": false, + "idShort": "SubmodelElementCollection", + "constraints": [], + "kind": "Instance", + "category": "CONSTANT" +} \ No newline at end of file diff --git a/projects/aas-server/src/assets/templates/submodel/Submodel_Nameplate.json b/projects/aas-server/src/assets/templates/submodel/Submodel_Nameplate.json new file mode 100644 index 00000000..9176eb3b --- /dev/null +++ b/projects/aas-server/src/assets/templates/submodel/Submodel_Nameplate.json @@ -0,0 +1,4570 @@ +{ + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate", + "index": 0, + "idType": "IRI" + } + ] + }, + "qualifiers": [], + "hasDataSpecification": [], + "identification": { + "idType": "IRI", + "id": "www.example.com/ids/sm/1225_9020_5022_1974" + }, + "idShort": "Nameplate", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "https://www.domain-abc.com/Model-Nr-1234/Serial-Nr-5678", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAY811#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "URIOfTheProduct", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABN590#001 URI of product instance " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Muster AG" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO677#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ManufacturerName", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA565#007 manufacturer Note: mandatory property according to EU Machine Directive 2006/42/EC. " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "ABC-123" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAW338#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ManufacturerProductDesignation", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA567#007 name of product Note: Short designation of the product is meant. Note: mandatory property according to EU Machine Directive 2006/42/EC. " + } + ] + }, + { + "ordered": false, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ContactInformation", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0173-1#07-AAS931#001", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO204#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "RoleOfContactPerson", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "enumeration: 0173-1#07-AAS927#001 (administrativ contact), 0173-1#07-AAS928#001 (commercial contact), 0173-1#07-AAS929#001 (other contact), 0173-1#07-AAS930#001 (hazardous goods contact), 0173-1#07-AAS931#001 (technical contact). Note: the above mentioned ECLASS enumeration should be declared as “open” for further addition. ECLASS enumeration IRDI is preferable. If no IRDI available, custom input as String may also be accepted." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "DE" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO134#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "NationalCode", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61360_4#ADA005#001 country code. country codes defined accord. to DIN EN ISO 3166-1 alpha-2 codes. Mandatory property according to EU Machine Directive 2006/42/EC. Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "de", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Language", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Language", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: language codes defined accord. to ISO 639-1. Note: as per ECLASS definition, Expression and representation of thoughts, information, feelings, ideas through characters." + } + ] + }, + { + "value": "Z", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/TimeZone", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TimeZone", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: notation accord. to ISO 8601 Note: for time in UTC the zone designator “Z” is to be used" + } + ] + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Musterstadt" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO132#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "CityTown", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA129#001 city/town. Mandatory property according to EU Machine Directive 2006/42/EC." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "ABC Company" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAW001#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Company", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Vertrieb" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO127#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Department", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/Phone", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Phone", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": { + "langString": [ + { + "language": "en", + "text": "+491234567890" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO136#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TelephoneNumber", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "0173-1#07-AAS754#001", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO137#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfTelephone", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": " enumeration: 0173-1#07-AAS754#001 (office), 0173-1#07-AAS755#001 (office mobile), 0173-1#07-AAS756#001 (secretary), 0173-1#07-AAS757#001 (substitute), 0173-1#07-AAS758#001 (home), 0173-1#07-AAS759#001 (private mobile)" + } + ] + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Montag – Freitag 08:00 bis 16:00" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/AvailableTime/", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AvailableTime", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ834#005", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Fax", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": { + "langString": [ + { + "language": "en", + "text": "+491234567890" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO195#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "FaxNumber", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": " 0173-1#07-AAS754#001", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO196#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfFaxNumber", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "enumeration: 0173-1#07-AAS754#001 (office), 0173-1#07-AAS756#001 (secretary), 0173-1#07-AAS758#001 (home)" + } + ] + } + ], + "kind": "Instance" + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ836#005", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Email", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "email@muster-ag.de", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO198#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "EmailAddress", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO200#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "PublicKey", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "0173-1#07-AAS754#001", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO199#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfEmailAddress", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "enumeration: 0173-1#07-AAS754#001 (office), 0173-1#07-AAS756#001 (secretary), 0173-1#07-AAS757#001 (substitute), 0173-1#07-AAS758#001 (home)" + } + ] + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO201#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfPublicKey", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "IPCommunication{00}", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ326#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AddressOfAdditionalLink", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + }, + { + "value": "Chat", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ ContactInformations/ContactInformation/IPCommunication/TypeOfCommunication", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfCommunication", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Montag – Freitag 08:00 bis 16:00" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/1/0/ContactInformations/ContactInformation/AvailableTime/", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AvailableTime", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Musterstraße 1" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO128#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Street", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA286#001 street. Mandatory property according to EU Machine Directive 2006/42/EC" + } + ] + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "12345" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO129#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Zipcode", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA281#001 ZIP/Postal code. Mandatory property according to EU Machine Directive 2006/42/EC. Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "PF 1234" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO130#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "POBox", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "12345" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO131#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ZipCodeOfPOBox", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "de", + "text": "Muster-Bundesland" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO133#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "StateCounty", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO205#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "NameOfContact", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO206#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "FirstName", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO207#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MiddleNames", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO208#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Title", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO209#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AcademicTitle", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO210#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "FurtherDetailsOfContact", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ326#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AddressOfAdditionalLink", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "The SMC “ContactInformation” contains information on how to contact the manufacturer or an authorised service provider, e.g. when a maintenance service is required. Note: physical address is a mandatory property according to EU Machine Directive 2006/42/EC" + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "flow meter" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAU732#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ManufacturerProductRoot", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance" + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "Type ABC" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAU731#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ManufacturerProductFamily", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: conditionally mandatory property according to EU Machine Directive 2006/42/EC. One of the two properties must be provided: ManufacturerProductFamily (0173-1#02-AAU731#001) or ManufacturerProductType (0173-1#02-AAO057#002). " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "FM-ABC-1234" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO057#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ManufacturerProductType", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA300#006 code of product Note: conditionally mandatory property according to EU Machine Directive 2006/42/EC. One of the two properties must be provided: ManufacturerProductFamily (0173-1#02-AAU731#001) or ManufacturerProductType (0173-1#02-AAO057#002). " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "FMABC1234" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO227#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "OrderCodeOfManufacturer", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA950#006 order code of product Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "FM11-ABC22-123456" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO676#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ProductArticleNumberOfManufacturer", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA581#006 article number Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "12345678", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM556#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "SerialNumber", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA951#007 serial number " + } + ] + }, + { + "value": "2022", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAP906#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "YearOfConstruction", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: mandatory property according to EU Machine Directive 2006/42/EC. " + } + ] + }, + { + "value": "2022-01-01", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAR972#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "DateOfManufacture", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "date" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABB757#007 date of manufacture Note: format by lexical representation: CCYY-MM-DD " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "1.0.0" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAN270#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "HardwareVersion", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA926#006 hardware version Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "1.0" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM985#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "FirmwareVersion", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA302#004 firmware version Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "1.0.0" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM737#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "SoftwareVersion", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA601#006 software version Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "DE", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO259#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "CountryOfOrigin", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61360_4#ADA034#001 country of origin Note: Country codes defined accord. to DIN EN ISO 3166-1 alpha-2 codes " + } + ] + }, + { + "mimeType": "", + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/CompanyLogo ", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "CompanyLogo", + "modelType": { + "name": "File" + }, + "kind": "Instance" + }, + { + "ordered": false, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#01-AGZ673#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Markings", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": false, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#01-AHD206#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "hasDataSpecification": [], + "idShort": "Marking", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0173-1#07-DAA603#004", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/MarkingName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MarkingName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0173-1#02-BAB392#015 certificate/approval valueId with ECLASS enumeration IRDI is preferable, e.g. [IRDI] 0173-1#07-DAA603#004 for CE. If no IRDI available, string value can also be accepted. Note: CE marking is declared as mandatory according to Blue Guide of the EU-Commission " + } + ] + }, + { + "value": "KEMA99IECEX1105/128", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0112/2///61987#ABH783#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "DesignationOfCertificateOrApproval", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Approval identifier, reference to the certificate number, to be entered without spaces " + } + ] + }, + { + "value": "2022-01-01", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/IssueDate", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "IssueDate", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Date" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: format by lexical representation: CCYY-MM-DD Note: to be specified to the day " + } + ] + }, + { + "value": "2022-01-01", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExpiryDate", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExpiryDate", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Date" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also ([IRDI] 0173-1#02-AAO997#001 Validity date Note: format by lexical representation: CCYY-MM-DD Note: to be specified to the day " + } + ] + }, + { + "mimeType": "", + "value": "/aasx/Nameplate/marking_ce.png ", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/MarkingFile", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MarkingFile", + "modelType": { + "name": "File" + }, + "kind": "Instance" + }, + { + "value": "0044", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/MarkingAdditionalText", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MarkingAdditionalText", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0173-1#02-AAM954#002 details of other certificate " + } + ] + }, + { + "ordered": false, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExplosionSafeties", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": false, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "OneToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExplosionSafety", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "KEMA99IECEX1105/128", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0112/2///61987#ABH783#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "DesignationOfCertificateOrApproval", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Approval identifier, reference to the certificate number, to be entered without spaces " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "ATEX" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM812#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfApproval", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA231#008 type of hazardous area approval Note: name of the approval system, e.g. ATEX, IECEX, NEC, EAC, CCC, CEC Note: only values from the enumeration should be used as stated. For additional systems further values can be used. Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "PTB" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM632#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ApprovalAgencyTestingAgency", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA634#004 approval agency/testing agency Note: name of the agency, which has issued the certificate, e.g. PTB, KEMA, CSA, SIRA Note: only values from the enumeration should be used as stated. For additional systems further values can be used. Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "db", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ325#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfProtection", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA589#002 type of protection (Ex) Note: ·       Type of protection for the device as listed in the certificate ·       Symbol(s) for the Type of protection. Several types of protection are separated by a semicolon “;” ·       If several TypeOfProtection are listed in the same certificate, for each TypeOfProtection a separate SMC “Explosion Safety” shall be provided " + } + ] + }, + { + "value": "250", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAN532#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "RatedInsulationVoltage", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Um(eff) Note: Insulation voltage, if specified in the certificate " + } + ] + }, + { + "value": { + "keys": [] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0112/2///61987#ABO102#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "InstructionsControlDrawing", + "modelType": { + "name": "ReferenceElement" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Reference to the instruction manual or control drawing " + } + ] + }, + { + "value": "X", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/SpecificConditionsForUse", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "SpecificConditionsForUse", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: X if any, otherwise no entry" + } + ] + }, + { + "value": "U", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/IncompleteDevice", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "IncompleteDevice", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/AmbientConditions", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AmbientConditions", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "2G", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAK297#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "DeviceCategory", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA467#002 equipment/device category Note: editorial definiton: Category of device in accordance with directive 2014/34/EU Note: Equipment category according to the ATEX system. According to the current nameplate, also the combination “GD” is permitted Note: The combination “GD” is no longer accepted and was changed in the standards. Currently the marking for “G” and “D” must be provided in a separate marking string. Older devices may still exist with the marking “GD”. " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "Gb" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM668#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "EquipmentProtectionLevel", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA464#005 equipment protection level Note: editorial definition: Level of protection assigned to equipment based on its likelihood of becoming a source of ignition Note: Equipment protection level according to the IEC standards. According to the current nameplate, also the combination “GD” is permitted Note: The combination “GD” is no longer accepted and was changed in the standards. Currently the marking for “G” and “D” must be provided in a separate marking string. Older devices may still exist with the marking “GD”. Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "Class I, Division 2", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/RegionalSpecificMarking", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "RegionalSpecificMarking", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + }, + { + "value": "db", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ325#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfProtection", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA589#002 type of protection (Ex) Note: Symbol(s) for the Type of protection. Several types of protection are separated by a semicolon “;” " + } + ] + }, + { + "value": "IIC", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAT372#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExplosionGroup", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA961#007 permitted gas group/explosion group Note: Equipment grouping according to IEC 60079-0 is meant by this property Note: Symbol(s) for the gas group (IIA…IIC) or dust group (IIIA…IIIC) " + } + ] + }, + { + "value": "-40", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAZ952#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MinimumAmbientTemperature", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA621#007 minimum ambient temperature Note: editorial defnition: lower limit of the temperature range of the environment in which the component, the pipework or the system can be operated Note: Rated minimum ambient temperature Note: Positive temperatures are listed without “+” sign. If several temperatures ranges are marked, only the most general range shall be indicated in the template, which is consistent with the specified temperature class or maximum surface temperature. Other temperature ranges and temperature classes/maximum surface temperatures may be listed in the instructions." + } + ] + }, + { + "value": "120", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAA039#010", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxAmbientTemperature", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA623#007 maximum ambient temperature Note: editorial definition: upper limit of the temperature range of the environment in which the component, the pipework or the system can be operated Note: Rated maximum ambient temperature Note: Positive temperatures are listed without “+” sign. If several temperatures ranges are marked, only the most general range shall be indicated in the template, which is consistent with the specified temperature class or maximum surface temperature. Other temperature ranges and temperature classes/maximum surface temperatures may be listed in the instructions." + } + ] + }, + { + "value": "100", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM666#005", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxSurfaceTemperatureForDustProof", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABB159#004 maximum surface temperature for dust-proof Note: Maximum surface temperature of the device (dust layer ≤ 5 mm) for specified maximum ambient and maximum process temperature, relevant for Group III only Note: Positive temperatures are listed without “+” sign. If several temperatures ranges are marked, only the most general range shall be indicated in the template, which is consistent with the specified temperature class or maximum surface temperature. Other temperature ranges and temperature classes/maximum surface temperatures may be listed in the instructions." + } + ] + }, + { + "value": "T4", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO371#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TemperatureClass", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA593#002 temperature class Note: editorial definition: classification system of electrical apparatus, based on its maximum surface temperature, intended for use in an explosive atmospheres with flammable gas, vapour or mist. Note: Temperature class for specified maximum ambient and maximum process temperature, relevant for Group II only (Further combinations may be provided in the instruction manual). " + } + ] + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: If the device is mounted in the process boundary, ambient and process conditions are provided separately. " + } + ] + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/ProcessConditions", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ProcessConditions", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1G", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAK297#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "DeviceCategory", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA467#002 equipment/device category Note: editorial defnition: Category of device in accordance with directive 2014/34/EU Note: Equipment category according to the ATEX system. " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "Ga" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM668#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "EquipmentProtectionLevel", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA464#005 equipment protection level Note: editorial defnition: Level of protection assigned to equipment based on its likelihood of becoming a source of ignition Note: Equipment protection level according to the IEC or other standards, e.g. Ga (IEC), Class I/Division 1 (US), Zone (EAC) Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "IS", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/RegionalSpecificMarking", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "RegionalSpecificMarking", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + }, + { + "value": "ia", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ325#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfProtection", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA589#002 type of protection (Ex) Note: Symbol(s) for the Type of protection. Several types of protection are separated by a semicolon “;” " + } + ] + }, + { + "value": "IIC", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAT372#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExplosionGroup", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA961#007 permitted gas group/explosion group Note: editorial definition: classification of dangerous gaseous substances based on their ability to be ignited Note: Equipment grouping according to IEC 60079-0 is meant by this property Note: Symbol(s) for the gas group (IIA…IIC) or dust group (IIIA…IIIC) " + } + ] + }, + { + "value": "-40", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAN309#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "LowerLimitingValueOfProcessTemperature", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Rated minimum process temperature Note: Positive temperatures are listed without “+” sign. If several temperatures ranges are marked, only the most general range shall be indicated in the template, which is consistent with the specified temperature class or maximum surface temperature. Other temperature ranges and temperature classes/maximum surface temperatures may be listed in the instructions." + } + ] + }, + { + "value": "120", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAN307#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "UpperLimitingValueOfProcessTemperature", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Rated maximum process temperature Note: Positive temperatures are listed without “+” sign. If several temperatures ranges are marked, only the most general range shall be indicated in the template, which is consistent with the specified temperature class or maximum surface temperature. Other temperature ranges and temperature classes/maximum surface temperatures may be listed in the instructions." + } + ] + }, + { + "value": "85", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM666#005", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxSurfaceTemperatureForDustProof", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABB159#004 maximum surface temperature for dust-proof Note: Maximum surface temperature (dust layer ≤ 5 mm) for specified maximum ambient and maximum process temperature, relevant for Group III only Note: Positive temperatures are listed without “+” sign. If several temperatures ranges are marked, only the most general range shall be indicated in the template, which is consistent with the specified temperature class or maximum surface temperature. Other temperature ranges and temperature classes/maximum surface temperatures may be listed in the instructions." + } + ] + }, + { + "value": "T4", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO371#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TemperatureClass", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA593#002 temperature class Note: editorial definition: classification system of electrical apparatus, based on its maximum surface temperature, intended for use in an explosive atmospheres with flammable gas, vapour or mist. Note: Temperature class for specified maximum ambient and maximum process temperature, relevant for Group II only (Further combinations may be provided in the instruction manual). " + } + ] + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: If the device is mounted in the process boundary, ambient and process conditions are provided separately. " + } + ] + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/ExternalElectricalCircuit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExternalElectricalCircuit", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "+/-", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0112/2///61987#ABB147#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "DesignationOfElectricalTerminal", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: For each circuit the designation of the terminals shall be specified. If several circuits are provided with the same parameters, their terminal pairs are listed and separated by a semicolon. If several circuits belong to one channel this shall be described in the instructions. " + } + ] + }, + { + "value": "db", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ325#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TypeOfProtection", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA589#002 type of protection (Ex)) Note: ·       Type of protection for the device as listed in the certificate ·       Symbol(s) for the Type of protection. Several types of protection are separated by a semicolon “;” ·       If several TypeOfProtection are listed in the same certificate, for each TypeOfProtection a separate SMC “Explosion Safety” shall be provided " + } + ] + }, + { + "value": { + "langString": [ + { + "language": "en", + "text": "Ga" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM668#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "EquipmentProtectionLevel", + "modelType": { + "name": "MultiLanguageProperty" + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA464#005 equipment protection level Note: editorial definition: Level of protection assigned to equipment based on its likelihood of becoming a source of ignition Note: EPL according to IEC standards Note: value should be chosen from an enumeration list with values “Ga, Gb, Gc, Da, Db, Dc, Ma, Mb” Note: Recommendation: property declaration as MLP is required by its semantic definition. As the property value is language independent, users are recommended to provide maximal 1 string in any language of the user’s choice." + } + ] + }, + { + "value": "IIC", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAT372#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "ExplosionGroup", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA961#007 permitted gas group/explosion group Note: editorial definition: classification of dangerous gaseous substances based on their ability to be ignited Note: Equipment grouping according to IEC 60079-0 is meant by this property Note: Symbol(s) for the gas group (IIA…IIC) or dust group (IIIA…IIIC) " + } + ] + }, + { + "value": "linear", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/ExternalElectricalCircuit/Characteristics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Characteristics", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: linear/ non-linear " + } + ] + }, + { + "value": "x", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/ExternalElectricalCircuit/Fisco", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "Fisco", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Enter “x” if relevant " + } + ] + }, + { + "value": "x", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "https://admin-shell.io/zvei/nameplate/2/0/Nameplate/Markings/Marking/ExplosionSafeties/ExplosionSafety/ExternalElectricalCircuit/TwoWISE", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "TwoWISE", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: Enter “x” if relevant " + } + ] + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ380#006", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "SafetyRelatedPropertiesForPassiveBehaviour", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1250", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ372#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxInputPower", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA981#001 maximum input power (Pi) Note: Limit value for input power " + } + ] + }, + { + "value": "30", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM638#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxInputVoltage", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA982#001 maximum input voltage (Ui) Note: Limit value for input voltage " + } + ] + }, + { + "value": "100", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM642#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxInputCurrent", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA983#001 maximum input current (Ii) Note: Limit value for input current " + } + ] + }, + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM640#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxInternalCapacitance", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA984#001 maximum internal capacitance (Ci) Note: Maximum internal capacitance of the circuit " + } + ] + }, + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM639#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxInternalInductance", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA985#001 maximum internal inductance (Li) Note: Maximum internal inductance of the circuit " + } + ] + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABC586#001 Safety related properties for passive behaviour Note: IS-parameters for passive circuits, if relevant (e.g. 2 wire field devices, valves) " + } + ] + }, + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ381#006", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "SafetyRelatedPropertiesForActiveBehaviour", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "960", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAQ371#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxOutputPower", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA987#001 maximum output power (Po) Note: Limit value for output power " + } + ] + }, + { + "value": "15.7", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM635#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxOutputVoltage", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA989#001 maximum output voltage (Uo) Note: Limit value for open circuits output voltage " + } + ] + }, + { + "value": "245", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM641#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxOutputCurrent", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA988#001maximum output current (Io) Note: Limit value for closed circuit output current " + } + ] + }, + { + "value": "2878", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM637#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxExternalCapacitance", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA990#001 maximum external capacitance (Co) Note: Maximum external capacitance to be connected to the circuit " + } + ] + }, + { + "value": "2.9", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM636#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxExternalInductance", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABA991#001 maximum external inductance (Lo) Note: Maximum external inductance to be connected to the circuit " + } + ] + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAM634#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "MaxExternalInductanceResistanceRatio", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "Decimal" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABB145#001 maximum external inductance/resistance ratio (Lo/Ro) Note: External Inductance to Resistance ratio " + } + ] + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABC585#001 Safety related properties for active behaviour Note: IS-parameters for active circuits, if relevant (e.g. power supply, IS-barriers) " + } + ] + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: If several external circuits can be connected to the device, this block shall provide a cardinality with the number of circuits Note: If for one external IS circuit several sets of safety parameters are provided (e.g. for several material groups), each set is specified in a separate block as a separate circuit. " + } + ] + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: see also [IRDI] 0112/2///61987#ABH515#003 Certificate or approval Note: CE marking is declared as mandatory according to the Blue Guide of the EU-Commission " + } + ] + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: CE marking is declared as mandatory according to EU Machine Directive 2006/42/EC." + } + ] + }, + { + "ordered": false, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#01-AGZ672#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "ZeroToOne", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "AssetSpecificProperties", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#01-AHD205#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "OneToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "GuidelineSpecificProperties{00}", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO856#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "One", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "GuidelineForConformityDeclaration", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": false, + "value": "www.example.com/ids/cd/3325_9020_5022_1074", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "OneToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "{arbitrary}", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "String" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": false, + "value": "www.example.com/ids/cd/3325_9020_5022_1964", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [ + { + "type": "Multiplicity", + "valueType": "", + "value": "OneToMany", + "modelType": { + "name": "Qualifier" + } + } + ], + "hasDataSpecification": [], + "idShort": "{arbitrary}", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance", + "descriptions": [ + { + "language": "en", + "text": "Note: defined as “Asset specific nameplate information” per ECLASS " + } + ] + } + ], + "descriptions": [ + { + "language": "en", + "text": "Contains the nameplate information attached to the product" + } + ] +} diff --git a/projects/aas-server/src/test/aas-provider/aas-provider.spec.ts b/projects/aas-server/src/test/aas-provider/aas-provider.spec.ts new file mode 100644 index 00000000..c2f3e1a0 --- /dev/null +++ b/projects/aas-server/src/test/aas-provider/aas-provider.spec.ts @@ -0,0 +1,268 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { Readable } from 'stream'; +import { AASDocument, aas } from 'common'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +import { Logger } from '../../app/logging/logger.js'; +import { AASProvider } from '../../app/aas-provider/aas-provider.js'; +import { Parallel } from '../../app/aas-provider/parallel.js'; +import { LocalFileStorage } from '../../app/file-storage/local-file-storage.js'; +import { AASPackage } from '../../app/packages/aas-package.js'; +import { sampleDocument } from '../assets/sample-document.js'; +import { AASResourceFactory } from '../../app/packages/aas-resource-factory.js'; +import { AASResource } from '../../app/packages/aas-resource.js'; +import { createSpyObj } from '../utils.js'; +import { AASServerConfiguration, createEndpoint } from '../../app/configuration.js'; +import { AASResourceScanFactory } from '../../app/aas-provider/aas-resource-scan-factory.js'; +import { WSServer } from '../../app/ws-server.js'; +import { Variable } from '../../app/variable.js'; +import { FileStorageFactory } from '../../app/file-storage/file-storage-factory.js'; + +describe('AASProvider', function () { + let aasProvider: AASProvider; + let variable: jest.Mocked; + let fileStorageFactory: jest.Mocked; + const logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + const parallel = createSpyObj(['execute', 'on']); + const wsServer = createSpyObj(['notify', 'close', 'on']); + const resourceFactory = createSpyObj(['create', 'testAsync']); + + beforeEach(function () { + fileStorageFactory = createSpyObj(['create']); + fileStorageFactory.create.mockReturnValue(new LocalFileStorage('./src/test/assets/samples')); + resourceFactory.testAsync.mockReturnValue(new Promise(resolve => resolve())); + variable = createSpyObj({}, { ENDPOINTS: [] }); + }); + + describe('addEndpointAsync', function () { + beforeEach(function () { + variable.ENDPOINTS.push(createEndpoint('file:///shop', 'Shop').href); + aasProvider = new AASProvider( + variable, { + endpoints: [ + createEndpoint('file:///shop', 'Shop').href + ] + }, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + }); + + it('adds an existing endpoint to the configuration', async function () { + await aasProvider.addEndpointAsync('samples', createEndpoint('file:///samples', 'samples')); + const workspaces = aasProvider.getWorkspaces(); + expect(workspaces.length).toEqual(2); + }); + }); + + describe('removeEndpointAsync', function () { + beforeEach(function () { + variable.ENDPOINTS.push( + createEndpoint('file:///shop', 'Shop').href, + createEndpoint('file:///samples', 'Samples').href); + + aasProvider = new AASProvider( + variable, { + endpoints: + [ + createEndpoint('file:///shop', 'Shop').href, + createEndpoint('file:///samples', 'Samples').href + ] + }, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + }); + + it('removes an endpoint from the configuration', async function () { + await aasProvider.removeEndpointAsync('Shop'); + const workspaces = aasProvider.getWorkspaces(); + expect(workspaces.length).toEqual(1); + if (workspaces.length > 0) { + expect(workspaces[0].name).toEqual('Samples'); + } else { + expect(workspaces.length).toBeGreaterThan(0); + } + }); + }); + + describe('resetAsync', function () { + beforeEach(function () { + variable.ENDPOINTS.push( + createEndpoint('file:///shop', 'Shop').href, + createEndpoint('file:///samples', 'Samples').href); + + const configuration: AASServerConfiguration = { + endpoints: [ + createEndpoint('file:///samples', 'Samples').href + ] + }; + + aasProvider = new AASProvider( + variable, + configuration, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + }); + + it('resets the configuration', async function () { + let workspaces = aasProvider.getWorkspaces(); + expect(workspaces.length).toEqual(1); + expect(workspaces[0].name).toEqual('Samples'); + + await aasProvider.resetAsync(); + workspaces = aasProvider.getWorkspaces(); + expect(workspaces.length).toEqual(2); + expect(workspaces[0].name).toEqual('Shop'); + expect(workspaces[1].name).toEqual('Samples'); + }); + }); + + describe('getPackageAsync', function () { + beforeEach(async function () { + const configuration: AASServerConfiguration = { + endpoints: [createEndpoint('file:///samples', 'Samples').href] + }; + + variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); + aasProvider = new AASProvider( + variable, + configuration, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); + }); + + it('downloads an AASX package', async function () { + const source = createSpyObj(['openAsync', 'closeAsync', 'getPackageAsync']); + source.getPackageAsync.mockReturnValue(new Promise(resolve => { + const stream = new Readable(); + stream.push('Hello World!'); + stream.push(null); + resolve(stream); + })); + + resourceFactory.create.mockReturnValue(source); + await expect(aasProvider.getDocumentAsync( + 'http://customer.com/aas/9175_7013_7091_9168', + 'file:///samples')).resolves.toBeDefined(); + }); + }); + + describe('addDocumentAsync', function () { + beforeEach(async function () { + const configuration: AASServerConfiguration = { + endpoints: [createEndpoint('file:///samples', 'Samples').href] + }; + + variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); + aasProvider = new AASProvider( + variable, + configuration, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); + }); + + it('uploads an AASX package', async function () { + const source = createSpyObj(['openAsync', 'closeAsync', 'postPackageAsync']); + const aasPackage = createSpyObj(['createDocumentAsync']); + aasPackage.createDocumentAsync.mockReturnValue(new Promise(resolve => resolve(sampleDocument))); + source.postPackageAsync.mockReturnValue(new Promise(resolve => resolve(aasPackage))); + resourceFactory.create.mockReturnValue(source); + await expect(aasProvider.addDocumentsAsync( + 'file:///samples', + [createSpyObj(['buffer'])])).resolves.toBeUndefined(); + }); + }); + + describe('deletePackageAsync', function () { + beforeEach(async function () { + const configuration: AASServerConfiguration = { + endpoints: [createEndpoint('file:///samples', 'Samples').href] + }; + + variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); + aasProvider = new AASProvider( + variable, + configuration, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); + }); + + it('deletes an AASX package', async function () { + const source = createSpyObj(['openAsync', 'closeAsync', 'deletePackageAsync']); + source.deletePackageAsync.mockReturnValue(new Promise(resolve => resolve())); + resourceFactory.create.mockReturnValue(source); + await expect(aasProvider.deleteDocumentAsync( + 'file:///samples', + 'http://customer.com/aas/9175_7013_7091_9168')).resolves.toBeUndefined(); + + expect(source.deletePackageAsync).toHaveBeenCalled(); + }); + }); + + describe('invoke', function () { + beforeEach(async function () { + const configuration: AASServerConfiguration = { + endpoints: [createEndpoint('file:///samples', 'Samples').href] + }; + + variable.ENDPOINTS.push(createEndpoint('file:///samples', 'Samples').href); + aasProvider = new AASProvider( + variable, + configuration, + logger, + parallel, + resourceFactory); + + aasProvider.start(wsServer); + await aasProvider.scanAsync(new AASResourceScanFactory(logger, fileStorageFactory)); + }); + + it('invokes an operation', async function () { + const operation: aas.Operation = { + idShort: 'noop', + modelType: 'Operation' + }; + + const source = createSpyObj(['openAsync', 'closeAsync', 'invoke']); + source.invoke.mockReturnValue(new Promise(resolve => resolve(operation))); + resourceFactory.create.mockReturnValue(source); + + await expect(aasProvider.invoke( + 'file:///samples', + 'http://customer.com/aas/9175_7013_7091_9168', + operation)).resolves.toEqual(operation); + + expect(source.openAsync).toHaveBeenCalled(); + expect(source.invoke).toHaveBeenCalled(); + expect(source.closeAsync).toHaveBeenCalled(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/aas-provider/aas-registry-scan.spec.ts b/projects/aas-server/src/test/aas-provider/aas-registry-scan.spec.ts new file mode 100644 index 00000000..e6e723e5 --- /dev/null +++ b/projects/aas-server/src/test/aas-provider/aas-registry-scan.spec.ts @@ -0,0 +1,93 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import http, { IncomingMessage } from 'http'; +import { AASContainer } from 'common'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +import { AASRegistryScan } from '../../app/aas-provider/aas-registry-scan.js'; +import { Logger } from '../../app/logging/logger.js'; +import { Socket } from 'net'; +import testRegistry from '../assets/test-registry.js' +import { createSpyObj } from '../utils.js'; +import { AssetAdministrationShellDescriptor } from '../../app/types/registry.js'; + +describe('AASRegistryScan', function () { + let registryScan: AASRegistryScan; + let logger: jest.Mocked; + let endpoint: URL; + let descriptors: AssetAdministrationShellDescriptor[]; + + beforeEach(function () { + descriptors = testRegistry as unknown as AssetAdministrationShellDescriptor[]; + endpoint = new URL('http://localhost/registry/api/v1/registry/'); + endpoint.searchParams.append('name', 'AAS Registry'); + endpoint.searchParams.append('type', 'AASRegistry'); + + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + }); + + it('should create', function () { + expect(new AASRegistryScan(logger, endpoint.href, [])).toBeTruthy(); + }); + + it('adds new containers', async function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify(descriptors)); + stream.push(null); + stream.statusCode = 201, + stream.statusMessage = 'Created', + (callback as (res: IncomingMessage) => void)(stream); + + return new http.ClientRequest('http://localhost:1234/registry/api/v1/registry/'); + }); + + registryScan = new AASRegistryScan(logger, endpoint.href, []); + const spy = jest.fn(); + registryScan.on('added', spy); + await expect(registryScan.scanAsync()).resolves.toBeUndefined(); + expect(spy).toHaveBeenCalledTimes(descriptors.length); + registryScan.off('added', spy); + }); + + it('removes unavailable containers', async function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify([])); + stream.push(null); + stream.statusCode = 200, + stream.statusMessage = 'OK', + (callback as (res: IncomingMessage) => void)(stream); + + return new http.ClientRequest('http://localhost:1234/registry/api/v1/registry/'); + }); + + const containers: AASContainer[] = [ + { + name: 'http://172.16.160.171:51000', + url: 'http://172.16.160.171:51000/?type=AasxServer' + }, + { + name: 'http://172.16.160.188:50010', + url: 'http://172.16.160.188:50010/?type=AasxServer' + }, + { + name: 'http://172.16.160.171:54000', + url: 'http://172.16.160.171:54000/?type=AasxServer' + } + ]; + + registryScan = new AASRegistryScan(logger, endpoint.href, containers); + const spy = jest.fn(); + registryScan.on('removed', spy); + await expect(registryScan.scanAsync()).resolves.toBeUndefined(); + expect(spy).toHaveBeenCalledTimes(containers.length); + registryScan.off('removed', spy); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/aas-provider/aasx-server-endpoint-scan.spec.ts b/projects/aas-server/src/test/aas-provider/aasx-server-endpoint-scan.spec.ts new file mode 100644 index 00000000..9ff0065d --- /dev/null +++ b/projects/aas-server/src/test/aas-provider/aasx-server-endpoint-scan.spec.ts @@ -0,0 +1,100 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import net from 'net'; +import { AASXServerEndpointScan } from '../../app/aas-provider/aasx-server-endpoint-scan.js'; +import { Logger } from '../../app/logging/logger.js'; +import { createSpyObj } from '../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import { createEndpoint } from '../../app/configuration.js'; +import { AASResourceFactory } from '../../app/packages/aas-resource-factory.js'; +import { AASResource } from '../../app/packages/aas-resource.js'; +import { reject } from 'lodash-es'; + +describe('AasxServerEndpointScan', function () { + let logger: jest.Mocked; + let resourceFactory: jest.Mocked; + let resource: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + resource = createSpyObj(['openAsync', 'closeAsync']); + resourceFactory = createSpyObj(['create']); + resourceFactory.create.mockReturnValue(resource); + }); + + describe('added', function () { + let scan: AASXServerEndpointScan; + let socket: jest.Mocked; + + beforeEach(function () { + scan = new AASXServerEndpointScan( + logger, + resourceFactory, + createEndpoint('http://localhost:1234', 'aasx server').href, + []); + + socket = createSpyObj(['on', 'setTimeout', 'end']); + socket.on.mockImplementation((event, listener) => { + if (event === 'connect') { + setTimeout(() => (listener as () => void)()); + } + + return socket; + }); + }); + + it('adds an available AASX server', async function () { + jest.spyOn(net, 'createConnection').mockImplementation(() => { + return socket; + }); + + const spy = jest.fn(); + scan.on('added', spy); + await scan.scanAsync(); + expect(spy).toHaveBeenCalled(); + scan.off('added', spy); + }); + }); + + describe('removed', function () { + let scan: AASXServerEndpointScan; + let socket: jest.Mocked; + + beforeEach(function () { + const endpoint = createEndpoint('http://localhost:1234', 'aasx server').href; + scan = new AASXServerEndpointScan( + logger, + resourceFactory, + endpoint, + [{ name: 'aasx server', url: endpoint }]); + + socket = createSpyObj(['on', 'setTimeout', 'destroy']); + socket.on.mockImplementation((event, listener) => { + if (event === 'timeout') { + setTimeout(() => (listener as () => void)()); + } + + return socket; + }); + }); + + it('removes an unavailable AASX server', async function () { + resource.openAsync.mockReturnValue(new Promise((_, reject) => reject(new Error()))); + jest.spyOn(net, 'createConnection').mockImplementation(() => { + return socket; + }); + + const removedSpy = jest.fn(); + scan.on('removed', removedSpy); + await scan.scanAsync(); + expect(removedSpy).toHaveBeenCalled(); + scan.off('removed', removedSpy); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/application-info.spec.ts b/projects/aas-server/src/test/application-info.spec.ts new file mode 100644 index 00000000..4c58fc19 --- /dev/null +++ b/projects/aas-server/src/test/application-info.spec.ts @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { resolve } from 'path'; +import { ApplicationInfo } from '../app/application-info.js'; +import { Logger } from '../app/logging/logger.js'; +import { readFile } from 'fs/promises'; +import { PackageInfo } from 'common'; +import { createSpyObj } from './utils.js'; +import { describe, beforeEach, it, expect } from '@jest/globals'; + +describe('Application Info service', function () { + let logger: Logger; + let applicationInfo: ApplicationInfo; + let file: string; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + file = resolve('.', 'src/test/assets/app-info.json'); + applicationInfo = new ApplicationInfo(logger); + }); + + it('gets the AASServer package info', async function () { + const expected: PackageInfo = JSON.parse((await readFile(file)).toString()); + await expect(applicationInfo.getAsync(file)).resolves.toEqual(expected); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/aas-default-namespace.xml b/projects/aas-server/src/test/assets/aas-default-namespace.xml new file mode 100644 index 00000000..eae00810 --- /dev/null +++ b/projects/aas-server/src/test/assets/aas-default-namespace.xml @@ -0,0 +1,8384 @@ + + + + + Festo_3S7PM0CP4BD + CONSTANT + smart.festo.com/demo/aas/1/1/454576463545648365874 + + + HTTP://PK.FESTO.COM/3S7PM0CP4BD + + + + + + www.company.com/ids/sm/4343_5072_7091_3242 + + + + + www.company.com/ids/sm/2543_5072_7091_2660 + + + + + www.company.com/ids/sm/6053_5072_7091_5102 + + + + + www.company.com/ids/sm/6563_5072_7091_4267 + + + + + smart.festo.com/demo/sm/instance/1/1/13B7CCD9BF7A3F24 + + + + + + + + + FPK_3s7plfdrs35 + + Festo OVEL Vacuum generator + Festo OVEL Vakuumsaugdüse + + HTTP://PK.FESTO.COM/3S7PM0CP4BD + Instance + + + + + Nameplate + www.company.com/ids/sm/4343_5072_7091_3242 + + + https://www.hsu-hh.de/aut/aas/nameplate + + + Instance + + + + + ManufacturerName + PARAMETER + + + 0173-1#02-AAO677#002 + + + Instance + + string + Festo AG & Co. KG + + + + + ManufacturerProductDesignation + PARAMETER + + + 0173-1#02-AAW338#001 + + + Instance + + string + OVEL Vacuum generator + + + + + PhysicalAddress + PARAMETER + + + https://www.hsu-hh.de/aut/aas/physicaladdress + + + Instance + + + + + CountryCode + PARAMETER + + + 0173-1#02-AAO730#001 + + + Instance + + string + DE + + + + + Street + PARAMETER + + + 0173-1#02-AAO128#001 + + + Instance + + string + Ruiter Straße 82 + + + + + Zip + PARAMETER + + + 0173-1#02-AAO129#002 + + + Instance + + string + 73734 + + + + + CityTown + PARAMETER + + + 0173-1#02-AAO132#001 + + + Instance + + string + Esslingen-Berkheim + + + + + StateCounty + PARAMETER + + + 0173-1#02-AAO133#002 + + + Instance + + string + Baden-Württemberg + + + + false + false + + + + + ManufacturerProductFamily + PARAMETER + + + 0173-1#02-AAU731#001 + + + Instance + + + OVEL-5-H-10-P-VQ4-UA-Z-C-A-V1PNLK-H3 + + + + + SerialNumber + PARAMETER + + + 0173-1#02-AAM556#002 + + + Instance + + string + JO43 + + + + + BatchNumber + PARAMETER + + + 0173-1#02-AAQ196#001 + + + Instance + + + + + + + + ProductCountryOfOrigin + PARAMETER + + + 0173-1#02-AAO841#001 + + + Instance + + string + DE + + + + + YearOfConstruction + PARAMETER + + + 0173-1#02-AAP906#001 + + + Instance + + integer + 2019 + + + + + Marking_CE + PARAMETER + + + https://www.hsu-hh.de/aut/aas/productmarking + + + Instance + + + + + CEQualificationPresent + PARAMETER + + + 0173-1#02-BAF053#008 + + + Instance + + boolean + 1 + + + 0173-1#07-CAA016#001 + + + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + image/png + /aasx/Nameplate/marking_ce.png + + + + false + false + + + + + Marking_CRUUS + PARAMETER + + + https://www.hsu-hh.de/aut/aas/productmarking + + + Instance + + + + + CRUUSLabelingPresent + PARAMETER + + + 0173-1#02-AAR528#005 + + + Instance + + boolean + 1 + + + 0173-1#07-CAA016#001 + + + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + image/png + /aasx/Nameplate/marking_cruus.jpg + + + + false + false + + + + + Marking_RCM + PARAMETER + + + https://www.hsu-hh.de/aut/aas/productmarking + + + Instance + + + + + RCMLabelingPresent + PARAMETER + + + 0173-1#02-AAR528#005 + + + Instance + + boolean + 1 + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + image/png + /aasx/Nameplate/marking_rcm.jpg + + + + false + false + + + + + + Document + www.company.com/ids/sm/2543_5072_7091_2660 + + + https://www.hsu-hh.de/aut/aas/document + + + Instance + + + + + DeclarationCEMarking + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Erklärung zur CE-Kennzeichnung bei Produkten der Festo AG & Co.KG + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + CE_Kennzeichnung_2016_de.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/CE_Kennzeichnung_2016_de.pdf + + + + false + false + + + + + DeclarationRoHS + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + RoHS 2011/65/EU und delegierte Fassung (EU) 2015/863 + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + RoHS_2011_65_EU_Konzern_Information_de.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/RoHS_2011_65_EU_Konzern_Information_de.pdf + + + + false + false + + + + + DeclarationCRUUS + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + UL + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Underwriter Laboratories LLC + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Certificate of compliance + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_UL_4531318_-_2_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_UL_4531318_-_2_EN.pdf + + + + false + false + + + + + DeclarationIOLink + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Manufacturer's declaration of conformity + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + OVEL_IO_Link_5439356_-_3_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/OVEL_IO_Link_5439356_-_3_EN.pdf + + + + false + false + + + + + Manual_OVEL_EN + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8070874 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-05 + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Operating instructions Vacuum generator OVEL + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + The OVEL vacuum generator is used to generate a vacuum. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + OVEL_2017-05_8070876g1_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/OVEL_2017-05_8070876g1_EN.pdf + + + + false + false + + + + + Manual_OVEL_DE + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8070874 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-05 + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Bedienungsanleitung Vakuumsaugdüse OVEL + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + Die Vakuumsaugdüse OVEL wird bestimmungsgemäß zur Erzeugung von Vakuum eingesetzt. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + OVEL_2017-05_8070875d1_DE.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/OVEL_2017-05_8070875d1_DE.pdf + + + + false + false + + + + + Manual_SPAE_EN + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8058480 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-03b + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Operating instructions Pressure sensor SPAE + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + The SPAE pressure sensor is intended for measuring the relative pressure in pneumatic applications. The SPAE converts pneumatic pressure values into a pressure proportional voltage. The measurement result is shown on the display. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_2017-03b_8058481d1_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_2017-03b_8058481d1_EN.pdf + + + + false + false + + + + + Manual_SPAE_DE + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8058480 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-03b + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Bedienungsanleitung Drucksensor SPAE + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + Der Drucksensor SPAE dient bestimmungsgemäß zur Erfassung des Relativdrucks in Pneumatikapplikationen. Der SPAE wandelt pneumatische Druckwerte in eine druckproportionale Spannung. Das Messergebnis wird im Display angezeigt. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_2017-03b_8058481d1_DE.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_2017-03b_8058481d1_DE.pdf + + + + false + false + + + + + ApplicationNote_SPAE_EN + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 1.10 + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Application Note IO-Link parameter description + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + A brief explanation of the contents (identification, parameter and commands, block parameterization, teach-In, process data, using different pressure units, diagnosis) + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + 09.02.2015 + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_100017_ApplNote.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_100017_ApplNote.pdf + + + + false + false + + + + + + Service + www.company.com/ids/sm/6053_5072_7091_5102 + + + https://www.hsu-hh.de/aut/aas/service + + + Instance + + + + + ContactInfo + PARAMETER + + + https://www.hsu-hh.de/aut/aas/contactinfo + + + Instance + + + + + NameOfSupplier + PARAMETER + + + 0173-1#02-AAO735#003 + + + Instance + + string + Festo AG & Co. KG + + + + + ContactInfo_Role + PARAMETER + + + https://www.hsu-hh.de/aut/aas/role + + + Instance + + string + Manufacturer + + + + + PhysicalAddress + PARAMETER + + + https://www.hsu-hh.de/aut/aas/physicaladdress + + + Instance + + + + + CountryCode + PARAMETER + + + 0173-1#02-AAO730#001 + + + Instance + + string + DE + + + + + Street + PARAMETER + + + 0173-1#02-AAO128#001 + + + Instance + + string + Ruiter Straße 82 + + + + + Zip + PARAMETER + + + 0173-1#02-AAO129#002 + + + Instance + + string + 73734 + + + + + CityTown + PARAMETER + + + 0173-1#02-AAO132#001 + + + Instance + + string + Esslingen-Berkheim + + + + + StateCounty + PARAMETER + + + 0173-1#02-AAO133#002 + + + Instance + + string + Baden-Württemberg + + + + false + false + + + + + Email + PARAMETER + + + https://www.hsu-hh.de/aut/aas/email + + + Instance + + string + technikservice@festo.com + + + + + URL + PARAMETER + + + 0173-1#02-AAO694#001 + + + Instance + + string + https://www.festo.com + + + + + PhoneNumber + PARAMETER + + + 0173-1#02-AAO136#002 + + + Instance + + string + +49711347-3000 + + + + + Fax + PARAMETER + + + https://www.hsu-hh.de/aut/aas/fax + + + Instance + + string + +49711 347-2190 + + + + false + false + + + + + + Identification + www.company.com/ids/sm/6563_5072_7091_4267 + + + https://www.hsu-hh.de/aut/aas/identification + + + Instance + + + + + ManufacturerName + PARAMETER + + + 0173-1#02-AAO677#002 + + + Instance + + string + Festo AG & Co. KG + + + + + GLNOfManufacturer + PARAMETER + + + 0173-1#02-AAY812#001 + + + Instance + + string + 2220000020640 + + + + + SupplierOfTheIdentifier + + + 0173-1#02-AAP796#004 + + + Instance + + + + + + + + MAN_PROD_NUM + + + 0173-1#02-AAO676#003 + + + Instance + + + + + + + + ManufacturerProductDesignation + PARAMETER + + + 0173-1#02-AAW338#001 + + + Instance + + string + OVEL Vacuum generator + + + + + ManufacturerProductDescription + PARAMETER + + + 0173-1#02-AAU734#001 + + + Instance + + langString + Compact vacuum generator with IO-Link sensor + + + + + NameOfSupplier + PARAMETER + + + 0173-1#02-AAO735#003 + + + Instance + + string + Festo AG & Co. KG + + + + + GLNOfSupplier + PARAMETER + + + 0173-1#02-AAY813#001 + + + Instance + + string + 2220000020640 + + + + + SupplierIdProvider + PARAMETER + + + https://www.hsu-hh.de/aut/aas/supplieridprovider + + + Instance + + + + + + + + SUP_PROD_NUM + PARAMETER + + + 0173-1#02-AAO736#004 + + + Instance + + + + + + + + SupplierProductDesignation + + + 0173-1#02-AAM551#002 + + + Instance + + string + OVEL Vacuum generator + + + + + SupplierProductDescription + PARAMETER + + + 0173-1#02-AAU730#001 + + + Instance + + langString + Compact vacuum generator with IO-Link sensor + + + + + ManufacturerProductFamily + PARAMETER + + + 0173-1#02-AAU731#001 + + + Instance + + string + OVEL-5-H-10-P-VQ4-UA-Z-C-A-V1PNLK-H3 + + + + + ClassificationSystem + PARAMETER + + + 0173-1#02-AAO715#002 + + + Instance + + string + eclass + + + + + SecondaryKeyTyp + + + https://www.hsu-hh.de/aut/aas/secondarykeytyp + + + Instance + + + + + + + + TypThumbnail + PARAMETER + + + https://www.hsu-hh.de/aut/aas/thumbnail + + + Instance + + image/jpeg + /Festo_OVEL_product_rendering.png + + + + + AssetId + PARAMETER + + + https://www.hsu-hh.de/aut/aas/assetid + + + Instance + + anyURI + HTTP://PK.FESTO.COM/3S7PM0CP4BD + + + + + SerialNumber + PARAMETER + + + 0173-1#02-AAM556#002 + + + Instance + + string + smart.festo.com/demo/aas/1/1/454576463545648365874 + + + + + BatchNumber + PARAMETER + + + 0173-1#02-AAQ196#001 + + + Instance + + + + + + + + SecondaryKeyInstance + PARAMETER + + + https://www.hsu-hh.de/aut/aas/secondarykeyinstance + + + Instance + + + + + + + + DateOfManufacture + PARAMETER + + + 0173-1#02-AAR972#002 + + + Instance + + date + + + + + + DeviceRevision + PARAMETER + + + https://www.hsu-hh.de/aut/aas/devicerevision + + + Instance + + + + + + + + SoftwareRevision + PARAMETER + + + https://www.hsu-hh.de/aut/aas/softwarerevision + + + Instance + + + + + + + + HardwareRevision + PARAMETER + + + https://www.hsu-hh.de/aut/aas/hardwarerevision + + + Instance + + + + + + + + ContactInfo + PARAMETER + + + https://www.hsu-hh.de/aut/aas/contactinfo + + + Instance + + + + + NameOfSupplier + PARAMETER + + + 0173-1#02-AAO735#003 + + + Instance + + string + Festo AG & Co. KG + + + + + ContactInfo_Role + PARAMETER + + + https://www.hsu-hh.de/aut/aas/role + + + Instance + + string + Manufacturer + + + + + PhysicalAddress + PARAMETER + + + https://www.hsu-hh.de/aut/aas/physicaladdress + + + Instance + + + + + CountryCode + PARAMETER + + + 0173-1#02-AAO730#001 + + + Instance + + string + DE + + + + + Street + PARAMETER + + + 0173-1#02-AAO128#001 + + + Instance + + langString + Ruiter Straße 82 + + + + + Zip + PARAMETER + + + 0173-1#02-AAO129#002 + + + Instance + + string + 73734 + + + + + CityTown + PARAMETER + + + 0173-1#02-AAO132#001 + + + Instance + + string + Esslingen-Berkheim + + + + + StateCounty + PARAMETER + + + 0173-1#02-AAO133#002 + + + Instance + + string + Baden-Württemberg + + + + false + false + + + + + Email + PARAMETER + + + https://www.hsu-hh.de/aut/aas/email + + + Instance + + string + technikservice@festo.com + + + + + URL + PARAMETER + + + 0173-1#02-AAO694#001 + + + Instance + + anyURI + https://www.festo.com + + + + + PhoneNumber + PARAMETER + + + 0173-1#02-AAO136#002 + + + Instance + + string + +49711347-3000 + + + + + Fax + PARAMETER + + + https://www.hsu-hh.de/aut/aas/fax + + + Instance + + string + +49711 347-2190 + + + + false + false + + + + + CompanyLogo + PARAMETER + + + https://www.hsu-hh.de/aut/aas/companylogo + + + Instance + + image/png + /aasx/assetIdentification/logo.png + + + + + URL + PARAMETER + + + 0173-1#02-AAO694#001 + + + Instance + + anyURI + https://pk.festo.com/3s7plfdrs35 + + + + + + DeviceDescriptionFiles + smart.festo.com/demo/sm/instance/1/1/13B7CCD9BF7A3F24 + + + http://admin-shell/sample/submodel/type/device-description-files + + + Instance + + + + + IODD + + + http://admin-shell.io/sample/conceptdescriptions/437857438753457473 + + + Instance + + application/general + /aasx/Software/Festo-SPAE-kPa-20171025-IODD1.1.zip + + + + + + + + ManufacturerName + 0173-1#02-AAO677#002 + + + + + + + + Herstellername + Manufacturer Name + + Manufacturer Name + + + + + Bezeichnung für eine natürliche oder juristische Person, die für die Auslegung, Herstellung und Verpackung sowie die Etikettierung eines Produkts im Hinblick auf das 'Inverkehrbringen' im eigenen Namen verantwortlich ist + legally valid designation of the natural or judicial person which is directly responsible for the design, production, packaging and labeling of a product in respect to its being brought into circulation + + + + + + + GLNOfManufacturer + 0173-1#02-AAY812#001 + + + + + + + + GLN of manufacturer + GLN des Herstellers + + GLN of manufacturer + + + + + international eindeutige Nummer für den Geräte- oder Produkthersteller sowie für den Standort + internationally unique identification number for the manufacturer of the device or the product and for the physical location + + + + + + + SupplierOfTheIdentifier + 0173-1#02-AAP796#004 + + + + + + + + Supplier of the identifier + Anbieter der Identifikationsnummer für Hersteller + + Supplier of the identifier + + + STRING_TRANSLATABLE + + DUNS-no., supplier number, or other number as identifier of an offeror or supplier of the identification + DUNS-Nr., Lieferantennummer oder andere Nummer zur Identifikation eines Anbieters bzw. Lieferanten der Identifikationsnummer + + + + + + + MAN_PROD_NUM + + product article number of manufacturer + + 0173-1#02-AAO676#003 + + + + + + + + product article number of manufacturer + Herstellerartikelnummer + + MAN_PROD_NUM + + + STRING_TRANSLATABLE + + eindeutiger Bestellschlüssel des Herstellers + unique product identifier of the manufacturer + + + + + + + ManufacturerProductDesignation + 0173-1#02-AAW338#001 + + + + + + + + Manufacturer product designation + Herstellerproduktbezeichnung + + ManufacturerTypName + + + STRING_TRANSLATABLE + + Kurze Beschreibung des Produktes (Kurztext) + Short description of the product (short text) + + + + + + + ManufacturerProductDescription + 0173-1#02-AAU734#001 + + + + + + + + Manufacturer product description + Herstellerproduktbeschreibung + + Manufacturer product description + + + + + Beschreibung des Produktes, seiner technischen Eigenschaften und ggf. seiner Anwendung (Langtext) + Description of the product, it's technical features and implementation if needed (long text) + + + + + + + NameOfSupplier + 0173-1#02-AAO735#003 + + + + + + + + + + + + name of supplier + Lieferantenname + + name of supplier + + + + + Name des Lieferanten, welcher dem Kunden ein Produkt oder eine Dienstleistung bereitstellt + name of supplier which provides the customer with a product or a service + + + + + + + GLNOfSupplier + 0173-1#02-AAY813#001 + + + + + + + + GLN of supplier + GLN des Lieferanten + + GLN of supplier + + + + + international eindeutige Nummer für den Geräte- oder Produktlieferanten sowie für den Standort + internationally unique identification number for the supplier of the device or the product and for the physical location + + + + + + + SupplierIdProvider + https://www.hsu-hh.de/aut/aas/supplieridprovider + + + + + + + + SupplierIdProvider + Anbieter der Identifikationsnummer + + SupplierIdProvider + + + STRING_TRANSLATABLE + + DUNS-Nr., Lieferantennummer oder andere Nummer zur Identifikation eines Anbieters bzw. Lieferanten der Identifikationsnummer + DUNS-no., supplier number, or other number as identifier of an offeror or supplier of the identification + + + + + + + SUP_PROD_NUM + 0173-1#02-AAO736#004 + + + + + + + + product article number of supplier + Lieferantenartikelnummer + + product article number of supplier + + + + + eindeutiger Bestellschlüssel des Lieferanten + unique product order identifier of the supplier + + + + + + + SupplierProductDesignation + 0173-1#02-AAM551#002 + + + + + + + + Supplier product designation + Lieferantenproduktbezeichnung + + SupplierTypName + + + STRING_TRANSLATABLE + + Kurze Beschreibung des Produktes (Kurztext) + Short description of the product (short text) + + + + + + + SupplierProductDescription + 0173-1#02-AAU730#001 + + + + + + + + Supplier product description + Lieferantenproduktbeschreibung + + Supplier product description + + + + + Beschreibung des Produktes, seiner technischen Eigenschaften und ggf. seiner Anwendung (Langtext) + Description of the product, it's technical features and implementation if needed (long text) + + + + + + + ManufacturerProductFamily + 0173-1#02-AAU731#001 + + + + + + + + Manufacturer product family + Herstellerproduktfamilie + + TypClass + + + + + 2. Ebene einer 3 stufigen herstellerspezifischen Produkthierarchie + 2nd level of a 3 level manufacturer specific product hierarchy + + + + + + + ClassificationSystem + 0173-1#02-AAO715#002 + + + + + + + + classification system + Klassifizierungssystem + + ClassificationSystem + + + + + Klassifizierungssystem + Classification System + + + + + + + SecondaryKeyTyp + https://www.hsu-hh.de/aut/aas/secondarykeytyp + + + + + + + + SecondaryKeyTyp + Typnummer des IT Systems + + SecondaryKeyTyp + + + + + Führende technische ID im IT System des Typs + SecondaryKeyTyp + + + + + + + TypThumbnail + https://www.hsu-hh.de/aut/aas/thumbnail + + + + + + + + TypThumbnail + Vorschaubild + + TypThumbnail + + + + + Darstellung des Produkttyps in kleinem Format + Small picture of the product type + + + + + + + AssetId + https://www.hsu-hh.de/aut/aas/assetid + + + + + + + + AssetId + Asset ID + + AssetId + + + + + Global eindeutige ID eines Asset, die machienenlesbar oder durch Menschen lesbar ist. + Global unique ID of an asset, which can be read by both human and machine. + + + + + + + SerialNumber + 0173-1#02-AAM556#002 + + + + + + + + Serial number + Seriennummer + + InstanceId + + + + + eindeutige Zahlen- und Buchstabenkombination mit der das Gerät nach seiner Herstellung identifiziert ist + unique combination of numbers and letters used to identify the device once it has been manufactured + + + + + + + BatchNumber + 0173-1#02-AAQ196#001 + + + + + + + + Batch number + Chargen-Nummer + + ChargeId + + + + + Eine vom Hersteller eines Stoffes vergebene Nummer zur Identifikation einer Charge + Number assigned by the manufacturer of a material to identify the manufacturer's batch + + + + + + + SecondaryKeyInstance + https://www.hsu-hh.de/aut/aas/secondarykeyinstance + + + + + + + + SecondaryKeyInstance + Instanznummer des IT Systems + + SecondaryKeyInstance + + + + + Führende technische ID im IT System der Instanz + SecondaryKeyInstance + + + + + + + DateOfManufacture + 0173-1#02-AAR972#002 + + + + + + + + Date of manufacture + Herstellungsdatum + + Date of manufacture + + + DATE + + Datum, ab der der Herstellungs- und/oder Entstehungsprozess abgeschlossen ist bzw. ab dem eine Dienstleistung vollständig erbracht ist + Date from which the production and / or development process is completed or from which a service is provided completely + + + + + + + DeviceRevision + https://www.hsu-hh.de/aut/aas/devicerevision + + + + + + + + DeviceRevision + DeviceRevision + + DeviceRevision + + + + + DeviceRevision + DeviceRevision + + + + + + + SoftwareRevision + https://www.hsu-hh.de/aut/aas/softwarerevision + + + + + + + + SoftwareRevision + SoftwareRevision + + SoftwareRevision + + + + + SoftwareRevision + SoftwareRevision + + + + + + + HardwareRevision + https://www.hsu-hh.de/aut/aas/hardwarerevision + + + + + + + + HardwareRevision + HardwareRevision + + HardwareRevision + + + + + HardwareRevision + HardwareRevision + + + + + + + QrCode + https://www.hsu-hh.de/aut/aas/qrcode + + + + + + + + QrCode + QrCode + + QrCode + + + + + In dem QRCode ist die URL, die die Instanz des Assets genau beschreibt, hinterlegt. + QrCode + + + + + + + OrganisationContactInfo + https://www.hsu-hh.de/aut/aas/contactinfo + + + + + + + + Contact Info + Kontakt Info + + OrganisationContactInfo + + + + + Sammlung für die allgemeinen Kontaktdaten + Collection for general contact data + + + + + + + PhysicalAddress + https://www.hsu-hh.de/aut/aas/physicaladdress + + + + + + + + PhysicalAddress + Physische Adresse + + PhysicalAddress + + + + + Sammlung für reale physische Adresse + Collection for real physical address + + + + + + + CountryCode + 0173-1#02-AAO730#001 + + + + + + + + + + + + Landeskennung + Country code + + Country code + + + + + Vereinbartes Merkmal zur eindeutigen Identifizierung eines Landes + agreed upon symbol for unambiguous identification of a country + + + + + + + Street + 0173-1#02-AAO128#001 + + + + + + + + Strasse + Street + + Street + + + + + Name der Strasse und Hausnummer + Street name and house number + + + + + + + Zip + 0173-1#02-AAO129#002 + + + + + + + + Zip + Postleitzahl + + PostalCode + + + + + ZIP code of address + Postleitzahl der Anschrift + + + + + + + CityTown + 0173-1#02-AAO132#001 + + + + + + + + Ort + City/town + + City/town + + + + + Town or city of the company + Ortsangabe + + + + + + + StateCounty + 0173-1#02-AAO133#002 + + + + + + + + state/county + Bundesland + + StateCounty + + + + + Bundesland + state/county + + + + + + + Email + https://www.hsu-hh.de/aut/aas/email + + + + + + + + Emailadresse + Email address + + Email + + + + + Emailadresse + Email address + + + + + + + TelephoneContact + https://www.hsu-hh.de/aut/aas/ContactInfo/TelephoneContact + + + + + + + + Telephone Contact + Telefonkontakt + + TelephoneContact + + + + + Sammlung für Kontaktdaten über Telefon + Collection for contact data via telephone + + + + + + + PhoneNumber + 0173-1#02-AAO136#002 + + + + + + + + Telefonnummer + telephone number + + Phone + + + + + vollständige Telefonnummer unter der ein Geschäftspartner erreichbar ist + complete telephone number to be called to reach a business partner + + + + + + + CompanyLogo + https://www.hsu-hh.de/aut/aas/companylogo + + + + + + + + Firmenlogo + CompanyLogo + + CompanyLogo + + + + + Firmenlogo + CompanyLogo + + + + + + + URL + 0173-1#02-AAO694#001 + + + + + + + + Internetadresse + Internet address + + URL + + + + + stated as link to a home page. The home page is the starting page or table of contents of a web site with offerings. It usually has the name index.htm or index.html + Angabe als Link, um in eine Homepage zu gelangen. die Homepage ist die Start- beziehungsweise die Inhaltsseite eines Web-Angebots. Meistens trägt sie den Namen index.htm oder index.html + + + + + + + ProductCountryOfOrigin + 0173-1#02-AAO841#001 + + + + + + + + Produkt Ursprungsland + Product country of origin + + CountryOfOrigin + + + + + Land in dem das Produkt hergestellt wurde (Hersteller Land) + Country in which the product is manufactured (manufacturer country) + + + + + + + YearOfConstruction + 0173-1#02-AAP906#001 + + + + + + + + Year of construction + Baujahr + + YearOfConstruction + + + + + Jahreszahl als Datumsangabe für die Fertigstellung des Objektes + Year as completion date of object + + + + + + + File + 0173-1#02-AAD005#008 + + + + www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360 + + + + + + Enthaltene Doku. Datei + Embedded Doc. file + + File + + + + + Verweis/ BLOB auf enthaltene Dokumentations-Datei. + Reference/ BLOB to embedded documentation file. + + + + + + + ProductMarking + https://www.hsu-hh.de/aut/aas/productmarking + + + + + + + + Produktkennzeichnung + Product Marking + + ProductMarking + + + + + Sammlungsdatei für Produktkennzeichnung + Collection file for product marking + + + + + + + CEQualificationPresent + 0173-1#02-BAF053#008 + + + + + + + + CE-Kennzeichnung vorhanden + CE- qualification present + + CEMarkingPresent + + + BOOLEAN + + whether CE- qualification is present + Angabe, ob CE-Kennzeichnung vorhanden ist + + + + + + + CRUUSLabelingPresent + 0173-1#02-AAR528#005 + + + + + + + + Kennzeichnung (RCM) vorhanden + RCM labeling present + + CRUUSLabelingPresent + + + BOOLEAN + + indication whether the product is equipped with a specified RCM labeling + Angabe, ob das Produkt mit einer spezifizierten RCM-Kennzeichnung ausgestattet ist + + + + + + + DocumentClassification_ClassId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + + + + Dokumentkategorie + Document category + + DocCategory + + + + + Dokumentkategorie nach VDI 2770:2018/10 + Document category after VDI 2770:2018/10 + + + + + + + DocumentId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + + + + + + DocumentId + Dokumenten-Nummer + + DocumentId + + + + + Die Dokument ID stellt eine eindeutige Identifizierung des Dokuments innerhalb einer Domäne sicher. + TBD + + + + + + + VDI2770_DomainId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + + + + + + Domain-Nummer + DomainId + + DomainId + + + + + Kennung oder Kennzeichen einer Domäne, in der eine DocumentId eineindeutig ist. + TBD + + + + + + + VDI2770_IdType + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + + + + + + Nummerntyp + IdType + + IdType + + + + + Besitzt ein Dokument mehrere Identifikationsnummern, muss mithilfe dieser Eigenschaft die führende ID angegeben werden. Der Wert „Primary“ ist für diese ID zu setzen. + TBD + + + + + + + ValString + www.company.com/ids/cd/4490_8182_7091_6124 + + + + + + + + Wert + Value String + + ValString + + + + + Ausdruck für den Wert der übergeordneten Collection. + Value string for the collection value on the next superordinate level + + + + + + + DocumentationItem + 0173-1#02-AAD001#001 + + + + + + + + Dokumentationsgruppe + Documentation item + + DocumentationItem + + + + + Gruppe von Merkmalen, die Zugriff gibt auf eine Dokumentation für ein Asset, beispielhaft struktuiert nach VDI 2770. + Collection of properties, which gives access to documentation of an asset, structured exemplary-wise according to VDI 2770. + + + + + + + DocumentIdDomain + www.company.com/ids/cd/6003_8182_7091_9350 + + + + + + + + DocumentIdDomain + DocumentIdDomain + + DocumentIdDomain + + + + + Angabe einer Liste von Domänen, in de-nen die DocumentIds des Dokuments eindeutig sind + TBD + + + + + + + DocumentDomainId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + + + + + + DocumentDomainId + DocumentDomainId + + DocumentDomainId + + + + + Kennung oder Kennzeichen einer Domäne + TBD + + + + + + + VDI2770_Party + www.company.com/ids/cd/3153_8182_7091_4327 + + + + + + + + Party + Party + + Party + + + + + Verweis auf eine Party (siehe VDI 2770 Anhang C1.17), die für diese Domäne verantwortlich ist + TBD + + + + + + + VDI2770_Role + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + + + + + + Rolle + Role + + Role + + + + + Festlegung einer Rolle für die Organisation gemäß der folgenden Auswahlliste: Author (Autor), Customer (Kunde), Supplier (Zulieferer, Anbieter), Manufacturer (Hersteller), Responsible (Verantwortlicher) + TBD + + + + + + + VDI2770_Organisation + www.company.com/ids/cd/9214_8182_7091_6391 + + + + + + + + Organisation + Organisation + + Organisation + + + + + Angabe einer Organisation + TBD + + + + + + + VDI2770_OrganisationId + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + + + + + + Organisation ID + Organisation ID + + OrganisationId + + + + + eindeutige ID für die Organisation + TBD + + + + + + + VDI2770_OrganisationName + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + + + + + + OrganisationName + OrganisationName + + OrganisationName + + + + + gebräuchliche Bezeichnung für die Organisation + TBD + + + + + + + VDI2770_OrganisationOfficialName + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + + + + + + Offizieller Name der Organisation + Organisation Official Name + + OrganisationOfficialName + + + + + offizieller Name der Organisation + TBD + + + + + + + DocumentPartId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + + + + + + Dokumenten-Teilnummer + DocumentPartId + + DocumentPartId + + + + + Ist das Dokument ein zusammengesetztes Dokument, können mithilfe dieser Eigenschaft eindeutige Dokumententeile IDs eingetragen werden, um das Dokument von den anderen Dokumenten zu unterscheiden. + TBD + + + + + + + VDI2770_Description + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + + + + + + Beschreibung + Description + + Description + + + + + Beschreibung für die nächste übergeordnete Collection + TBD + + + + + + + VDI2770_ClassName + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + + + + + + Klassenname + Class Name + + ClassName + + + + + Liste von sprachabhängigen Namen zur ClassId. Für die Klassennamen nach VDI 2770 müssen die Werte aus Tabelle 1 in Abschnitt 8.5 angewendet werden. + TBD + + + + + + + DocumentVersion_LanguageCode + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + + + + + + Sprachenschlüssel + LanguageCode + + LanguageCode + + + + + Angabe eines Sprachcodes gemäss ISO 639-1 oder -2 + TBD + + + + + + + VDI2770_ClassificationSystem + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + + + + + + Klassifizierungssystem + classification system + + ClassificationSystem + + + + + Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss „VDI2770:2018“ verwenden werden. + TBD + + + + + + + DocumentVersion + www.company.com/ids/cd/2580_0282_7091_6213 + + + + + + + + Dokumenten-Version + DocumentVersion + + DocumentVersion + + + + + Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden. + TBD + + + + + + + DocumentVersionId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + + + + + + Dokumenten-Versionsnummer + DocumentVersionId + + DocumentVersionId + + + + + Identifikationsnummer zur Dokumenten-version. Verweist ein Document (siehe Anhang C1.1, Eigenschaft DocumentVersion) auf diese Dokumentenversion, muss die Kombination aus DocumentId und DocumentVersionId eindeutig sein. + TBD + + + + + + + VDI2770_Language + www.company.com/ids/cd/0231_0282_7091_5062 + + + + + + + + Sprache + Language + + Language + + + + + Liste der im Dokument verwendeten Sprachen + TBD + + + + + + + DocumentVersion_Description + www.company.com/ids/cd/9151_0282_7091_8032 + + + + + + + + Beschreibung zur DocumentVersion + DocumentVersion Description + + DocumentVersion_Description + + + + + Zusammenfassende Beschreibungen zur Dokumentenversion in ggf. unterschiedlichen Sprachen. + TBD + + + + + + + VDI2770_Title + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + + + + + + Titel + Title + + VDI2770_Title + + + + + sprachabhängiger Titel des Dokuments + TBD + + + + + + + VDI2770_Summary + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + + + + + + Zusammenfassung + Summary + + Summary + + + + + sprachabhängige, aussagekräftige Zusammenfassung des Dokumenteninhalts + TBD + + + + + + + VDI2770_Keywords + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + + + + + + Schlagwörter + Keywords + + Keywords + + + + + sprachabhängige, durch Komma getrennte Liste von Schlagwörtern + TBD + + + + + + + VDI2770_LifeCycleStatus + www.company.com/ids/cd/0282_0282_7091_7878 + + + + + + + + Lebenszyklus Status + LifeCycleStatus + + LifeCycleStatus + + + + + Liste von Statusdefinitionen mit Bezug zum Dokumentenlebenszyklus inklusive der Angabe der Beteiligten und einem zugehörigen Zeitstempel + TBD + + + + + + + VDI2770_StatusValue + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + + + + + + Statuswert + StatusValue + + StatusValue + + + + + Jede Dokumentenversion stellt einen Zeitpunkt im Dokumentenlebenszyklus dar. Dieser Statuswert bezieht sich auf die Meilensteine im Dokumentenlebenszyklus. Für die Anwendung dieser Richtlinie sind die beiden folgenden Status zu verwenden. InReview (in Prüfung), Released (freigegeben) + TBD + + + + + + + VDI2770_SetDate + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + + + + + + Erstellungsdatum + Set Date + + SetDate + + + + + Datum und Uhrzeit, an dem der Status festgelegt wurde Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe DIN ISO 8601). + TBD + + + + + + + VDI2770_Purpose + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + + + + + + Zweck + Purpose + + Purpose + + + + + Hier kann ein Zweck zum Meilenstein angegeben werden, z. B. „zur Weiterleitung an den Kunden“. + TBD + + + + + + + VDI2770_BasedOnProcedure + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + + + + + + Prozedur + Procedure + + BasedOnProcedure + + + + + textueller Bezug auf ein Verfahren, das der Festlegung dieses Status zugrunde liegt + TBD + + + + + + + VDI2770_Comments + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + + + + + + Kommentar + Comments + + Comments + + + + + textuelle Bemerkungen und Anmerkungen zum Status + TBD + + + + + + + DocumentRelationship + www.company.com/ids/cd/1204_0282_7091_7896 + + + + + + + + Dokumenten-Beziehung + Document Relationship + + DocumentRelationship + + + + + Liste von Beziehungen zu anderen Dokumenten. Es ist möglich, auf einen Dokument, ein Dokument in einer spezifischen Dokumentenversion oder auch ein Teildokument zu verweisen. + TBD + + + + + + + DocumentRelationship_Type + www.company.com/ids/cd/5044_0282_7091_6924 + + + + + + + + Typ der Dokumenten-Beziehung + DocumentRelationship_Type + + DocumentRelationship_Type + + + + + Typisierung der Beziehung zwischen den beiden DocumentVersions. Folgende Beziehungsarten können verwendet werden: Affecting (hat Auswirkungen auf), ReferesTo (bezieht sich auf), BasedOn (basiert auf) + TBD + + + + + + + StoredDocumentRepresentation + www.company.com/ids/cd/3094_0282_7091_2090 + + + + + + + + StoredDocumentRepresentation + StoredDocumentRepresentation + + StoredDocumentRepresentation + + + + + Liste von digitalen Repräsentationen zur DocumentVersion + TBD + + + + + + + VDI2770_DigitalFile + www.company.com/ids/cd/2305_0282_7091_2077 + + + + + + + + Digitaler-File + DigitalFile + + DigitalFile + + + + + Datei, die die DocumentVersion (siehe VDI 2770:2018 Anhang C1.5) repräsentiert Neben der obligatorischen PDF/A-Datei können weitere Dateien angegeben werden. + TBD + + + + + + + VDI2770_FileId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + + + + + + ID der Datei + File ID + + FileId + + + + + eindeutige ID für die Datei + TBD + + + + + + + VDI2770_FileName + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + + + + + + Dateiname + File name + + FileName + + + + + Name der Datei inkl. einer Dateiendung (sofern vorhanden) Es ist nicht notwendig, einen Pfad für die Datei anzugeben. + TBD + + + + + + + VDI2770_FileFormat + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + + + + + + Datei Format + File format + + FileFormat + + + + + Angabe eines Media Typs gemäß der Liste der IANA + TBD + + + + + + + DocumentType + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + + + + + + Dokumententyp + Document Type + + DocumentType + + + + + Festlegung des Typs des Dokuments im Sinne der DIN EN 82045-1: a) Single (Einzeldokument) b) Aggregate (Sammeldokument) c) DocumentSet (Dokumentensatz) d) CompoundDoc (Mischdokument) + TBD + + + + + + + VDI2770_ReferencedObject + www.company.com/ids/cd/2570_2282_7091_0055 + + + + + + + + ReferencedObject + ReferencedObject + + ReferencedObject + + + + + Liste von IDs für ein Objekt, auf das sich das Dokument bezieht + TBD + + + + + + + VDI2770_ReferencedObject_Type + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + + + + + + Typ + Type + + Type + + + + + Für Type des Objekts muss immer Product angegeben werden. + TBD + + + + + + + VDI2770_ReferencedObject_RefType + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + + + + + + RefType + RefType + + RefType + + + + + Angabe einer Typisierung zur Kennung des technischen Objekts. Folgende Werte sind möglich, ProductId (Produktnummer), SerialId (Seriennummer) + TBD + + + + + + + VDI2770_ReferencedObject_ObjectId + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + + + + + + ObjectId + ObjectId + + ObjectId + + + + + Angabe der Identifikationsnummer zum Objekt + TBD + + + + + + + ContactInfo_Role + https://www.hsu-hh.de/aut/aas/role + + + + + + + + Rolle + Role + + Role + + + + + Angabe zur Spezifizierung der Rolle, die die Organisation aus ContactInfo einnimmt + Information to specify the role which the organisation of ContactInfo plays + + + + + + + Fax + https://www.hsu-hh.de/aut/aas/fax + + + + + + + + Fax + Fax + + Fax + + + + + Faxnummer + Fax number + + + + + + + 0173-1#02-AAO136#002 + + + + + DocGroup_01 + www.company.com/ids/cd/1420_0113_7091_0891 + + + + + + + + 01 Identifikation + 01 Identification + + DocGroup_01 + + + + + Der Gruppe „Identifikation“ werden alle Dokumente zugeordnet, die der Identifikation des Objekts dienen, zu dem die Herstellerdokumentation gehört. Sie enthält insbesondere Informationen, die die elektronische Datenverarbeitung unterstützen und die es dem Hersteller und dem Nutzer erlauben, das Objekt in ihren jeweiligen elektronischen Datenverarbeitungssystemen zu identifizieren. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocGroup_02 + www.company.com/ids/cd/4323_0113_7091_2591 + + + + + + + + 02 Technische Beschaffenheit + 02 Technical characteristics + + DocGroup_02 + + + + + Die Gruppe „Technische Beschaffenheit“ beinhaltet alle Dokumente, die die technischen Anforderungen, deren Erfüllung und die Bescheinigung der Eigenschaften eines Objekts betreffen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocGroup_03 + www.company.com/ids/cd/5053_0113_7091_5741 + + + + + + + + 03 Tätigkeitsbezogene Dokumente + 03 Work-related documents + + DocGroup_03 + + + + + Die Gruppe „Tätigkeitsbezogene Dokumente“ beinhaltet alle Dokumente, die Anforderungen, Hinweise und Hilfestellungen für Tätigkeiten an und mit dem Objekt nach der Übergabe an den Nutzer betreffen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocGroup_04 + www.company.com/ids/cd/5473_0113_7091_1588 + + + + + + + + 04 Vertragsunterlagen + 04 Contract documents + + DocGroup_04 + + + + + Der Gruppe „Vertragsunterlagen“ werden alle Dokumente zugeordnet, die im Zusammenhang mit der kaufmännischen Abwicklung eines Vertrages stehen, aber nicht selbst Gegenstand des Vertrags sind und lediglich zur Erfüllung des Vertrags dienen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_01-01 + www.company.com/ids/cd/9593_0113_7091_2401 + + + + + + + + 01-01 Identifikation + 01-01 Identification + + DocCategory_01-01 + + + + + Der Kategorie „Identifikation“ werden alle Dokumente zugeordnet, die der Identifikation des Objekts dienen, zu dem die Herstellerdokumentation gehört. Sie enthält insbesondere Informationen, die die elektronische Datenverarbeitung unterstützen und die es dem Hersteller und dem Nutzer erlauben, das Objekt in ihren jeweiligen elektronischen Datenverarbeitungssystemen zu identifizieren. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-01 + www.company.com/ids/cd/5314_0113_7091_8640 + + + + + + + + 02-01 Techn. Spezifikation + 02-01 Technical specification + + DocCategory_02-01 + + + + + Der Kategorie „Technische Spezifikation“ werden alle Dokumente zugeordnet, die die Anforderungen an ein Objekt sowie dessen Eigenschaften beschreiben. Dazu gehören die Auslegungsdaten, Berechnungen (Verfahrenstechnik, Festigkeit usw.) sowie alle relevanten Eigenschaften des übergebenen Objekts. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-02 + www.company.com/ids/cd/5515_0113_7091_8581 + + + + + + + + 02-02 Zeichnungen, Pläne + 02-02 Drawings and diagrams + + DocCategory_02-02 + + + + + Der Kategorie „Zeichnungen, Pläne“ werden alle Dokumente zugeordnet, die Zeichnungscharakter haben, das heißt eine grafische Darstellung zur Übermittlung von Information nutzen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-03 + www.company.com/ids/cd/0335_0113_7091_0312 + + + + + + + + 02-03 Bauteile + 02-03 Components + + DocCategory_02-03 + + + + + Der Kategorie „Bauteile“ werden alle Dokumente zugeordnet, die eine strukturierte Auflistung der Teile eines Objekts beinhalten. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-04 + www.company.com/ids/cd/2155_0113_7091_3955 + + + + + + + + 02-04 Zeugnisse, Zertifikate, Bescheinigungen + 02-04 Reports, Certificates, declarations + + DocCategory_02-04 + + + + + Der Kategorie „Zeugnisse, Zertifikate, Bescheinigungen“ werden alle Dokumente zugeordnet, die Urkundencharakter haben. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-01 + www.company.com/ids/cd/3565_0113_7091_2704 + + + + + + + + 03-01 Montage, Inbetriebnahme, Demontage + 03-01 Assembly, commissioning, disassembly + + DocCategory_03-01 + + + + + Der Kategorie „Montage, Demontage“ werden alle Dokumente zugeordnet, die Tätigkeiten und Maßnahmen beschreiben, die erforderlich sind, um ein Objekt: zu transportieren oder zu lagern, als Ganzes in ein übergeordnetes Objekt einzubauen, auszubauen oder an dieses anzuschließen, so weit vorzubereiten, dass es zur Inbetriebnahme bereitsteht, nach Abschluss der Nutzungsphase zu demontieren und zu entsorgen + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-02 + www.company.com/ids/cd/4290_1113_7091_7266 + + + + + + + + 03-02 Bedienung + 03-02 Operation + + DocCategory_03-02 + + + + + Der Kategorie „Bedienung“ werden Dokumente zur bestimmungsgemäßen Verwendung und sicheren Bedienung eines Objekts zugeordnet. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-03 + www.company.com/ids/cd/2211_1113_7091_3911 + + + + + + + + 03-03 Allgemeine Sicherheit + 03-03 Safety in general + + DocCategory_03-03 + + + + + Der Kategorie „Allgemeine Sicherheit“ werden Dokumente zugeordnet, die Sicherheitshinweise auf mögliche Gefährdungen bei der Verwendung des Objekts geben. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-04 + www.company.com/ids/cd/7521_1113_7091_4471 + + + + + + + + 03-04 Inspektion, Wartung, Prüfung + 03-04 Inspection, maintenance, test + + DocCategory_03-04 + + + + + Der Kategorie „Inspektion, Wartung, Prüfung“ werden alle Dokumente zugeordnet, die vom Hersteller vorgeschlagene wiederkehrende Maßnahmen zur Feststellung oder zum Erhalt des funktionsfähigen Zustands beschreiben. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-05 + www.company.com/ids/cd/5161_1113_7091_0458 + + + + + + + + 03-05 Instandsetzung + 03-05 Repair + + DocCategory_03-05 + + + + + Der Kategorie „Instandsetzung“ werden alle Dokumente zugeordnet, die Maßnahmen zur Wiederherstellung der Funktion eines Objekts betreffen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-06 + www.company.com/ids/cd/2181_1113_7091_5948 + + + + + + + + 03-06 Ersatzteile + 03-06 Spare parts + + DocCategory_03-06 + + + + + Der Kategorie „Ersatzteile“ werden Dokumente zugeordnet, die Informationen zu Ersatzteilen und Hilfs- und Betriebsstoffen enthalten. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_04-01 + www.company.com/ids/cd/5391_1113_7091_8996 + + + + + + + + 04-01 Vertragsunterlagen + 04-01 Contract documents + + DocCategory_04-01 + + + + + Der Kategorie „Vertragsunterlagen“ werden alle Dokumente zugeordnet, die im Zusammenhang mit der kaufmännischen Abwicklung eines Vertrages stehen, aber nicht selbst Gegenstand des Vertrags sind und lediglich zur Erfüllung des Vertrags dienen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/aas-environment.ts b/projects/aas-server/src/test/assets/aas-environment.ts new file mode 100644 index 00000000..ec37019a --- /dev/null +++ b/projects/aas-server/src/test/assets/aas-environment.ts @@ -0,0 +1,1489 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from "common/dist/types/index.js"; + +export default { + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassId" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassName" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassificationSystem" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationName" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationOfficialName" + }, + { + "idShort": "Title", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Title" + }, + { + "idShort": "Language", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Language" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/RotationSpeed" + }, + { + "idShort": "Torque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/Torque" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +} as any as aas.Environment \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/aas-example-v2.json b/projects/aas-server/src/test/assets/aas-example-v2.json new file mode 100644 index 00000000..b52089c4 --- /dev/null +++ b/projects/aas-server/src/test/assets/aas-example-v2.json @@ -0,0 +1,1636 @@ +{ + "assetAdministrationShells": [ + { + "asset": { + "keys": [ + { + "type": "Asset", + "local": true, + "value": "http://customer.com/assets/KHBVZJSQKIY", + "index": 0, + "idType": "IRI" + } + ] + }, + "submodels": [ + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "index": 0, + "idType": "IRI" + } + ] + } + ], + "conceptDictionaries": [], + "identification": { + "idType": "IRI", + "id": "http://customer.com/aas/9175_7013_7091_9168" + }, + "idShort": "ExampleMotor", + "category": "CONSTANT", + "modelType": { + "name": "AssetAdministrationShell" + } + } + ], + "assets": [ + { + "assetIdentificationModelRef": { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "i40.customer.com/type/1/1/F13E8576F6488342", + "index": 0, + "idType": "IRI" + } + ] + }, + "identification": { + "idType": "IRI", + "id": "http://customer.com/assets/KHBVZJSQKIY" + }, + "idShort": "ServoDCMotor", + "category": "", + "modelType": { + "name": "Asset" + }, + "kind": "Instance" + } + ], + "submodels": [ + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#01-ADN198#009", + "index": 0, + "idType": "IRDI" + } + ] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342" + }, + "idShort": "Identification", + "category": "CONSTANT", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "CUSTOMER GmbH", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAO677#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "Manufacturer", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "10101010", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAY812#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "GLN", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "integer" + } + }, + "kind": "Instance" + }, + { + "value": "I40 Capable Servo Motor (EN)", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAW338#001", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "ProductDesignation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "langString" + } + }, + "kind": "Instance" + }, + { + "value": "P12345678I40", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#02-AAM556#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "SerialNumber", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ] + }, + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#01-AFZ615#016", + "index": 0, + "idType": "IRDI" + } + ] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + }, + "idShort": "TechnicalData", + "category": "CONSTANT", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "5000", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAA120#008", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "MaxRotationSpeed", + "category": "PARAMETER", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "integer" + } + }, + "kind": "Instance" + }, + { + "value": "200", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAE098#004", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "MaxTorque", + "category": "PARAMETER", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "value": "BAB657", + "valueId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#07-BAB657#003 ", + "index": 0, + "idType": "IRDI" + } + ] + }, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-BAE122#006", + "index": 0, + "idType": "IRDI" + } + ] + }, + "constraints": [], + "idShort": "CoolingType", + "category": "PARAMETER", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ] + } + ] + }, + { + "semanticId": { + "keys": [] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + "idShort": "Documentation", + "category": "CONSTANT", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "ordered": false, + "allowDuplicates": false, + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "OperatingManual", + "category": "", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "3 608 870 A47", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "03-02", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentClassId", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Operation (EN) Bedienung (DE)", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentClassName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "langString" + } + }, + "kind": "Instance" + }, + { + "value": "VDI2770:2018", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DocumentClassificationSystem", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "CUSTOMER", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "OrganizationName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "CUSTOMER GmbH", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "OrganizationOfficialName", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Operating Manual Servo Motor", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "Title", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "langString" + } + }, + "kind": "Instance" + }, + { + "value": "en-US", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "Language", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "mimeType": "application/pdf", + "value": "/aasx/OperatingManual.pdf", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "idShort": "DigitalFile_PDF", + "category": "PARAMETER", + "modelType": { + "name": "File" + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ] + }, + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#01-AFZ615#016", + "index": 0, + "idType": "IRDI" + } + ] + }, + "qualifiers": [], + "identification": { + "idType": "IRI", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + }, + "idShort": "OperationalData", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "4370", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "hasDataSpecification": [], + "idShort": "RotationSpeed", + "category": "VARIABLE", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "integer" + } + }, + "kind": "Instance" + }, + { + "value": "117.4", + "semanticId": { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": [], + "hasDataSpecification": [], + "idShort": "Torque", + "category": "VARIABLE", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + } + ] + } + ], + "conceptDescriptions": [ + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + }, + "idShort": "Document", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "unit": "", + "sourceOfDefinition": "[ISO 15519-1:2010]", + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ] + } + } + ], + "descriptions": [] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + }, + "idShort": "DocumentIdValue", + "category": "CONSTANT", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ], + "unit": "", + "sourceOfDefinition": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + }, + "idShort": "DocumentClassId", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + }, + "idShort": "DocumentClassName", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ], + "unit": "", + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + }, + "idShort": "DocumentClassificationSystem", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + }, + "idShort": "OrganizationName", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + }, + "idShort": "OrganizationOfficialName", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ] + } + } + ], + "isCaseOf": [ + { + "keys": [ + { + "type": "ConceptDescription", + "local": true, + "value": "0173-1#02-AAO677#002", + "index": 0, + "idType": "IRDI" + } + ] + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion" + }, + "idShort": "DocumentVersion", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ], + "unit": "", + "dataType": "", + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + }, + "idShort": "Language", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + }, + "idShort": "Title", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ], + "unit": "", + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate" + }, + "idShort": "Date", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ], + "unit": "", + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val" + }, + "idShort": "DocumentVersionIdValue", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + }, + "idShort": "DigitalFile", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ], + "unit": "", + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#02-BAA120#008" + }, + "administration": { + "version": "", + "revision": "2" + }, + "idShort": "MaxRotationSpeed", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#05-AAA650#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ] + } + } + ], + "isCaseOf": [ + { + "keys": [] + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#02-BAE098#004" + }, + "idShort": "MaxTorque", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#05-AAA212#003", + "index": 0, + "idType": "IRDI" + } + ] + }, + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895" + }, + "idShort": "RotationSpeed", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "0173-1#05-AAA650#002", + "index": 0, + "idType": "IRDI" + } + ] + }, + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRI", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896" + }, + "idShort": "Torque", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "keys": [] + }, + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#02-BAE122#006" + }, + "idShort": "CoolingType", + "category": "PROPERTY", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "shortName": [], + "unit": "", + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ] + } + } + ] + }, + { + "identification": { + "idType": "IRDI", + "id": "0173-1#07-BAB657#003" + }, + "idShort": "BAB657", + "category": "VALUE", + "modelType": { + "name": "ConceptDescription" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360", + "index": 0, + "idType": "IRI" + } + ] + }, + "dataSpecificationContent": { + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "shortName": [], + "unit": "", + "dataType": "STRING", + "definition": [] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/aas-example.json b/projects/aas-server/src/test/assets/aas-example.json new file mode 100644 index 00000000..f9ba301b --- /dev/null +++ b/projects/aas-server/src/test/assets/aas-example.json @@ -0,0 +1,1263 @@ +{ + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "Title", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor" + }, + { + "idShort": "Language", + "modelType": "Property", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370" + }, + { + "idShort": "Torque", + "modelType": "Property", + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/aas-prefix-namespace.xml b/projects/aas-server/src/test/assets/aas-prefix-namespace.xml new file mode 100644 index 00000000..ac57a24b --- /dev/null +++ b/projects/aas-server/src/test/assets/aas-prefix-namespace.xml @@ -0,0 +1,8384 @@ + + + + + Festo_3S7PM0CP4BD + CONSTANT + smart.festo.com/demo/aas/1/1/454576463545648365874 + + + HTTP://PK.FESTO.COM/3S7PM0CP4BD + + + + + + www.company.com/ids/sm/4343_5072_7091_3242 + + + + + www.company.com/ids/sm/2543_5072_7091_2660 + + + + + www.company.com/ids/sm/6053_5072_7091_5102 + + + + + www.company.com/ids/sm/6563_5072_7091_4267 + + + + + smart.festo.com/demo/sm/instance/1/1/13B7CCD9BF7A3F24 + + + + + + + + + FPK_3s7plfdrs35 + + Festo OVEL Vacuum generator + Festo OVEL Vakuumsaugdüse + + HTTP://PK.FESTO.COM/3S7PM0CP4BD + Instance + + + + + Nameplate + www.company.com/ids/sm/4343_5072_7091_3242 + + + https://www.hsu-hh.de/aut/aas/nameplate + + + Instance + + + + + ManufacturerName + PARAMETER + + + 0173-1#02-AAO677#002 + + + Instance + + string + Festo AG & Co. KG + + + + + ManufacturerProductDesignation + PARAMETER + + + 0173-1#02-AAW338#001 + + + Instance + + string + OVEL Vacuum generator + + + + + PhysicalAddress + PARAMETER + + + https://www.hsu-hh.de/aut/aas/physicaladdress + + + Instance + + + + + CountryCode + PARAMETER + + + 0173-1#02-AAO730#001 + + + Instance + + string + DE + + + + + Street + PARAMETER + + + 0173-1#02-AAO128#001 + + + Instance + + string + Ruiter Straße 82 + + + + + Zip + PARAMETER + + + 0173-1#02-AAO129#002 + + + Instance + + string + 73734 + + + + + CityTown + PARAMETER + + + 0173-1#02-AAO132#001 + + + Instance + + string + Esslingen-Berkheim + + + + + StateCounty + PARAMETER + + + 0173-1#02-AAO133#002 + + + Instance + + string + Baden-Württemberg + + + + false + false + + + + + ManufacturerProductFamily + PARAMETER + + + 0173-1#02-AAU731#001 + + + Instance + + + OVEL-5-H-10-P-VQ4-UA-Z-C-A-V1PNLK-H3 + + + + + SerialNumber + PARAMETER + + + 0173-1#02-AAM556#002 + + + Instance + + string + JO43 + + + + + BatchNumber + PARAMETER + + + 0173-1#02-AAQ196#001 + + + Instance + + + + + + + + ProductCountryOfOrigin + PARAMETER + + + 0173-1#02-AAO841#001 + + + Instance + + string + DE + + + + + YearOfConstruction + PARAMETER + + + 0173-1#02-AAP906#001 + + + Instance + + integer + 2019 + + + + + Marking_CE + PARAMETER + + + https://www.hsu-hh.de/aut/aas/productmarking + + + Instance + + + + + CEQualificationPresent + PARAMETER + + + 0173-1#02-BAF053#008 + + + Instance + + boolean + 1 + + + 0173-1#07-CAA016#001 + + + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + image/png + /aasx/Nameplate/marking_ce.png + + + + false + false + + + + + Marking_CRUUS + PARAMETER + + + https://www.hsu-hh.de/aut/aas/productmarking + + + Instance + + + + + CRUUSLabelingPresent + PARAMETER + + + 0173-1#02-AAR528#005 + + + Instance + + boolean + 1 + + + 0173-1#07-CAA016#001 + + + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + image/png + /aasx/Nameplate/marking_cruus.jpg + + + + false + false + + + + + Marking_RCM + PARAMETER + + + https://www.hsu-hh.de/aut/aas/productmarking + + + Instance + + + + + RCMLabelingPresent + PARAMETER + + + 0173-1#02-AAR528#005 + + + Instance + + boolean + 1 + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + image/png + /aasx/Nameplate/marking_rcm.jpg + + + + false + false + + + + + + Document + www.company.com/ids/sm/2543_5072_7091_2660 + + + https://www.hsu-hh.de/aut/aas/document + + + Instance + + + + + DeclarationCEMarking + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Erklärung zur CE-Kennzeichnung bei Produkten der Festo AG & Co.KG + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + CE_Kennzeichnung_2016_de.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/CE_Kennzeichnung_2016_de.pdf + + + + false + false + + + + + DeclarationRoHS + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + RoHS 2011/65/EU und delegierte Fassung (EU) 2015/863 + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + RoHS_2011_65_EU_Konzern_Information_de.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/RoHS_2011_65_EU_Konzern_Information_de.pdf + + + + false + false + + + + + DeclarationCRUUS + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + UL + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Underwriter Laboratories LLC + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Certificate of compliance + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_UL_4531318_-_2_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_UL_4531318_-_2_EN.pdf + + + + false + false + + + + + DeclarationIOLink + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 02-04 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Zeugnisse, Zertifikate, Bescheinigungen + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Manufacturer's declaration of conformity + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + OVEL_IO_Link_5439356_-_3_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/OVEL_IO_Link_5439356_-_3_EN.pdf + + + + false + false + + + + + Manual_OVEL_EN + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8070874 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-05 + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Operating instructions Vacuum generator OVEL + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + The OVEL vacuum generator is used to generate a vacuum. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + OVEL_2017-05_8070876g1_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/OVEL_2017-05_8070876g1_EN.pdf + + + + false + false + + + + + Manual_OVEL_DE + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8070874 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-05 + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Bedienungsanleitung Vakuumsaugdüse OVEL + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + Die Vakuumsaugdüse OVEL wird bestimmungsgemäß zur Erzeugung von Vakuum eingesetzt. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + OVEL_2017-05_8070875d1_DE.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/OVEL_2017-05_8070875d1_DE.pdf + + + + false + false + + + + + Manual_SPAE_EN + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8058480 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-03b + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Operating instructions Pressure sensor SPAE + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + The SPAE pressure sensor is intended for measuring the relative pressure in pneumatic applications. The SPAE converts pneumatic pressure values into a pressure proportional voltage. The measurement result is shown on the display. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_2017-03b_8058481d1_EN.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_2017-03b_8058481d1_EN.pdf + + + + false + false + + + + + Manual_SPAE_DE + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + 8058480 + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 2017-03b + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + de + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Bedienungsanleitung Drucksensor SPAE + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + Der Drucksensor SPAE dient bestimmungsgemäß zur Erfassung des Relativdrucks in Pneumatikapplikationen. Der SPAE wandelt pneumatische Druckwerte in eine druckproportionale Spannung. Das Messergebnis wird im Display angezeigt. + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_2017-03b_8058481d1_DE.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_2017-03b_8058481d1_DE.pdf + + + + false + false + + + + + ApplicationNote_SPAE_EN + PARAMETER + + + 0173-1#02-AAD001#001 + + + Instance + + + + + DocumentType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + Instance + + string + Single + + + + + VDI2770_DomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + Instance + + + + + + + + VDI2770_IdType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + Instance + + string + Primary + + + + + DocumentId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + Instance + + + + + + + + DocumentDomainId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + Instance + + + + + + + + VDI2770_Role + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + Instance + + string + Responsible + + + + + VDI2770_OrganisationId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + Instance + + + + + + + + VDI2770_OrganisationName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + Instance + + string + Festo + + + + + VDI2770_OrganisationOfficialName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + Instance + + string + Festo AG & Co. KG + + + + + VDI2770_Description + PARAMETER + + Eine Beschreibung zur Dokumententeile ID. Da eine Sprachangabe nicht möglich ist, sollte die Sprache für dieses Metadatum vor der Lieferung abgestimmt werden. + + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + Instance + + + + + + + + DocumentPartId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + Instance + + + + + + + + DocumentClassification_ClassId + PARAMETER + + eindeutige ID der Klasse in einer Klassifikation + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + Instance + + string + 03-02 + + + + + VDI2770_ClassName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + Instance + + string + Bedienung + + + + + ClassificationSystem + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + Instance + + string + VDI2770:2018 + + + + + DocumentVersionId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + Instance + + + 1.10 + + + + + DocumentVersion_LanguageCode + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + Instance + + string + en + + + + + VDI2770_Title + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + Instance + + string + Application Note IO-Link parameter description + + + + + VDI2770_Summary + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + Instance + + + A brief explanation of the contents (identification, parameter and commands, block parameterization, teach-In, process data, using different pressure units, diagnosis) + + + + + VDI2770_Keywords + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + Instance + + + + + + + + VDI2770_StatusValue + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + Instance + + string + Released + + + + + VDI2770_SetDate + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + Instance + + + 09.02.2015 + + + + + VDI2770_Purpose + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + Instance + + + + + + + + VDI2770_BasedOnProcedure + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + Instance + + + + + + + + VDI2770_Comments + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + Instance + + + + + + + + VDI2770_ReferencedObject_Type + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + Instance + + string + Product + + + + + VDI2770_ReferencedObject_RefType + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + Instance + + + + + + + + VDI2770_ReferencedObject_ObjectId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + Instance + + + + + + + + VDI2770_FileId + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + Instance + + + + + + + + VDI2770_FileName + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + Instance + + string + SPAE_100017_ApplNote.pdf + + + + + VDI2770_FileFormat + PARAMETER + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + Instance + + string + application/pdf + + + + + File + PARAMETER + + + 0173-1#02-AAD005#008 + + + Instance + + application/pdf + /aasx/Document/SPAE_100017_ApplNote.pdf + + + + false + false + + + + + + Service + www.company.com/ids/sm/6053_5072_7091_5102 + + + https://www.hsu-hh.de/aut/aas/service + + + Instance + + + + + ContactInfo + PARAMETER + + + https://www.hsu-hh.de/aut/aas/contactinfo + + + Instance + + + + + NameOfSupplier + PARAMETER + + + 0173-1#02-AAO735#003 + + + Instance + + string + Festo AG & Co. KG + + + + + ContactInfo_Role + PARAMETER + + + https://www.hsu-hh.de/aut/aas/role + + + Instance + + string + Manufacturer + + + + + PhysicalAddress + PARAMETER + + + https://www.hsu-hh.de/aut/aas/physicaladdress + + + Instance + + + + + CountryCode + PARAMETER + + + 0173-1#02-AAO730#001 + + + Instance + + string + DE + + + + + Street + PARAMETER + + + 0173-1#02-AAO128#001 + + + Instance + + string + Ruiter Straße 82 + + + + + Zip + PARAMETER + + + 0173-1#02-AAO129#002 + + + Instance + + string + 73734 + + + + + CityTown + PARAMETER + + + 0173-1#02-AAO132#001 + + + Instance + + string + Esslingen-Berkheim + + + + + StateCounty + PARAMETER + + + 0173-1#02-AAO133#002 + + + Instance + + string + Baden-Württemberg + + + + false + false + + + + + Email + PARAMETER + + + https://www.hsu-hh.de/aut/aas/email + + + Instance + + string + technikservice@festo.com + + + + + URL + PARAMETER + + + 0173-1#02-AAO694#001 + + + Instance + + string + https://www.festo.com + + + + + PhoneNumber + PARAMETER + + + 0173-1#02-AAO136#002 + + + Instance + + string + +49711347-3000 + + + + + Fax + PARAMETER + + + https://www.hsu-hh.de/aut/aas/fax + + + Instance + + string + +49711 347-2190 + + + + false + false + + + + + + Identification + www.company.com/ids/sm/6563_5072_7091_4267 + + + https://www.hsu-hh.de/aut/aas/identification + + + Instance + + + + + ManufacturerName + PARAMETER + + + 0173-1#02-AAO677#002 + + + Instance + + string + Festo AG & Co. KG + + + + + GLNOfManufacturer + PARAMETER + + + 0173-1#02-AAY812#001 + + + Instance + + string + 2220000020640 + + + + + SupplierOfTheIdentifier + + + 0173-1#02-AAP796#004 + + + Instance + + + + + + + + MAN_PROD_NUM + + + 0173-1#02-AAO676#003 + + + Instance + + + + + + + + ManufacturerProductDesignation + PARAMETER + + + 0173-1#02-AAW338#001 + + + Instance + + string + OVEL Vacuum generator + + + + + ManufacturerProductDescription + PARAMETER + + + 0173-1#02-AAU734#001 + + + Instance + + langString + Compact vacuum generator with IO-Link sensor + + + + + NameOfSupplier + PARAMETER + + + 0173-1#02-AAO735#003 + + + Instance + + string + Festo AG & Co. KG + + + + + GLNOfSupplier + PARAMETER + + + 0173-1#02-AAY813#001 + + + Instance + + string + 2220000020640 + + + + + SupplierIdProvider + PARAMETER + + + https://www.hsu-hh.de/aut/aas/supplieridprovider + + + Instance + + + + + + + + SUP_PROD_NUM + PARAMETER + + + 0173-1#02-AAO736#004 + + + Instance + + + + + + + + SupplierProductDesignation + + + 0173-1#02-AAM551#002 + + + Instance + + string + OVEL Vacuum generator + + + + + SupplierProductDescription + PARAMETER + + + 0173-1#02-AAU730#001 + + + Instance + + langString + Compact vacuum generator with IO-Link sensor + + + + + ManufacturerProductFamily + PARAMETER + + + 0173-1#02-AAU731#001 + + + Instance + + string + OVEL-5-H-10-P-VQ4-UA-Z-C-A-V1PNLK-H3 + + + + + ClassificationSystem + PARAMETER + + + 0173-1#02-AAO715#002 + + + Instance + + string + eclass + + + + + SecondaryKeyTyp + + + https://www.hsu-hh.de/aut/aas/secondarykeytyp + + + Instance + + + + + + + + TypThumbnail + PARAMETER + + + https://www.hsu-hh.de/aut/aas/thumbnail + + + Instance + + image/jpeg + /Festo_OVEL_product_rendering.png + + + + + AssetId + PARAMETER + + + https://www.hsu-hh.de/aut/aas/assetid + + + Instance + + anyURI + HTTP://PK.FESTO.COM/3S7PM0CP4BD + + + + + SerialNumber + PARAMETER + + + 0173-1#02-AAM556#002 + + + Instance + + string + smart.festo.com/demo/aas/1/1/454576463545648365874 + + + + + BatchNumber + PARAMETER + + + 0173-1#02-AAQ196#001 + + + Instance + + + + + + + + SecondaryKeyInstance + PARAMETER + + + https://www.hsu-hh.de/aut/aas/secondarykeyinstance + + + Instance + + + + + + + + DateOfManufacture + PARAMETER + + + 0173-1#02-AAR972#002 + + + Instance + + date + + + + + + DeviceRevision + PARAMETER + + + https://www.hsu-hh.de/aut/aas/devicerevision + + + Instance + + + + + + + + SoftwareRevision + PARAMETER + + + https://www.hsu-hh.de/aut/aas/softwarerevision + + + Instance + + + + + + + + HardwareRevision + PARAMETER + + + https://www.hsu-hh.de/aut/aas/hardwarerevision + + + Instance + + + + + + + + ContactInfo + PARAMETER + + + https://www.hsu-hh.de/aut/aas/contactinfo + + + Instance + + + + + NameOfSupplier + PARAMETER + + + 0173-1#02-AAO735#003 + + + Instance + + string + Festo AG & Co. KG + + + + + ContactInfo_Role + PARAMETER + + + https://www.hsu-hh.de/aut/aas/role + + + Instance + + string + Manufacturer + + + + + PhysicalAddress + PARAMETER + + + https://www.hsu-hh.de/aut/aas/physicaladdress + + + Instance + + + + + CountryCode + PARAMETER + + + 0173-1#02-AAO730#001 + + + Instance + + string + DE + + + + + Street + PARAMETER + + + 0173-1#02-AAO128#001 + + + Instance + + langString + Ruiter Straße 82 + + + + + Zip + PARAMETER + + + 0173-1#02-AAO129#002 + + + Instance + + string + 73734 + + + + + CityTown + PARAMETER + + + 0173-1#02-AAO132#001 + + + Instance + + string + Esslingen-Berkheim + + + + + StateCounty + PARAMETER + + + 0173-1#02-AAO133#002 + + + Instance + + string + Baden-Württemberg + + + + false + false + + + + + Email + PARAMETER + + + https://www.hsu-hh.de/aut/aas/email + + + Instance + + string + technikservice@festo.com + + + + + URL + PARAMETER + + + 0173-1#02-AAO694#001 + + + Instance + + anyURI + https://www.festo.com + + + + + PhoneNumber + PARAMETER + + + 0173-1#02-AAO136#002 + + + Instance + + string + +49711347-3000 + + + + + Fax + PARAMETER + + + https://www.hsu-hh.de/aut/aas/fax + + + Instance + + string + +49711 347-2190 + + + + false + false + + + + + CompanyLogo + PARAMETER + + + https://www.hsu-hh.de/aut/aas/companylogo + + + Instance + + image/png + /aasx/assetIdentification/logo.png + + + + + URL + PARAMETER + + + 0173-1#02-AAO694#001 + + + Instance + + anyURI + https://pk.festo.com/3s7plfdrs35 + + + + + + DeviceDescriptionFiles + smart.festo.com/demo/sm/instance/1/1/13B7CCD9BF7A3F24 + + + http://admin-shell/sample/submodel/type/device-description-files + + + Instance + + + + + IODD + + + http://admin-shell.io/sample/conceptdescriptions/437857438753457473 + + + Instance + + application/general + /aasx/Software/Festo-SPAE-kPa-20171025-IODD1.1.zip + + + + + + + + ManufacturerName + 0173-1#02-AAO677#002 + + + + + + + + Herstellername + Manufacturer Name + + Manufacturer Name + + + + + Bezeichnung für eine natürliche oder juristische Person, die für die Auslegung, Herstellung und Verpackung sowie die Etikettierung eines Produkts im Hinblick auf das 'Inverkehrbringen' im eigenen Namen verantwortlich ist + legally valid designation of the natural or judicial person which is directly responsible for the design, production, packaging and labeling of a product in respect to its being brought into circulation + + + + + + + GLNOfManufacturer + 0173-1#02-AAY812#001 + + + + + + + + GLN of manufacturer + GLN des Herstellers + + GLN of manufacturer + + + + + international eindeutige Nummer für den Geräte- oder Produkthersteller sowie für den Standort + internationally unique identification number for the manufacturer of the device or the product and for the physical location + + + + + + + SupplierOfTheIdentifier + 0173-1#02-AAP796#004 + + + + + + + + Supplier of the identifier + Anbieter der Identifikationsnummer für Hersteller + + Supplier of the identifier + + + STRING_TRANSLATABLE + + DUNS-no., supplier number, or other number as identifier of an offeror or supplier of the identification + DUNS-Nr., Lieferantennummer oder andere Nummer zur Identifikation eines Anbieters bzw. Lieferanten der Identifikationsnummer + + + + + + + MAN_PROD_NUM + + product article number of manufacturer + + 0173-1#02-AAO676#003 + + + + + + + + product article number of manufacturer + Herstellerartikelnummer + + MAN_PROD_NUM + + + STRING_TRANSLATABLE + + eindeutiger Bestellschlüssel des Herstellers + unique product identifier of the manufacturer + + + + + + + ManufacturerProductDesignation + 0173-1#02-AAW338#001 + + + + + + + + Manufacturer product designation + Herstellerproduktbezeichnung + + ManufacturerTypName + + + STRING_TRANSLATABLE + + Kurze Beschreibung des Produktes (Kurztext) + Short description of the product (short text) + + + + + + + ManufacturerProductDescription + 0173-1#02-AAU734#001 + + + + + + + + Manufacturer product description + Herstellerproduktbeschreibung + + Manufacturer product description + + + + + Beschreibung des Produktes, seiner technischen Eigenschaften und ggf. seiner Anwendung (Langtext) + Description of the product, it's technical features and implementation if needed (long text) + + + + + + + NameOfSupplier + 0173-1#02-AAO735#003 + + + + + + + + + + + + name of supplier + Lieferantenname + + name of supplier + + + + + Name des Lieferanten, welcher dem Kunden ein Produkt oder eine Dienstleistung bereitstellt + name of supplier which provides the customer with a product or a service + + + + + + + GLNOfSupplier + 0173-1#02-AAY813#001 + + + + + + + + GLN of supplier + GLN des Lieferanten + + GLN of supplier + + + + + international eindeutige Nummer für den Geräte- oder Produktlieferanten sowie für den Standort + internationally unique identification number for the supplier of the device or the product and for the physical location + + + + + + + SupplierIdProvider + https://www.hsu-hh.de/aut/aas/supplieridprovider + + + + + + + + SupplierIdProvider + Anbieter der Identifikationsnummer + + SupplierIdProvider + + + STRING_TRANSLATABLE + + DUNS-Nr., Lieferantennummer oder andere Nummer zur Identifikation eines Anbieters bzw. Lieferanten der Identifikationsnummer + DUNS-no., supplier number, or other number as identifier of an offeror or supplier of the identification + + + + + + + SUP_PROD_NUM + 0173-1#02-AAO736#004 + + + + + + + + product article number of supplier + Lieferantenartikelnummer + + product article number of supplier + + + + + eindeutiger Bestellschlüssel des Lieferanten + unique product order identifier of the supplier + + + + + + + SupplierProductDesignation + 0173-1#02-AAM551#002 + + + + + + + + Supplier product designation + Lieferantenproduktbezeichnung + + SupplierTypName + + + STRING_TRANSLATABLE + + Kurze Beschreibung des Produktes (Kurztext) + Short description of the product (short text) + + + + + + + SupplierProductDescription + 0173-1#02-AAU730#001 + + + + + + + + Supplier product description + Lieferantenproduktbeschreibung + + Supplier product description + + + + + Beschreibung des Produktes, seiner technischen Eigenschaften und ggf. seiner Anwendung (Langtext) + Description of the product, it's technical features and implementation if needed (long text) + + + + + + + ManufacturerProductFamily + 0173-1#02-AAU731#001 + + + + + + + + Manufacturer product family + Herstellerproduktfamilie + + TypClass + + + + + 2. Ebene einer 3 stufigen herstellerspezifischen Produkthierarchie + 2nd level of a 3 level manufacturer specific product hierarchy + + + + + + + ClassificationSystem + 0173-1#02-AAO715#002 + + + + + + + + classification system + Klassifizierungssystem + + ClassificationSystem + + + + + Klassifizierungssystem + Classification System + + + + + + + SecondaryKeyTyp + https://www.hsu-hh.de/aut/aas/secondarykeytyp + + + + + + + + SecondaryKeyTyp + Typnummer des IT Systems + + SecondaryKeyTyp + + + + + Führende technische ID im IT System des Typs + SecondaryKeyTyp + + + + + + + TypThumbnail + https://www.hsu-hh.de/aut/aas/thumbnail + + + + + + + + TypThumbnail + Vorschaubild + + TypThumbnail + + + + + Darstellung des Produkttyps in kleinem Format + Small picture of the product type + + + + + + + AssetId + https://www.hsu-hh.de/aut/aas/assetid + + + + + + + + AssetId + Asset ID + + AssetId + + + + + Global eindeutige ID eines Asset, die machienenlesbar oder durch Menschen lesbar ist. + Global unique ID of an asset, which can be read by both human and machine. + + + + + + + SerialNumber + 0173-1#02-AAM556#002 + + + + + + + + Serial number + Seriennummer + + InstanceId + + + + + eindeutige Zahlen- und Buchstabenkombination mit der das Gerät nach seiner Herstellung identifiziert ist + unique combination of numbers and letters used to identify the device once it has been manufactured + + + + + + + BatchNumber + 0173-1#02-AAQ196#001 + + + + + + + + Batch number + Chargen-Nummer + + ChargeId + + + + + Eine vom Hersteller eines Stoffes vergebene Nummer zur Identifikation einer Charge + Number assigned by the manufacturer of a material to identify the manufacturer's batch + + + + + + + SecondaryKeyInstance + https://www.hsu-hh.de/aut/aas/secondarykeyinstance + + + + + + + + SecondaryKeyInstance + Instanznummer des IT Systems + + SecondaryKeyInstance + + + + + Führende technische ID im IT System der Instanz + SecondaryKeyInstance + + + + + + + DateOfManufacture + 0173-1#02-AAR972#002 + + + + + + + + Date of manufacture + Herstellungsdatum + + Date of manufacture + + + DATE + + Datum, ab der der Herstellungs- und/oder Entstehungsprozess abgeschlossen ist bzw. ab dem eine Dienstleistung vollständig erbracht ist + Date from which the production and / or development process is completed or from which a service is provided completely + + + + + + + DeviceRevision + https://www.hsu-hh.de/aut/aas/devicerevision + + + + + + + + DeviceRevision + DeviceRevision + + DeviceRevision + + + + + DeviceRevision + DeviceRevision + + + + + + + SoftwareRevision + https://www.hsu-hh.de/aut/aas/softwarerevision + + + + + + + + SoftwareRevision + SoftwareRevision + + SoftwareRevision + + + + + SoftwareRevision + SoftwareRevision + + + + + + + HardwareRevision + https://www.hsu-hh.de/aut/aas/hardwarerevision + + + + + + + + HardwareRevision + HardwareRevision + + HardwareRevision + + + + + HardwareRevision + HardwareRevision + + + + + + + QrCode + https://www.hsu-hh.de/aut/aas/qrcode + + + + + + + + QrCode + QrCode + + QrCode + + + + + In dem QRCode ist die URL, die die Instanz des Assets genau beschreibt, hinterlegt. + QrCode + + + + + + + OrganisationContactInfo + https://www.hsu-hh.de/aut/aas/contactinfo + + + + + + + + Contact Info + Kontakt Info + + OrganisationContactInfo + + + + + Sammlung für die allgemeinen Kontaktdaten + Collection for general contact data + + + + + + + PhysicalAddress + https://www.hsu-hh.de/aut/aas/physicaladdress + + + + + + + + PhysicalAddress + Physische Adresse + + PhysicalAddress + + + + + Sammlung für reale physische Adresse + Collection for real physical address + + + + + + + CountryCode + 0173-1#02-AAO730#001 + + + + + + + + + + + + Landeskennung + Country code + + Country code + + + + + Vereinbartes Merkmal zur eindeutigen Identifizierung eines Landes + agreed upon symbol for unambiguous identification of a country + + + + + + + Street + 0173-1#02-AAO128#001 + + + + + + + + Strasse + Street + + Street + + + + + Name der Strasse und Hausnummer + Street name and house number + + + + + + + Zip + 0173-1#02-AAO129#002 + + + + + + + + Zip + Postleitzahl + + PostalCode + + + + + ZIP code of address + Postleitzahl der Anschrift + + + + + + + CityTown + 0173-1#02-AAO132#001 + + + + + + + + Ort + City/town + + City/town + + + + + Town or city of the company + Ortsangabe + + + + + + + StateCounty + 0173-1#02-AAO133#002 + + + + + + + + state/county + Bundesland + + StateCounty + + + + + Bundesland + state/county + + + + + + + Email + https://www.hsu-hh.de/aut/aas/email + + + + + + + + Emailadresse + Email address + + Email + + + + + Emailadresse + Email address + + + + + + + TelephoneContact + https://www.hsu-hh.de/aut/aas/ContactInfo/TelephoneContact + + + + + + + + Telephone Contact + Telefonkontakt + + TelephoneContact + + + + + Sammlung für Kontaktdaten über Telefon + Collection for contact data via telephone + + + + + + + PhoneNumber + 0173-1#02-AAO136#002 + + + + + + + + Telefonnummer + telephone number + + Phone + + + + + vollständige Telefonnummer unter der ein Geschäftspartner erreichbar ist + complete telephone number to be called to reach a business partner + + + + + + + CompanyLogo + https://www.hsu-hh.de/aut/aas/companylogo + + + + + + + + Firmenlogo + CompanyLogo + + CompanyLogo + + + + + Firmenlogo + CompanyLogo + + + + + + + URL + 0173-1#02-AAO694#001 + + + + + + + + Internetadresse + Internet address + + URL + + + + + stated as link to a home page. The home page is the starting page or table of contents of a web site with offerings. It usually has the name index.htm or index.html + Angabe als Link, um in eine Homepage zu gelangen. die Homepage ist die Start- beziehungsweise die Inhaltsseite eines Web-Angebots. Meistens trägt sie den Namen index.htm oder index.html + + + + + + + ProductCountryOfOrigin + 0173-1#02-AAO841#001 + + + + + + + + Produkt Ursprungsland + Product country of origin + + CountryOfOrigin + + + + + Land in dem das Produkt hergestellt wurde (Hersteller Land) + Country in which the product is manufactured (manufacturer country) + + + + + + + YearOfConstruction + 0173-1#02-AAP906#001 + + + + + + + + Year of construction + Baujahr + + YearOfConstruction + + + + + Jahreszahl als Datumsangabe für die Fertigstellung des Objektes + Year as completion date of object + + + + + + + File + 0173-1#02-AAD005#008 + + + + www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360 + + + + + + Enthaltene Doku. Datei + Embedded Doc. file + + File + + + + + Verweis/ BLOB auf enthaltene Dokumentations-Datei. + Reference/ BLOB to embedded documentation file. + + + + + + + ProductMarking + https://www.hsu-hh.de/aut/aas/productmarking + + + + + + + + Produktkennzeichnung + Product Marking + + ProductMarking + + + + + Sammlungsdatei für Produktkennzeichnung + Collection file for product marking + + + + + + + CEQualificationPresent + 0173-1#02-BAF053#008 + + + + + + + + CE-Kennzeichnung vorhanden + CE- qualification present + + CEMarkingPresent + + + BOOLEAN + + whether CE- qualification is present + Angabe, ob CE-Kennzeichnung vorhanden ist + + + + + + + CRUUSLabelingPresent + 0173-1#02-AAR528#005 + + + + + + + + Kennzeichnung (RCM) vorhanden + RCM labeling present + + CRUUSLabelingPresent + + + BOOLEAN + + indication whether the product is equipped with a specified RCM labeling + Angabe, ob das Produkt mit einer spezifizierten RCM-Kennzeichnung ausgestattet ist + + + + + + + DocumentClassification_ClassId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + + + + Dokumentkategorie + Document category + + DocCategory + + + + + Dokumentkategorie nach VDI 2770:2018/10 + Document category after VDI 2770:2018/10 + + + + + + + DocumentId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId + + + + + + + + DocumentId + Dokumenten-Nummer + + DocumentId + + + + + Die Dokument ID stellt eine eindeutige Identifizierung des Dokuments innerhalb einer Domäne sicher. + TBD + + + + + + + VDI2770_DomainId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/DomainId + + + + + + + + Domain-Nummer + DomainId + + DomainId + + + + + Kennung oder Kennzeichen einer Domäne, in der eine DocumentId eineindeutig ist. + TBD + + + + + + + VDI2770_IdType + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentId/IdType + + + + + + + + Nummerntyp + IdType + + IdType + + + + + Besitzt ein Dokument mehrere Identifikationsnummern, muss mithilfe dieser Eigenschaft die führende ID angegeben werden. Der Wert „Primary“ ist für diese ID zu setzen. + TBD + + + + + + + ValString + www.company.com/ids/cd/4490_8182_7091_6124 + + + + + + + + Wert + Value String + + ValString + + + + + Ausdruck für den Wert der übergeordneten Collection. + Value string for the collection value on the next superordinate level + + + + + + + DocumentationItem + 0173-1#02-AAD001#001 + + + + + + + + Dokumentationsgruppe + Documentation item + + DocumentationItem + + + + + Gruppe von Merkmalen, die Zugriff gibt auf eine Dokumentation für ein Asset, beispielhaft struktuiert nach VDI 2770. + Collection of properties, which gives access to documentation of an asset, structured exemplary-wise according to VDI 2770. + + + + + + + DocumentIdDomain + www.company.com/ids/cd/6003_8182_7091_9350 + + + + + + + + DocumentIdDomain + DocumentIdDomain + + DocumentIdDomain + + + + + Angabe einer Liste von Domänen, in de-nen die DocumentIds des Dokuments eindeutig sind + TBD + + + + + + + DocumentDomainId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentIdDomain/DocumentDomainId + + + + + + + + DocumentDomainId + DocumentDomainId + + DocumentDomainId + + + + + Kennung oder Kennzeichen einer Domäne + TBD + + + + + + + VDI2770_Party + www.company.com/ids/cd/3153_8182_7091_4327 + + + + + + + + Party + Party + + Party + + + + + Verweis auf eine Party (siehe VDI 2770 Anhang C1.17), die für diese Domäne verantwortlich ist + TBD + + + + + + + VDI2770_Role + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Role + + + + + + + + Rolle + Role + + Role + + + + + Festlegung einer Rolle für die Organisation gemäß der folgenden Auswahlliste: Author (Autor), Customer (Kunde), Supplier (Zulieferer, Anbieter), Manufacturer (Hersteller), Responsible (Verantwortlicher) + TBD + + + + + + + VDI2770_Organisation + www.company.com/ids/cd/9214_8182_7091_6391 + + + + + + + + Organisation + Organisation + + Organisation + + + + + Angabe einer Organisation + TBD + + + + + + + VDI2770_OrganisationId + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationId + + + + + + + + Organisation ID + Organisation ID + + OrganisationId + + + + + eindeutige ID für die Organisation + TBD + + + + + + + VDI2770_OrganisationName + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationName + + + + + + + + OrganisationName + OrganisationName + + OrganisationName + + + + + gebräuchliche Bezeichnung für die Organisation + TBD + + + + + + + VDI2770_OrganisationOfficialName + http://www.vdi.de/2770/AssetDocumentation/Document/Party/Organisation/OrganisationOfficialName + + + + + + + + Offizieller Name der Organisation + Organisation Official Name + + OrganisationOfficialName + + + + + offizieller Name der Organisation + TBD + + + + + + + DocumentPartId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentPartId + + + + + + + + Dokumenten-Teilnummer + DocumentPartId + + DocumentPartId + + + + + Ist das Dokument ein zusammengesetztes Dokument, können mithilfe dieser Eigenschaft eindeutige Dokumententeile IDs eingetragen werden, um das Dokument von den anderen Dokumenten zu unterscheiden. + TBD + + + + + + + VDI2770_Description + http://www.vdi.de/2770/AssetDocumentation/Document/Description + + + + + + + + Beschreibung + Description + + Description + + + + + Beschreibung für die nächste übergeordnete Collection + TBD + + + + + + + VDI2770_ClassName + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassName + + + + + + + + Klassenname + Class Name + + ClassName + + + + + Liste von sprachabhängigen Namen zur ClassId. Für die Klassennamen nach VDI 2770 müssen die Werte aus Tabelle 1 in Abschnitt 8.5 angewendet werden. + TBD + + + + + + + DocumentVersion_LanguageCode + http://www.vdi.de/2770/AssetDocumentation/Document/LanguageCode + + + + + + + + Sprachenschlüssel + LanguageCode + + LanguageCode + + + + + Angabe eines Sprachcodes gemäss ISO 639-1 oder -2 + TBD + + + + + + + VDI2770_ClassificationSystem + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassificationSystem + + + + + + + + Klassifizierungssystem + classification system + + ClassificationSystem + + + + + Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss „VDI2770:2018“ verwenden werden. + TBD + + + + + + + DocumentVersion + www.company.com/ids/cd/2580_0282_7091_6213 + + + + + + + + Dokumenten-Version + DocumentVersion + + DocumentVersion + + + + + Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden. + TBD + + + + + + + DocumentVersionId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersionId + + + + + + + + Dokumenten-Versionsnummer + DocumentVersionId + + DocumentVersionId + + + + + Identifikationsnummer zur Dokumenten-version. Verweist ein Document (siehe Anhang C1.1, Eigenschaft DocumentVersion) auf diese Dokumentenversion, muss die Kombination aus DocumentId und DocumentVersionId eindeutig sein. + TBD + + + + + + + VDI2770_Language + www.company.com/ids/cd/0231_0282_7091_5062 + + + + + + + + Sprache + Language + + Language + + + + + Liste der im Dokument verwendeten Sprachen + TBD + + + + + + + DocumentVersion_Description + www.company.com/ids/cd/9151_0282_7091_8032 + + + + + + + + Beschreibung zur DocumentVersion + DocumentVersion Description + + DocumentVersion_Description + + + + + Zusammenfassende Beschreibungen zur Dokumentenversion in ggf. unterschiedlichen Sprachen. + TBD + + + + + + + VDI2770_Title + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Title + + + + + + + + Titel + Title + + VDI2770_Title + + + + + sprachabhängiger Titel des Dokuments + TBD + + + + + + + VDI2770_Summary + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Summary + + + + + + + + Zusammenfassung + Summary + + Summary + + + + + sprachabhängige, aussagekräftige Zusammenfassung des Dokumenteninhalts + TBD + + + + + + + VDI2770_Keywords + http://www.vdi.de/2770/AssetDocumentation/Document/Description/Keywords + + + + + + + + Schlagwörter + Keywords + + Keywords + + + + + sprachabhängige, durch Komma getrennte Liste von Schlagwörtern + TBD + + + + + + + VDI2770_LifeCycleStatus + www.company.com/ids/cd/0282_0282_7091_7878 + + + + + + + + Lebenszyklus Status + LifeCycleStatus + + LifeCycleStatus + + + + + Liste von Statusdefinitionen mit Bezug zum Dokumentenlebenszyklus inklusive der Angabe der Beteiligten und einem zugehörigen Zeitstempel + TBD + + + + + + + VDI2770_StatusValue + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/StatusValue + + + + + + + + Statuswert + StatusValue + + StatusValue + + + + + Jede Dokumentenversion stellt einen Zeitpunkt im Dokumentenlebenszyklus dar. Dieser Statuswert bezieht sich auf die Meilensteine im Dokumentenlebenszyklus. Für die Anwendung dieser Richtlinie sind die beiden folgenden Status zu verwenden. InReview (in Prüfung), Released (freigegeben) + TBD + + + + + + + VDI2770_SetDate + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/SetDate + + + + + + + + Erstellungsdatum + Set Date + + SetDate + + + + + Datum und Uhrzeit, an dem der Status festgelegt wurde Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe DIN ISO 8601). + TBD + + + + + + + VDI2770_Purpose + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Purpose + + + + + + + + Zweck + Purpose + + Purpose + + + + + Hier kann ein Zweck zum Meilenstein angegeben werden, z. B. „zur Weiterleitung an den Kunden“. + TBD + + + + + + + VDI2770_BasedOnProcedure + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/BasedOnProcedure + + + + + + + + Prozedur + Procedure + + BasedOnProcedure + + + + + textueller Bezug auf ein Verfahren, das der Festlegung dieses Status zugrunde liegt + TBD + + + + + + + VDI2770_Comments + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/LifeCycleStatus/Comments + + + + + + + + Kommentar + Comments + + Comments + + + + + textuelle Bemerkungen und Anmerkungen zum Status + TBD + + + + + + + DocumentRelationship + www.company.com/ids/cd/1204_0282_7091_7896 + + + + + + + + Dokumenten-Beziehung + Document Relationship + + DocumentRelationship + + + + + Liste von Beziehungen zu anderen Dokumenten. Es ist möglich, auf einen Dokument, ein Dokument in einer spezifischen Dokumentenversion oder auch ein Teildokument zu verweisen. + TBD + + + + + + + DocumentRelationship_Type + www.company.com/ids/cd/5044_0282_7091_6924 + + + + + + + + Typ der Dokumenten-Beziehung + DocumentRelationship_Type + + DocumentRelationship_Type + + + + + Typisierung der Beziehung zwischen den beiden DocumentVersions. Folgende Beziehungsarten können verwendet werden: Affecting (hat Auswirkungen auf), ReferesTo (bezieht sich auf), BasedOn (basiert auf) + TBD + + + + + + + StoredDocumentRepresentation + www.company.com/ids/cd/3094_0282_7091_2090 + + + + + + + + StoredDocumentRepresentation + StoredDocumentRepresentation + + StoredDocumentRepresentation + + + + + Liste von digitalen Repräsentationen zur DocumentVersion + TBD + + + + + + + VDI2770_DigitalFile + www.company.com/ids/cd/2305_0282_7091_2077 + + + + + + + + Digitaler-File + DigitalFile + + DigitalFile + + + + + Datei, die die DocumentVersion (siehe VDI 2770:2018 Anhang C1.5) repräsentiert Neben der obligatorischen PDF/A-Datei können weitere Dateien angegeben werden. + TBD + + + + + + + VDI2770_FileId + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileId + + + + + + + + ID der Datei + File ID + + FileId + + + + + eindeutige ID für die Datei + TBD + + + + + + + VDI2770_FileName + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileName + + + + + + + + Dateiname + File name + + FileName + + + + + Name der Datei inkl. einer Dateiendung (sofern vorhanden) Es ist nicht notwendig, einen Pfad für die Datei anzugeben. + TBD + + + + + + + VDI2770_FileFormat + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentVersion/StoredDocumentRepresentation/DigitalFile/FileFormat + + + + + + + + Datei Format + File format + + FileFormat + + + + + Angabe eines Media Typs gemäß der Liste der IANA + TBD + + + + + + + DocumentType + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentType + + + + + + + + Dokumententyp + Document Type + + DocumentType + + + + + Festlegung des Typs des Dokuments im Sinne der DIN EN 82045-1: a) Single (Einzeldokument) b) Aggregate (Sammeldokument) c) DocumentSet (Dokumentensatz) d) CompoundDoc (Mischdokument) + TBD + + + + + + + VDI2770_ReferencedObject + www.company.com/ids/cd/2570_2282_7091_0055 + + + + + + + + ReferencedObject + ReferencedObject + + ReferencedObject + + + + + Liste von IDs für ein Objekt, auf das sich das Dokument bezieht + TBD + + + + + + + VDI2770_ReferencedObject_Type + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ReferencedObjectType + + + + + + + + Typ + Type + + Type + + + + + Für Type des Objekts muss immer Product angegeben werden. + TBD + + + + + + + VDI2770_ReferencedObject_RefType + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/RefType + + + + + + + + RefType + RefType + + RefType + + + + + Angabe einer Typisierung zur Kennung des technischen Objekts. Folgende Werte sind möglich, ProductId (Produktnummer), SerialId (Seriennummer) + TBD + + + + + + + VDI2770_ReferencedObject_ObjectId + http://www.vdi.de/2770/AssetDocumentation/Document/ReferencedObject/ObjectId + + + + + + + + ObjectId + ObjectId + + ObjectId + + + + + Angabe der Identifikationsnummer zum Objekt + TBD + + + + + + + ContactInfo_Role + https://www.hsu-hh.de/aut/aas/role + + + + + + + + Rolle + Role + + Role + + + + + Angabe zur Spezifizierung der Rolle, die die Organisation aus ContactInfo einnimmt + Information to specify the role which the organisation of ContactInfo plays + + + + + + + Fax + https://www.hsu-hh.de/aut/aas/fax + + + + + + + + Fax + Fax + + Fax + + + + + Faxnummer + Fax number + + + + + + + 0173-1#02-AAO136#002 + + + + + DocGroup_01 + www.company.com/ids/cd/1420_0113_7091_0891 + + + + + + + + 01 Identifikation + 01 Identification + + DocGroup_01 + + + + + Der Gruppe „Identifikation“ werden alle Dokumente zugeordnet, die der Identifikation des Objekts dienen, zu dem die Herstellerdokumentation gehört. Sie enthält insbesondere Informationen, die die elektronische Datenverarbeitung unterstützen und die es dem Hersteller und dem Nutzer erlauben, das Objekt in ihren jeweiligen elektronischen Datenverarbeitungssystemen zu identifizieren. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocGroup_02 + www.company.com/ids/cd/4323_0113_7091_2591 + + + + + + + + 02 Technische Beschaffenheit + 02 Technical characteristics + + DocGroup_02 + + + + + Die Gruppe „Technische Beschaffenheit“ beinhaltet alle Dokumente, die die technischen Anforderungen, deren Erfüllung und die Bescheinigung der Eigenschaften eines Objekts betreffen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocGroup_03 + www.company.com/ids/cd/5053_0113_7091_5741 + + + + + + + + 03 Tätigkeitsbezogene Dokumente + 03 Work-related documents + + DocGroup_03 + + + + + Die Gruppe „Tätigkeitsbezogene Dokumente“ beinhaltet alle Dokumente, die Anforderungen, Hinweise und Hilfestellungen für Tätigkeiten an und mit dem Objekt nach der Übergabe an den Nutzer betreffen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocGroup_04 + www.company.com/ids/cd/5473_0113_7091_1588 + + + + + + + + 04 Vertragsunterlagen + 04 Contract documents + + DocGroup_04 + + + + + Der Gruppe „Vertragsunterlagen“ werden alle Dokumente zugeordnet, die im Zusammenhang mit der kaufmännischen Abwicklung eines Vertrages stehen, aber nicht selbst Gegenstand des Vertrags sind und lediglich zur Erfüllung des Vertrags dienen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_01-01 + www.company.com/ids/cd/9593_0113_7091_2401 + + + + + + + + 01-01 Identifikation + 01-01 Identification + + DocCategory_01-01 + + + + + Der Kategorie „Identifikation“ werden alle Dokumente zugeordnet, die der Identifikation des Objekts dienen, zu dem die Herstellerdokumentation gehört. Sie enthält insbesondere Informationen, die die elektronische Datenverarbeitung unterstützen und die es dem Hersteller und dem Nutzer erlauben, das Objekt in ihren jeweiligen elektronischen Datenverarbeitungssystemen zu identifizieren. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-01 + www.company.com/ids/cd/5314_0113_7091_8640 + + + + + + + + 02-01 Techn. Spezifikation + 02-01 Technical specification + + DocCategory_02-01 + + + + + Der Kategorie „Technische Spezifikation“ werden alle Dokumente zugeordnet, die die Anforderungen an ein Objekt sowie dessen Eigenschaften beschreiben. Dazu gehören die Auslegungsdaten, Berechnungen (Verfahrenstechnik, Festigkeit usw.) sowie alle relevanten Eigenschaften des übergebenen Objekts. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-02 + www.company.com/ids/cd/5515_0113_7091_8581 + + + + + + + + 02-02 Zeichnungen, Pläne + 02-02 Drawings and diagrams + + DocCategory_02-02 + + + + + Der Kategorie „Zeichnungen, Pläne“ werden alle Dokumente zugeordnet, die Zeichnungscharakter haben, das heißt eine grafische Darstellung zur Übermittlung von Information nutzen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-03 + www.company.com/ids/cd/0335_0113_7091_0312 + + + + + + + + 02-03 Bauteile + 02-03 Components + + DocCategory_02-03 + + + + + Der Kategorie „Bauteile“ werden alle Dokumente zugeordnet, die eine strukturierte Auflistung der Teile eines Objekts beinhalten. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_02-04 + www.company.com/ids/cd/2155_0113_7091_3955 + + + + + + + + 02-04 Zeugnisse, Zertifikate, Bescheinigungen + 02-04 Reports, Certificates, declarations + + DocCategory_02-04 + + + + + Der Kategorie „Zeugnisse, Zertifikate, Bescheinigungen“ werden alle Dokumente zugeordnet, die Urkundencharakter haben. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-01 + www.company.com/ids/cd/3565_0113_7091_2704 + + + + + + + + 03-01 Montage, Inbetriebnahme, Demontage + 03-01 Assembly, commissioning, disassembly + + DocCategory_03-01 + + + + + Der Kategorie „Montage, Demontage“ werden alle Dokumente zugeordnet, die Tätigkeiten und Maßnahmen beschreiben, die erforderlich sind, um ein Objekt: zu transportieren oder zu lagern, als Ganzes in ein übergeordnetes Objekt einzubauen, auszubauen oder an dieses anzuschließen, so weit vorzubereiten, dass es zur Inbetriebnahme bereitsteht, nach Abschluss der Nutzungsphase zu demontieren und zu entsorgen + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-02 + www.company.com/ids/cd/4290_1113_7091_7266 + + + + + + + + 03-02 Bedienung + 03-02 Operation + + DocCategory_03-02 + + + + + Der Kategorie „Bedienung“ werden Dokumente zur bestimmungsgemäßen Verwendung und sicheren Bedienung eines Objekts zugeordnet. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-03 + www.company.com/ids/cd/2211_1113_7091_3911 + + + + + + + + 03-03 Allgemeine Sicherheit + 03-03 Safety in general + + DocCategory_03-03 + + + + + Der Kategorie „Allgemeine Sicherheit“ werden Dokumente zugeordnet, die Sicherheitshinweise auf mögliche Gefährdungen bei der Verwendung des Objekts geben. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-04 + www.company.com/ids/cd/7521_1113_7091_4471 + + + + + + + + 03-04 Inspektion, Wartung, Prüfung + 03-04 Inspection, maintenance, test + + DocCategory_03-04 + + + + + Der Kategorie „Inspektion, Wartung, Prüfung“ werden alle Dokumente zugeordnet, die vom Hersteller vorgeschlagene wiederkehrende Maßnahmen zur Feststellung oder zum Erhalt des funktionsfähigen Zustands beschreiben. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-05 + www.company.com/ids/cd/5161_1113_7091_0458 + + + + + + + + 03-05 Instandsetzung + 03-05 Repair + + DocCategory_03-05 + + + + + Der Kategorie „Instandsetzung“ werden alle Dokumente zugeordnet, die Maßnahmen zur Wiederherstellung der Funktion eines Objekts betreffen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_03-06 + www.company.com/ids/cd/2181_1113_7091_5948 + + + + + + + + 03-06 Ersatzteile + 03-06 Spare parts + + DocCategory_03-06 + + + + + Der Kategorie „Ersatzteile“ werden Dokumente zugeordnet, die Informationen zu Ersatzteilen und Hilfs- und Betriebsstoffen enthalten. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + DocCategory_04-01 + www.company.com/ids/cd/5391_1113_7091_8996 + + + + + + + + 04-01 Vertragsunterlagen + 04-01 Contract documents + + DocCategory_04-01 + + + + + Der Kategorie „Vertragsunterlagen“ werden alle Dokumente zugeordnet, die im Zusammenhang mit der kaufmännischen Abwicklung eines Vertrages stehen, aber nicht selbst Gegenstand des Vertrags sind und lediglich zur Erfüllung des Vertrags dienen. + TBD + + + + + + + http://www.vdi.de/2770/AssetDocumentation/Document/DocumentClassification/ClassId + + + + + \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/app-info.json b/projects/aas-server/src/test/assets/app-info.json new file mode 100644 index 00000000..af535a43 --- /dev/null +++ b/projects/aas-server/src/test/assets/app-info.json @@ -0,0 +1,17 @@ +{ + "name": "aas-portal-project", + "version": "2.0.0", + "description": "Web-based visualization and control of asset administration shells.", + "author": "Fraunhofer IOSB-INA e.V.", + "homepage": "https://www.iosb-ina.fraunhofer.de/", + "license": "Apache-2.0", + "libraries": [ + { + "name": "Library", + "version": "1.0", + "description": "A library.", + "license": "MIT", + "homepage": "https://www.iosb-ina.fraunhofer.de/" + } + ] +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/error-handler.ts b/projects/aas-server/src/test/assets/error-handler.ts new file mode 100644 index 00000000..3b912d6d --- /dev/null +++ b/projects/aas-server/src/test/assets/error-handler.ts @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { ApplicationError } from "common"; +import { NextFunction, Request, Response } from "express"; +import { ValidateError } from "tsoa"; +import { ERRORS } from "../../app/errors.js"; + +export const errorHandler = (err: unknown, req: Request, res: Response, next: NextFunction): Response | void => { + if (err instanceof ValidateError) { + return res.status(422).json({ + message: "Validation Failed", + details: err?.fields, + }); + } + + if (err instanceof ApplicationError) { + if (err.name === ERRORS.UnauthorizedAccess) { + return res.status(401).json({ + message: 'Unauthorized' + }); + } + + return res.status(500).json({ + message: "Internal Server Error", + }); + } + + if (err instanceof Error) { + return res.status(500).json({ + message: "Internal Server Error", + }); + } + + next(); +}; \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/image.tiff b/projects/aas-server/src/test/assets/image.tiff new file mode 100644 index 00000000..c444b014 Binary files /dev/null and b/projects/aas-server/src/test/assets/image.tiff differ diff --git a/projects/aas-server/src/test/assets/json-web-token.ts b/projects/aas-server/src/test/assets/json-web-token.ts new file mode 100644 index 00000000..30df1c4f --- /dev/null +++ b/projects/aas-server/src/test/assets/json-web-token.ts @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { JWTPayload } from 'common'; +import jwt from 'jsonwebtoken'; + +export const guestPayload: JWTPayload = { role: 'guest' }; + +export const editorPayload = { id: 'john.doe@email.com', name: 'John', role: 'editor' }; + +export function getToken(name?: string): string { + return name + ? jwt.sign(editorPayload, 'SecretSecretSecretSecretSecretSecret') + : jwt.sign(guestPayload as JWTPayload, 'SecretSecretSecretSecretSecretSecret'); +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/sample-document.ts b/projects/aas-server/src/test/assets/sample-document.ts new file mode 100644 index 00000000..7d75532c --- /dev/null +++ b/projects/aas-server/src/test/assets/sample-document.ts @@ -0,0 +1,24 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASDocument } from 'common' + +export const sampleDocument: AASDocument = { + id: 'http://customer.com/aas/42', + idShort: 'ExampleMotor', + container: 'file:///samples?name=Samples', + endpoint: { + type: 'file', + address: 'ExampleMotor.aasx' + }, + timeStamp: 1656866284429, + modified: false, + readonly: false, + onlineReady: false, + content: null +}; \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/samples/example-motor.aasx b/projects/aas-server/src/test/assets/samples/example-motor.aasx new file mode 100644 index 00000000..e63538fc Binary files /dev/null and b/projects/aas-server/src/test/assets/samples/example-motor.aasx differ diff --git a/projects/aas-server/src/test/assets/samples/json-origin.aasx b/projects/aas-server/src/test/assets/samples/json-origin.aasx new file mode 100644 index 00000000..90c4578f Binary files /dev/null and b/projects/aas-server/src/test/assets/samples/json-origin.aasx differ diff --git a/projects/aas-server/src/test/assets/samples/xml-origin.aasx b/projects/aas-server/src/test/assets/samples/xml-origin.aasx new file mode 100644 index 00000000..604a2eee Binary files /dev/null and b/projects/aas-server/src/test/assets/samples/xml-origin.aasx differ diff --git a/projects/aas-server/src/test/assets/shop/AASSmartLightTypeLarge.aasx b/projects/aas-server/src/test/assets/shop/AASSmartLightTypeLarge.aasx new file mode 100644 index 00000000..8d128ce9 Binary files /dev/null and b/projects/aas-server/src/test/assets/shop/AASSmartLightTypeLarge.aasx differ diff --git a/projects/aas-server/src/test/assets/shop/AASSmartLightTypeSmall.aasx b/projects/aas-server/src/test/assets/shop/AASSmartLightTypeSmall.aasx new file mode 100644 index 00000000..d031599b Binary files /dev/null and b/projects/aas-server/src/test/assets/shop/AASSmartLightTypeSmall.aasx differ diff --git a/projects/aas-server/src/test/assets/test-aas/cuna-cup-becher1.ts b/projects/aas-server/src/test/assets/test-aas/cuna-cup-becher1.ts new file mode 100644 index 00000000..9e67df5c --- /dev/null +++ b/projects/aas-server/src/test/assets/test-aas/cuna-cup-becher1.ts @@ -0,0 +1,7072 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as aasv2 from '../../../app/types/aas-v2.js'; + +export default { + "assetAdministrationShells": [ + { + "asset": { + "keys": [ + { + "type": "Asset", + "local": true, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Asset:CunaCup:Becher-1", + "index": 0, + "idType": "IRI" + } + ] + }, + "submodels": [ + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:Nameplate:Becher-1", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:DigitalProductPassport:Becher-1", + "index": 0, + "idType": "IRI" + } + ] + }, + { + "keys": [ + { + "type": "Submodel", + "local": true, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:CustomerFeedback:Becher-1", + "index": 0, + "idType": "IRI" + } + ] + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:AAS:CunaCup:Becher-1" + }, + "idShort": "CunaCup_Becher-1", + "category": "VARIABLE", + "modelType": { + "name": "AssetAdministrationShell" + } + } + ], + "assets": [ + { + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Asset:CunaCup:Becher-1" + }, + "idShort": "CunaCup_Becher-1", + "category": "VARIABLE", + "modelType": { + "name": "Asset" + }, + "kind": "Instance" + } + ], + "submodels": [ + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate", + "index": 0, + "idType": "IRI" + } + ] + }, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:Nameplate:Becher-1" + }, + "idShort": "Nameplate_Becher-1", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "CUNA Products GmbH", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ManufacturerName", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "ManufacturerName", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ManufacturerProductDesignation", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "ManufacturerProductDesignation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ManufacturerProductFamily", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "ManufacturerProductFamily", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Becher-1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:SerialNumber", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "SerialNumber", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:BatchNumber", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "BatchNumber", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "DE", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ProductCountryOfOrigin", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "ProductCountryOfOrigin", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "01/15/2023", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:DateOfConstruction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "DateOfConstruction", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "datetime" + } + }, + "kind": "Instance" + }, + { + "value": "DE", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ProductCountryOfOrigin", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "ProductCountryOfOrigin", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Marking", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Marking_CE", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Marking:CEQualificationPresent", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "CEQualificationPresent", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:PhysicalAddress", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "PhysicalAddress", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "DE", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:CountryCode", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "CountryCode", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Rudolf-Diesel-Str. 3 ", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Street", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Street", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "40822", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Zip", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Zip", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Mettmann", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:CityTown", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "CityTown", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "DE", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:StateCounty", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "StateCounty", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ] + }, + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport", + "index": 0, + "idType": "IRI" + } + ] + }, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:DigitalProductPassport:Becher-1" + }, + "idShort": "DigitalProductPassport_Becher-1", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Color", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Color", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:LaserMotive", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "LaserMotive", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Volume", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Volume", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Height", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Height", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Diameter", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Diameter", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Commodity", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Commodity_group", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Abbreviation", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Abbreviation_DIN", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Density", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Density", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Tensile", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Tensile_strength", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Heat", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Heat_resistance", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Moisture", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Moisture_absorption", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Temperature", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Temperature_range", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Weight", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Weight", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Energy", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:neededEnergy", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "neededEnergy", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:CO2", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "CO2_emission", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:Renewable", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Renewable_portion", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:Electrical", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Electrical_work", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Recycling", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Recycling", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Recycling:savedMaterial", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "savedMaterial", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ] + }, + { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback", + "index": 0, + "idType": "IRI" + } + ] + }, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:CustomerFeedback:Becher-1" + }, + "idShort": "CustomerFeedback_Becher-1", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Becher war gut. Ich mochte das Aussehen.", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "4", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "no", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "SFOWL", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Gestalt: neutral; Geometrie: neutral; Maße: neutral; dimensions: neutral; Konstruktion: neutral; depth: neutral; Tiefe: neutral; räumlich: neutral; Form: neutral; area: neutral; length: neutral; Proportion: neutral; Gebilde: neutral; spatial: neutral; Abmaße: neutral; Größe: neutral; structure: neutral; Relation: neutral; Höhe: neutral; Breite: neutral; geometry: neutral; shape: neutral; broad: neutral; model: neutral; height: neutral; Abmessungen: neutral; Länge: neutral; Fläche: neutral; Modell: neutral; size: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.0238772", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "blue: neutral; Hässlich: neutral; beautiful: neutral; Colorful: neutral; Ugly: neutral; Blau: neutral; Aussehen: positive; Look: neutral; schön: neutral; edel: neutral; Noble: neutral; modern: neutral; hochwertig: neutral; high-quality: neutral; colours: neutral; Rot: neutral; Lichtwirkung: neutral; Weiß: neutral; color: neutral; Grün: neutral; Schwarz: neutral; Red: neutral; Design: neutral; Optik: neutral; colour: neutral; optics: neutral; Gelb: neutral; black: neutral; yellow: neutral; lighting effect: neutral; Farbe: neutral; material look: neutral; Materialoptik: neutral; Bunt: neutral; green: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Handhabung: neutral; handling: neutral; Benutzerfreundlichkeit: neutral; user friendliness: neutral; Usability: neutral; Intuitiv: neutral; Intuitive: neutral; Natürlich: neutral; Natural: neutral; Simple: neutral; Bildschirm: neutral; screen: neutral; Tasten: neutral; Knöpfe: neutral; buttons: neutral; Keys: neutral; Hebel: neutral; lever: neutral; Klappe: neutral; flap: neutral; Anzeige: neutral; display: neutral; Eingabe: neutral; input: neutral; output: neutral; Ausgabe: neutral; Feedback: neutral; Benutzerschnittstelle: neutral; Einfach: neutral; user interface: neutral; Interaktion: neutral; interaction: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "vocals: neutral; hidden: neutral; composition: neutral; generation: neutral; voices: neutral; components: neutral; module: neutral; great: neutral; component: neutral; modules: neutral; female: neutral; young: neutral; dependencies: neutral; active structure: neutral; desert: neutral; Artikel: neutral; item: neutral; Austausch: neutral; modular: neutral; exchange: neutral; construction: neutral; Struktur: neutral; white: neutral; structure: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Oberfläche: neutral; surface: neutral; Greifen: neutral; Grasp: neutral; Gefühl: neutral; feeling: neutral; grip: neutral; Griffigkeit: neutral; touch: neutral; Berührung: neutral; Taktil: neutral; Tactile: neutral; Haptik: neutral; Anfassen: neutral; feel: neutral; Widerstand: neutral; resistance: neutral; feels: neutral; feelings: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Geräusche: neutral; noises: neutral; Lautstärke: neutral; volume: neutral; Quietly: neutral; Betriebsgeräusch: neutral; Lärm: neutral; operating noise: neutral; noise: neutral; Leise: neutral; Laut: neutral; audible: neutral; Audio: neutral; Ton: neutral; Akustik: neutral; acoustics: neutral; hörbar: neutral; akustisch: neutral; acoustically: neutral; wahrnehmbar: neutral; Schall: neutral; sound: neutral; perceptible: neutral; Echo: neutral; Klang: neutral; Tonqualität: neutral; sound quality: neutral; Rauschen: neutral; rush: neutral; Krach: neutral; According to: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Montageschritte: neutral; Anfügen: neutral; assembly steps: neutral; append: neutral; Zusammenbau: neutral; assembly: neutral; Montage: neutral; Installation: neutral; Einbau: neutral; Einbauen: neutral; build in: neutral; work steps: neutral; installieren: neutral; to install: neutral; Arbeitsschritte: neutral; Aufbau: neutral; Inbetriebnahme: neutral; setup: neutral; Anschließen: neutral; Connect: neutral; Aufstellen: neutral; Set up: neutral; Auspacken: neutral; unpacking: neutral; Einsetzen: neutral; Deploy: neutral; Nutzen: neutral; To use: neutral; Montage und Installation: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Material: neutral; Robust: neutral; Haltbar: neutral; Durable: neutral; durability: neutral; Robustheit: neutral; robustness: neutral; Haltbarkeit: neutral; Materialien: neutral; materials: neutral; Plastik: neutral; plastic: neutral; metal: neutral; Metall: neutral; Eisen: neutral; Holz: neutral; wood: neutral; iron: neutral; Stahl: neutral; steel: neutral; Oberflächenstruktur: neutral; surface structure: neutral; Rauheitsgrad: neutral; degree of roughness: neutral; Härtegrad: neutral; Festigkeit: neutral; degree of hardness: neutral; strength: neutral; Biegfestigkeit: neutral; Dichte: neutral; density: neutral; Probe: neutral; sample: neutral; flexural strength: neutral; material sample: neutral; Materialprobe: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:dad32a3b1b56d8bb2ca4b6859fd271d0cf2db7df:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "c85518aa0f631389dfb9f46f78a38814dee437b9", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "c85518aa0f631389dfb9f46f78a38814dee437b9", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "testtetstesttes", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "4", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "no", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "fghj", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Gestalt: neutral; length: neutral; Abmaße: neutral; räumlich: neutral; height: neutral; Höhe: neutral; Tiefe: neutral; Form: neutral; Geometrie: neutral; Proportion: neutral; Gebilde: neutral; Konstruktion: neutral; Länge: neutral; model: neutral; broad: neutral; Maße: neutral; area: neutral; structure: neutral; size: neutral; spatial: neutral; Modell: neutral; Größe: neutral; Fläche: neutral; depth: neutral; Abmessungen: neutral; Breite: neutral; Relation: neutral; shape: neutral; geometry: neutral; dimensions: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Design: neutral; Materialoptik: neutral; material look: neutral; Gelb: neutral; yellow: neutral; optics: neutral; green: neutral; Optik: neutral; Red: neutral; Schwarz: neutral; black: neutral; Weiß: neutral; Bunt: neutral; Grün: neutral; Hässlich: neutral; Ugly: neutral; Blau: neutral; blue: neutral; Look: neutral; Rot: neutral; schön: neutral; beautiful: neutral; edel: neutral; Noble: neutral; modern: neutral; hochwertig: neutral; high-quality: neutral; Colorful: neutral; Aussehen: neutral; colours: neutral; lighting effect: neutral; Lichtwirkung: neutral; Farbe: neutral; colour: neutral; color: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Handhabung: neutral; handling: neutral; Benutzerfreundlichkeit: neutral; user friendliness: neutral; Intuitiv: neutral; Intuitive: neutral; Natürlich: neutral; Natural: neutral; Simple: neutral; Einfach: neutral; Bildschirm: neutral; screen: neutral; Tasten: neutral; Keys: neutral; Knöpfe: neutral; buttons: neutral; Hebel: neutral; lever: neutral; flap: neutral; Klappe: neutral; Anzeige: neutral; display: neutral; Eingabe: neutral; input: neutral; Ausgabe: neutral; output: neutral; Feedback: neutral; Benutzerschnittstelle: neutral; user interface: neutral; Usability: neutral; Interaktion: neutral; interaction: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "white: neutral; vocals: neutral; hidden: neutral; composition: neutral; component: neutral; desert: neutral; components: neutral; voices: neutral; module: neutral; great: neutral; modules: neutral; female: neutral; young: neutral; dependencies: neutral; active structure: neutral; Artikel: neutral; item: neutral; Austausch: neutral; exchange: neutral; modular: neutral; generation: neutral; construction: neutral; Struktur: neutral; structure: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Oberfläche: neutral; surface: neutral; Greifen: neutral; Grasp: neutral; Gefühl: neutral; feeling: neutral; Griffigkeit: neutral; grip: neutral; Berührung: neutral; touch: neutral; Taktil: neutral; Tactile: neutral; Widerstand: neutral; resistance: neutral; Haptik: neutral; Anfassen: neutral; feel: neutral; feelings: neutral; feels: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Geräusche: neutral; noises: neutral; Lautstärke: neutral; volume: neutral; operating noise: neutral; Leise: neutral; Lärm: neutral; Betriebsgeräusch: neutral; noise: neutral; Quietly: neutral; Laut: neutral; According to: neutral; hörbar: neutral; Audio: neutral; Ton: neutral; Akustik: neutral; acoustics: neutral; akustisch: neutral; acoustically: neutral; perceptible: neutral; wahrnehmbar: neutral; Schall: neutral; sound: neutral; Klang: neutral; Tonqualität: neutral; sound quality: neutral; Rauschen: neutral; rush: neutral; Krach: neutral; Echo: neutral; audible: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Montageschritte: neutral; assembly steps: neutral; Anfügen: neutral; Zusammenbau: neutral; assembly: neutral; append: neutral; Installation: neutral; Montage: neutral; Arbeitsschritte: neutral; Einbau: neutral; Einbauen: neutral; build in: neutral; installieren: neutral; to install: neutral; Inbetriebnahme: neutral; Aufbau: neutral; Anschließen: neutral; setup: neutral; Set up: neutral; Aufstellen: neutral; Connect: neutral; unpacking: neutral; Einsetzen: neutral; To use: neutral; Auspacken: neutral; Deploy: neutral; Nutzen: neutral; work steps: neutral; Montage und Installation: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Material: neutral; Robust: neutral; Haltbarkeit: neutral; durability: neutral; Durable: neutral; Haltbar: neutral; Robustheit: neutral; robustness: neutral; Materialien: neutral; materials: neutral; plastic: neutral; Metall: neutral; metal: neutral; iron: neutral; Holz: neutral; Eisen: neutral; wood: neutral; Stahl: neutral; steel: neutral; Oberflächenstruktur: neutral; surface structure: neutral; Rauheitsgrad: neutral; degree of roughness: neutral; Härtegrad: neutral; degree of hardness: neutral; Festigkeit: neutral; strength: neutral; Biegfestigkeit: neutral; Dichte: neutral; flexural strength: neutral; density: neutral; Probe: neutral; sample: neutral; Materialprobe: neutral; material sample: neutral; Plastik: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c85518aa0f631389dfb9f46f78a38814dee437b9:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Das ist ein guter Becher. Der Kaffee war lecker.", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "4", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "SFOWL", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "spatial: neutral; Abmessungen: neutral; Relation: neutral; depth: neutral; length: neutral; Form: neutral; shape: neutral; Geometrie: neutral; geometry: neutral; Gebilde: neutral; structure: neutral; Modell: neutral; model: neutral; Maße: neutral; dimensions: neutral; Abmaße: neutral; Größe: neutral; size: neutral; Länge: neutral; Breite: neutral; broad: neutral; Konstruktion: neutral; height: neutral; Proportion: neutral; Tiefe: neutral; Höhe: neutral; area: neutral; räumlich: neutral; Fläche: neutral; Gestalt: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Grün: neutral; colours: neutral; hochwertig: neutral; Look: neutral; Aussehen: neutral; Farbe: neutral; color: neutral; colour: neutral; lighting effect: neutral; Optik: neutral; optics: neutral; Design: neutral; Materialoptik: neutral; Gelb: neutral; yellow: neutral; green: neutral; Lichtwirkung: neutral; Red: neutral; Schwarz: neutral; black: neutral; Weiß: neutral; material look: neutral; Colorful: neutral; Hässlich: neutral; Ugly: neutral; Blau: neutral; blue: neutral; schön: neutral; Rot: neutral; edel: neutral; Noble: neutral; modern: neutral; high-quality: neutral; Bunt: neutral; beautiful: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Handhabung: neutral; handling: neutral; Benutzerfreundlichkeit: neutral; user friendliness: neutral; Usability: neutral; Intuitiv: neutral; Intuitive: neutral; Natürlich: neutral; Natural: neutral; Einfach: neutral; Simple: neutral; Bildschirm: neutral; screen: neutral; Tasten: neutral; Keys: neutral; Knöpfe: neutral; buttons: neutral; Hebel: neutral; lever: neutral; Klappe: neutral; flap: neutral; Anzeige: neutral; display: neutral; Eingabe: neutral; input: neutral; Ausgabe: neutral; output: neutral; Feedback: neutral; Benutzerschnittstelle: neutral; user interface: neutral; Interaktion: neutral; interaction: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "vocals: neutral; hidden: neutral; composition: neutral; generation: neutral; component: neutral; desert: neutral; components: neutral; voices: neutral; module: neutral; great: neutral; modules: neutral; female: neutral; dependencies: neutral; young: neutral; active structure: neutral; Artikel: neutral; item: neutral; Austausch: neutral; exchange: neutral; modular: neutral; construction: neutral; Struktur: neutral; structure: neutral; white: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Gefühl: neutral; feeling: neutral; Griffigkeit: neutral; grip: neutral; Berührung: neutral; touch: neutral; Taktil: neutral; Tactile: neutral; Widerstand: neutral; resistance: neutral; Haptik: neutral; feel: neutral; Anfassen: neutral; feelings: neutral; feels: neutral; surface: neutral; Grasp: neutral; Oberfläche: neutral; Greifen: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Geräusche: neutral; noises: neutral; Lautstärke: neutral; volume: neutral; Leise: neutral; Quietly: neutral; Betriebsgeräusch: neutral; operating noise: neutral; Lärm: neutral; noise: neutral; Laut: neutral; According to: neutral; hörbar: neutral; audible: neutral; Audio: neutral; Ton: neutral; Akustik: neutral; acoustics: neutral; akustisch: neutral; acoustically: neutral; wahrnehmbar: neutral; perceptible: neutral; Schall: neutral; sound: neutral; Echo: neutral; Klang: neutral; Tonqualität: neutral; sound quality: neutral; Rauschen: neutral; rush: neutral; Krach: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Montageschritte: neutral; assembly steps: neutral; Anfügen: neutral; append: neutral; Zusammenbau: neutral; assembly: neutral; Installation: neutral; Montage: neutral; Arbeitsschritte: neutral; work steps: neutral; Einbau: neutral; Einbauen: neutral; build in: neutral; installieren: neutral; to install: neutral; Inbetriebnahme: neutral; Aufbau: neutral; setup: neutral; Anschließen: neutral; Connect: neutral; Aufstellen: neutral; Set up: neutral; Auspacken: neutral; unpacking: neutral; Einsetzen: neutral; Deploy: neutral; Nutzen: neutral; To use: neutral; Montage und Installation: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Material: neutral; Robust: neutral; Haltbar: neutral; Durable: neutral; Haltbarkeit: neutral; durability: neutral; Robustheit: neutral; robustness: neutral; Materialien: neutral; materials: neutral; Plastik: neutral; plastic: neutral; Metall: neutral; metal: neutral; Eisen: neutral; iron: neutral; Holz: neutral; wood: neutral; Stahl: neutral; steel: neutral; Oberflächenstruktur: neutral; surface structure: neutral; Rauheitsgrad: neutral; degree of roughness: neutral; Härtegrad: neutral; degree of hardness: neutral; Festigkeit: neutral; strength: neutral; Biegfestigkeit: neutral; flexural strength: neutral; Dichte: neutral; density: neutral; Probe: neutral; sample: neutral; Materialprobe: neutral; material sample: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6fb0b6712f6bee1b8bc64a8abfcc00022da66f0a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Becher war gut. Mir gefällt das Aussehen.", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "5", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "no", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "SFOWl", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Tiefe: neutral; depth: neutral; area: neutral; räumlich: neutral; spatial: neutral; Relation: neutral; Fläche: neutral; Gestalt: neutral; Form: neutral; Proportion: neutral; Breite: neutral; dimensions: neutral; Größe: neutral; Länge: neutral; Modell: neutral; structure: neutral; Gebilde: neutral; geometry: neutral; shape: neutral; size: neutral; length: neutral; Konstruktion: neutral; Abmaße: neutral; height: neutral; Geometrie: neutral; Abmessungen: neutral; Maße: neutral; Höhe: neutral; model: neutral; broad: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.02490083", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Farbe: neutral; color: neutral; colour: neutral; Lichtwirkung: neutral; Optik: neutral; optics: neutral; Design: neutral; Materialoptik: neutral; material look: neutral; Gelb: neutral; yellow: neutral; green: neutral; Rot: neutral; Red: neutral; Schwarz: neutral; black: neutral; Weiß: neutral; Bunt: neutral; Colorful: neutral; Hässlich: neutral; Ugly: neutral; Blau: neutral; blue: neutral; Aussehen: positive; Look: neutral; schön: neutral; beautiful: neutral; edel: neutral; lighting effect: neutral; modern: neutral; hochwertig: neutral; high-quality: neutral; Grün: neutral; Noble: neutral; colours: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Handhabung: neutral; handling: neutral; Benutzerfreundlichkeit: neutral; user friendliness: neutral; Usability: neutral; Intuitive: neutral; Natürlich: neutral; Simple: neutral; Bildschirm: neutral; screen: neutral; Tasten: neutral; Keys: neutral; Knöpfe: neutral; buttons: neutral; Hebel: neutral; lever: neutral; Intuitiv: neutral; Einfach: neutral; flap: neutral; Anzeige: neutral; Natural: neutral; Klappe: neutral; display: neutral; Ausgabe: neutral; input: neutral; output: neutral; Eingabe: neutral; Feedback: neutral; Benutzerschnittstelle: neutral; user interface: neutral; interaction: neutral; Interaktion: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Struktur: neutral; structure: neutral; white: neutral; composition: neutral; generation: neutral; component: neutral; desert: neutral; components: neutral; voices: neutral; module: neutral; great: neutral; modules: neutral; female: neutral; dependencies: neutral; young: neutral; active structure: neutral; Artikel: neutral; Austausch: neutral; exchange: neutral; modular: neutral; item: neutral; vocals: neutral; hidden: neutral; construction: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "surface: neutral; Oberfläche: neutral; Greifen: neutral; Grasp: neutral; Gefühl: neutral; feeling: neutral; Griffigkeit: neutral; grip: neutral; Berührung: neutral; touch: neutral; Taktil: neutral; Tactile: neutral; Widerstand: neutral; resistance: neutral; feel: neutral; Haptik: neutral; Anfassen: neutral; feels: neutral; feelings: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Geräusche: neutral; Lautstärke: neutral; volume: neutral; Leise: neutral; noises: neutral; Quietly: neutral; Betriebsgeräusch: neutral; operating noise: neutral; Lärm: neutral; noise: neutral; Laut: neutral; hörbar: neutral; audible: neutral; According to: neutral; Audio: neutral; Ton: neutral; Akustik: neutral; acoustics: neutral; akustisch: neutral; acoustically: neutral; wahrnehmbar: neutral; perceptible: neutral; sound: neutral; Echo: neutral; Klang: neutral; Tonqualität: neutral; sound quality: neutral; Rauschen: neutral; rush: neutral; Krach: neutral; Schall: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Montage: neutral; Installation: neutral; Montage und Installation: neutral; Montageschritte: neutral; assembly steps: neutral; append: neutral; Anfügen: neutral; Zusammenbau: neutral; assembly: neutral; Arbeitsschritte: neutral; work steps: neutral; Einbau: neutral; Einbauen: neutral; build in: neutral; installieren: neutral; to install: neutral; Inbetriebnahme: neutral; Aufbau: neutral; setup: neutral; Anschließen: neutral; Aufstellen: neutral; Auspacken: neutral; unpacking: neutral; Connect: neutral; Deploy: neutral; Einsetzen: neutral; Nutzen: neutral; To use: neutral; Set up: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Material: neutral; Robust: neutral; Haltbar: neutral; Durable: neutral; durability: neutral; Haltbarkeit: neutral; Robustheit: neutral; robustness: neutral; Materialien: neutral; materials: neutral; Plastik: neutral; plastic: neutral; Metall: neutral; metal: neutral; Eisen: neutral; iron: neutral; Holz: neutral; wood: neutral; Stahl: neutral; steel: neutral; Oberflächenstruktur: neutral; surface structure: neutral; degree of roughness: neutral; Rauheitsgrad: neutral; degree of hardness: neutral; Härtegrad: neutral; Festigkeit: neutral; Biegfestigkeit: neutral; Dichte: neutral; flexural strength: neutral; density: neutral; Probe: neutral; strength: neutral; sample: neutral; Materialprobe: neutral; material sample: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:75a426dae2f7e3a170fbb3cfce97a25a5bb3cd4a:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "c41147e91f2164ddae7d217da8f38c76b28cba6f", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "c41147e91f2164ddae7d217da8f38c76b28cba6f", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Der Becher hat mir gar nicht gefallen.", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "1", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "no", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Tiefe: neutral; depth: neutral; area: neutral; räumlich: neutral; spatial: neutral; Relation: neutral; Fläche: neutral; Gestalt: neutral; Form: neutral; Proportion: neutral; Breite: neutral; dimensions: neutral; Größe: neutral; Länge: neutral; Modell: neutral; structure: neutral; Gebilde: neutral; geometry: neutral; shape: neutral; size: neutral; length: neutral; Konstruktion: neutral; Abmaße: neutral; height: neutral; Geometrie: neutral; Abmessungen: neutral; Maße: neutral; Höhe: neutral; model: neutral; broad: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Farbe: neutral; color: neutral; colour: neutral; Lichtwirkung: neutral; Optik: neutral; optics: neutral; Design: neutral; Materialoptik: neutral; material look: neutral; Gelb: neutral; yellow: neutral; green: neutral; Rot: neutral; Red: neutral; Schwarz: neutral; black: neutral; Weiß: neutral; Bunt: neutral; Colorful: neutral; Hässlich: neutral; Ugly: neutral; Blau: neutral; blue: neutral; Aussehen: neutral; Look: neutral; schön: neutral; beautiful: neutral; edel: neutral; lighting effect: neutral; modern: neutral; hochwertig: neutral; high-quality: neutral; Grün: neutral; Noble: neutral; colours: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Handhabung: neutral; handling: neutral; Benutzerfreundlichkeit: neutral; user friendliness: neutral; Usability: neutral; Intuitive: neutral; Natürlich: neutral; Simple: neutral; Bildschirm: neutral; screen: neutral; Tasten: neutral; Keys: neutral; Knöpfe: neutral; buttons: neutral; Hebel: neutral; lever: neutral; Intuitiv: neutral; Einfach: neutral; flap: neutral; Anzeige: neutral; Natural: neutral; Klappe: neutral; display: neutral; Ausgabe: neutral; input: neutral; output: neutral; Eingabe: neutral; Feedback: neutral; Benutzerschnittstelle: neutral; user interface: neutral; interaction: neutral; Interaktion: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Struktur: neutral; structure: neutral; white: neutral; composition: neutral; generation: neutral; component: neutral; desert: neutral; components: neutral; voices: neutral; module: neutral; great: neutral; modules: neutral; female: neutral; dependencies: neutral; young: neutral; active structure: neutral; Artikel: neutral; Austausch: neutral; exchange: neutral; modular: neutral; item: neutral; vocals: neutral; hidden: neutral; construction: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "surface: neutral; Oberfläche: neutral; Greifen: neutral; Grasp: neutral; Gefühl: neutral; feeling: neutral; Griffigkeit: neutral; grip: neutral; Berührung: neutral; touch: neutral; Taktil: neutral; Tactile: neutral; Widerstand: neutral; resistance: neutral; feel: neutral; Haptik: neutral; Anfassen: neutral; feels: neutral; feelings: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Geräusche: neutral; Lautstärke: neutral; volume: neutral; Leise: neutral; noises: neutral; Quietly: neutral; Betriebsgeräusch: neutral; operating noise: neutral; Lärm: neutral; noise: neutral; Laut: neutral; hörbar: neutral; audible: neutral; According to: neutral; Audio: neutral; Ton: neutral; Akustik: neutral; acoustics: neutral; akustisch: neutral; acoustically: neutral; wahrnehmbar: neutral; perceptible: neutral; sound: neutral; Echo: neutral; Klang: neutral; Tonqualität: neutral; sound quality: neutral; Rauschen: neutral; rush: neutral; Krach: neutral; Schall: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Montage: neutral; Installation: neutral; Montage und Installation: neutral; Montageschritte: neutral; assembly steps: neutral; append: neutral; Anfügen: neutral; Zusammenbau: neutral; assembly: neutral; Arbeitsschritte: neutral; work steps: neutral; Einbau: neutral; Einbauen: neutral; build in: neutral; installieren: neutral; to install: neutral; Inbetriebnahme: neutral; Aufbau: neutral; setup: neutral; Anschließen: neutral; Aufstellen: neutral; Auspacken: neutral; unpacking: neutral; Connect: neutral; Deploy: neutral; Einsetzen: neutral; Nutzen: neutral; To use: neutral; Set up: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Material: neutral; Robust: neutral; Haltbar: neutral; Durable: neutral; durability: neutral; Haltbarkeit: neutral; Robustheit: neutral; robustness: neutral; Materialien: neutral; materials: neutral; Plastik: neutral; plastic: neutral; Metall: neutral; metal: neutral; Eisen: neutral; iron: neutral; Holz: neutral; wood: neutral; Stahl: neutral; steel: neutral; Oberflächenstruktur: neutral; surface structure: neutral; degree of roughness: neutral; Rauheitsgrad: neutral; degree of hardness: neutral; Härtegrad: neutral; Festigkeit: neutral; Biegfestigkeit: neutral; Dichte: neutral; flexural strength: neutral; density: neutral; Probe: neutral; strength: neutral; sample: neutral; Materialprobe: neutral; material sample: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:c41147e91f2164ddae7d217da8f38c76b28cba6f:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "6b4b3b179b149667979e5bab9279df90c4567fdd", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "6b4b3b179b149667979e5bab9279df90c4567fdd", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Becher war ok. Die Akustik lässt zu wünschen übrig. Der Kaffee war aber gut. Das Aussehen und die Farbe gefallen mir ebenfalls.", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "5", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "no", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "SFOWL", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Aussehen: neutral; Farbe: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Akustik: neutral", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:6b4b3b179b149667979e5bab9279df90c4567fdd:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "0027dca15784ea35ce873a98cbdf35053d7e2f78", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "03/01/2023 11:09:59", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "0027dca15784ea35ce873a98cbdf35053d7e2f78", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Der Becher ist gut. Ich mag ihn wirklich sehr. Die Haptik gefällt mir auch sehr gut.", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "5", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "no", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "EveryDay", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "More than 3 times a day", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "SFOWL", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.994278", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "Haptik: positive", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + }, + { + "value": "", + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:0027dca15784ea35ce873a98cbdf35053d7e2f78:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ], + "kind": "Instance" + } + ] + } + ], + "conceptDescriptions": [] + } as unknown as aasv2.AssetAdministrationShellEnvironment; \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/test-aas/customer-feedback-becher1.ts b/projects/aas-server/src/test/assets/test-aas/customer-feedback-becher1.ts new file mode 100644 index 00000000..25b5ec1b --- /dev/null +++ b/projects/aas-server/src/test/assets/test-aas/customer-feedback-becher1.ts @@ -0,0 +1,5929 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export default { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback", + "index": 0, + "idType": "IRI" + } + ] + }, + "qualifiers": null, + "hasDataSpecification": null, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:CustomerFeedback:Becher1" + }, + "administration": null, + "idShort": "CustomerFeedback_Becher1", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "216031bd44ce1e9575f34567965ebfff65539bb57587g", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "12/15/2022 12:06:03", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "216031bd44ce1e9575f34567965ebfff65539bb57587g", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Das Design des Bechers und die Form gefallen mir gut. Ich mag auch die Farbe, die ist sehr modern. Das Material scheint sehr stabil zu sein und es ist leicht. Die Haptik ist super, der Becher liegt gut in der Hand. Der Becher ist zudem haltbar. Die Größe gefällt mir allerdings nicht so gut. Er könnte etwas größer sein bei meinem Kaffeebedarf. Es fehlt allerdings eine Bluetooth Schnittstelle, das ist schade. Insgesamt handelt es sich trotzdem um einen super Kaffeebecher mit gutem Aussehen", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.273084", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Form: positive; Größe: negative", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.91003275", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Farbe: positive; Aussehen: positive; modern: positive; Design: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.867639", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Haptik: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.318981", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Material: positive; Haltbar: neutral", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e9575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "216031bd44ce1e45893459575f34567965ebfff65539bb57587g", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "12/15/2022 12:06:03", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "216031bd44ce1e45893459575f34567965ebfff65539bb57587g", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Das Design des Bechers und die Form gefallen mir gut. Ich mag auch die Farbe, die ist sehr modern. Das Material scheint sehr stabil zu sein und es ist leicht. Die Haptik ist super, der Becher liegt gut in der Hand. Der Becher ist zudem haltbar. Die Größe gefällt mir allerdings nicht so gut. Er könnte etwas größer sein bei meinem Kaffeebedarf. Es fehlt allerdings eine Bluetooth Schnittstelle, das ist schade. Insgesamt handelt es sich trotzdem um einen super Kaffeebecher mit gutem Aussehen", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.273084", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Form: positive; Größe: negative", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.91003275", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Farbe: positive; Aussehen: positive; modern: positive; Design: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.867639", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Haptik: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.318981", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Material: positive; Haltbar: neutral", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:216031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "2346031bd44ce1e45893459575f34567965ebfff65539bb57587g", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "12/15/2022 12:06:03", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "2346031bd44ce1e45893459575f34567965ebfff65539bb57587g", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Das Design des Bechers und die Form gefallen mir gut. Ich mag auch die Farbe, die ist sehr modern. Das Material scheint sehr stabil zu sein und es ist leicht. Die Haptik ist super, der Becher liegt gut in der Hand. Der Becher ist zudem haltbar. Die Größe gefällt mir allerdings nicht so gut. Er könnte etwas größer sein bei meinem Kaffeebedarf. Es fehlt allerdings eine Bluetooth Schnittstelle, das ist schade. Insgesamt handelt es sich trotzdem um einen super Kaffeebecher mit gutem Aussehen", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.273084", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Form: positive; Größe: negative", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.91003275", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Farbe: positive; Aussehen: positive; modern: positive; Design: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.867639", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Haptik: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.318981", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Material: positive; Haltbar: neutral", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:2346031bd44ce1e45893459575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "4560146049575f34567965ebfff65539bb57587g", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "12/15/2022 12:06:03", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4560146049575f34567965ebfff65539bb57587g", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Das Design des Bechers und die Form gefallen mir gut. Ich mag auch die Farbe, die ist sehr modern. Das Material scheint sehr stabil zu sein und es ist leicht. Die Haptik ist super, der Becher liegt gut in der Hand. Der Becher ist zudem haltbar. Die Größe gefällt mir allerdings nicht so gut. Er könnte etwas größer sein bei meinem Kaffeebedarf. Es fehlt allerdings eine Bluetooth Schnittstelle, das ist schade. Insgesamt handelt es sich trotzdem um einen super Kaffeebecher mit gutem Aussehen", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.273084", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Form: positive; Größe: negative", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.91003275", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Farbe: positive; Aussehen: positive; modern: positive; Design: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.867639", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Haptik: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.318981", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Material: positive; Haltbar: neutral", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:4560146049575f34567965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "8974560146049575f67965ebfff65539bb57587g", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "12/15/2022 12:06:03", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "8974560146049575f67965ebfff65539bb57587g", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Das Design des Bechers und die Form gefallen mir gut. Ich mag auch die Farbe, die ist sehr modern. Das Material scheint sehr stabil zu sein und es ist leicht. Die Haptik ist super, der Becher liegt gut in der Hand. Der Becher ist zudem haltbar. Die Größe gefällt mir allerdings nicht so gut. Er könnte etwas größer sein bei meinem Kaffeebedarf. Es fehlt allerdings eine Bluetooth Schnittstelle, das ist schade. Insgesamt handelt es sich trotzdem um einen super Kaffeebecher mit gutem Aussehen", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.273084", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Form: positive; Größe: negative", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.91003275", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Farbe: positive; Aussehen: positive; modern: positive; Design: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.867639", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Haptik: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.318981", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Material: positive; Haltbar: neutral", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:8974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "123458974560146049575f67965ebfff65539bb57587g", + "category": "VARIABLE", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "12/15/2022 12:06:03", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:createdAt", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "createdAt", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "123458974560146049575f67965ebfff65539bb57587g", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:feedbackId", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "feedbackId", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Das Design des Bechers und die Form gefallen mir gut. Ich mag auch die Farbe, die ist sehr modern. Das Material scheint sehr stabil zu sein und es ist leicht. Die Haptik ist super, der Becher liegt gut in der Hand. Der Becher ist zudem haltbar. Die Größe gefällt mir allerdings nicht so gut. Er könnte etwas größer sein bei meinem Kaffeebedarf. Es fehlt allerdings eine Bluetooth Schnittstelle, das ist schade. Insgesamt handelt es sich trotzdem um einen super Kaffeebecher mit gutem Aussehen", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:message", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "message", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "4", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:stars", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "stars", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "float" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Individual", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Individual", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "yes", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Individual:Deposit", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Deposit_appropriate", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Individual:Coffee", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Coffee_frequency", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "EveryDay", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Individual:Usage", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Usage_CUNACup", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Individual:Cafe", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Cafe_recommendation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Form", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Form", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.273084", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Form: positive; Größe: negative", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Looks", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Looks", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.91003275", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Farbe: positive; Aussehen: positive; modern: positive; Design: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Interaction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Interaction", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Structure", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Structure", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Haptics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Haptics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.867639", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Haptik: positive", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Acustics", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Acustics", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Assembly", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Assembly_Installation", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:General:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "0.318981", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Score", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Score", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Material: positive; Haltbar: neutral", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:CustomerFeedback:123458974560146049575f67965ebfff65539bb57587g:Sentiment", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Sentiment", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "descriptions": null +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/test-aas/digital-product-passport-becher1.ts b/projects/aas-server/src/test/assets/test-aas/digital-product-passport-becher1.ts new file mode 100644 index 00000000..1e7ab350 --- /dev/null +++ b/projects/aas-server/src/test/assets/test-aas/digital-product-passport-becher1.ts @@ -0,0 +1,663 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export default { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport", + "index": 0, + "idType": "IRI" + } + ] + }, + "qualifiers": null, + "hasDataSpecification": null, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:DigitalProductPassport:Becher1" + }, + "administration": null, + "idShort": "DigitalProductPassport_Becher1", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "General", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Color", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Color", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:LaserMotive", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "LaserMotive", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Volume", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Volume", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Height", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Height", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:General:Diameter", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Diameter", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Material", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Commodity", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Commodity_group", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Abbreviation", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Abbreviation_DIN", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Density", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Density", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Tensile", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Tensile_strength", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Heat", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Heat_resistance", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Moisture", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Moisture_absorption", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Temperature", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Temperature_range", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Material:Weight", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Weight", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Energy", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:neededEnergy", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "neededEnergy", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:CO2", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "CO2_emission", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:Renewable", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Renewable_portion", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Energy:Electrical", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Electrical_work", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Recycling", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Recycling", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:DigitalProductPassport:Recycling:savedMaterial", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "savedMaterial", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "descriptions": null +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/test-aas/listaas.ts b/projects/aas-server/src/test/assets/test-aas/listaas.ts new file mode 100644 index 00000000..a1731d8a --- /dev/null +++ b/projects/aas-server/src/test/assets/test-aas/listaas.ts @@ -0,0 +1,16 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export default { + "aaslist": [ + "0 : AssistanceSystem_Dte : [IRI] urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:AAS:AssistanceSystem:Dte : ", + "0 : CunaCup_Becher1 : [IRI] urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:AAS:CunaCup:Becher1 : ", + "0 : CunaCup_Becher2 : [IRI] urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:AAS:CunaCup:Becher2 : ", + "1 : DTOrchestrator : [IRI] urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:AAS:DTOrchestrator : " + ] +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/test-aas/nameplate-becher1.ts b/projects/aas-server/src/test/assets/test-aas/nameplate-becher1.ts new file mode 100644 index 00000000..1371657e --- /dev/null +++ b/projects/aas-server/src/test/assets/test-aas/nameplate-becher1.ts @@ -0,0 +1,495 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export default { + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate", + "index": 0, + "idType": "IRI" + } + ] + }, + "qualifiers": null, + "hasDataSpecification": null, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:Nameplate:Becher1" + }, + "administration": null, + "idShort": "Nameplate_Becher1", + "category": "VARIABLE", + "modelType": { + "name": "Submodel" + }, + "kind": "Instance", + "submodelElements": [ + { + "value": "CUNA Products GmbH", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ManufacturerName", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "ManufacturerName", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ManufacturerProductDesignation", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "ManufacturerProductDesignation", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ManufacturerProductFamily", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "ManufacturerProductFamily", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Becher1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:SerialNumber", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "SerialNumber", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:BatchNumber", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "BatchNumber", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "DE", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ProductCountryOfOrigin", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "ProductCountryOfOrigin", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "2022", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:YearOfConstruction", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "YearOfConstruction", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "DE", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:ProductCountryOfOrigin", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "ProductCountryOfOrigin", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Marking", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Marking_CE", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "1", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Marking:CEQualificationPresent", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "CEQualificationPresent", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + }, + { + "ordered": true, + "allowDuplicates": true, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:PhysicalAddress", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "PhysicalAddress", + "category": "CONSTANT", + "modelType": { + "name": "SubmodelElementCollection" + }, + "value": [ + { + "value": "DE", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:CountryCode", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "CountryCode", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Rudolf-Diesel-Str. 3 ", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Street", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Street", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "40822", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:Zip", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "Zip", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "Mettmann", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:CityTown", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "CityTown", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + }, + { + "value": "DE", + "valueId": null, + "semanticId": { + "keys": [ + { + "type": "GlobalReference", + "local": false, + "value": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:SemId:Submodel:Nameplate:StateCounty", + "index": 0, + "idType": "IRI" + } + ] + }, + "constraints": null, + "hasDataSpecification": null, + "idShort": "StateCounty", + "category": "CONSTANT", + "modelType": { + "name": "Property" + }, + "valueType": { + "dataObjectType": { + "name": "string" + } + }, + "kind": "Instance", + "descriptions": null + } + ], + "kind": "Instance", + "descriptions": null + } + ], + "descriptions": null +} \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/test-aas/submodels.ts b/projects/aas-server/src/test/assets/test-aas/submodels.ts new file mode 100644 index 00000000..316748d2 --- /dev/null +++ b/projects/aas-server/src/test/assets/test-aas/submodels.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export default [ + { + "id": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:Nameplate:Becher1" + }, + "idShort": "Nameplate_Becher1", + "kind": "Instance" + }, + { + "id": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:DigitalProductPassport:Becher1" + }, + "idShort": "DigitalProductPassport_Becher1", + "kind": "Instance" + }, + { + "id": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:KIReallabor:CUNACup:Id:Submodel:CustomerFeedback:Becher1" + }, + "idShort": "CustomerFeedback_Becher1", + "kind": "Instance" + } +] \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/test-registry.ts b/projects/aas-server/src/test/assets/test-registry.ts new file mode 100644 index 00000000..f7ad3ae8 --- /dev/null +++ b/projects/aas-server/src/test/assets/test-registry.ts @@ -0,0 +1,316 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export default [ + { + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32", + "type": "http" + } + ], + "modelType": { + "name": "AssetAdministrationShellDescriptor" + }, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:AAS:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "ProductionJob_29663efb09f942cd80208737ad948b32", + "asset": { + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Asset:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "ProductionJob_29663efb09f942cd80208737ad948b32", + "kind": "Instance", + "modelType": { + "name": "Asset" + }, + "category": "VARIABLE" + }, + "submodels": [ + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:SemId:Submodel:MasterData:ProductionJob", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32/submodels/MasterData_ProductionJob_29663efb09f942cd80208737ad948b32/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Submodel:MasterData:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "MasterData_ProductionJob_29663efb09f942cd80208737ad948b32" + }, + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:SemId:Submodel:BillOfMaterial:ProductionJob", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32/submodels/BillOfMaterial_ProductionJob_29663efb09f942cd80208737ad948b32/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Submodel:BillOfMaterial:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "BillOfMaterial_ProductionJob_29663efb09f942cd80208737ad948b32" + }, + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:SemId:Submodel:AssetManagement:ProductionJob", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32/submodels/AssetManagement_ProductionJob_29663efb09f942cd80208737ad948b32/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Submodel:AssetManagement:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "AssetManagement_ProductionJob_29663efb09f942cd80208737ad948b32" + }, + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:SemId:Submodel:LifeCycleDocumentation:ProductionJob", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32/submodels/LifeCycleDocumentation_ProductionJob_29663efb09f942cd80208737ad948b32/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Submodel:LifeCycleDocumentation:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "LifeCycleDocumentation_ProductionJob_29663efb09f942cd80208737ad948b32" + }, + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:SemId:Submodel:DTStorageInterfaceConfiguration:ProductionJob", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32/submodels/DTStorageInterfaceConfiguration_ProductionJob_29663efb09f942cd80208737ad948b32/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Submodel:DTStorageInterfaceConfiguration:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "DTStorageInterfaceConfiguration_ProductionJob_29663efb09f942cd80208737ad948b32" + }, + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:SemId:Submodel:DTAssetInterfaceConfiguration:ProductionJob", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:51000/aas/ProductionJob_29663efb09f942cd80208737ad948b32/submodels/DTAssetInterfaceConfiguration_ProductionJob_29663efb09f942cd80208737ad948b32/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:Fraunhofer:de:CrossTepDte:AssemblyAssistance:Id:Submodel:DTAssetInterfaceConfiguration:ProductionJob:29663efb09f942cd80208737ad948b32" + }, + "idShort": "DTAssetInterfaceConfiguration_ProductionJob_29663efb09f942cd80208737ad948b32" + } + ] + }, + { + "endpoints": [ + { + "address": "http://172.16.160.188:50010/orderTakingService", + "type": "http" + } + ], + "modelType": { + "name": "AssetAdministrationShellDescriptor" + }, + "identification": { + "idType": "IRI", + "id": "urn:sfowl:manufacturer:aas:1:1:orderTakingService_0001" + }, + "idShort": "orderTakingService", + "asset": { + "identification": { + "idType": "IRI", + "id": "urn:sfowl:manufacturer:asset:1:1:orderTakingService_0001" + }, + "idShort": "orderTakingService", + "kind": "Instance", + "modelType": { + "name": "Asset" + }, + "category": "CONSTANT" + }, + "submodels": [ + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:sfowl:manufacturer:semId:1:1:orderTakingService", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.188:50010/orderTakingService/orderTakingService", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:sfowl:manufacturer:sm:1:1:orderTakingService_0001" + }, + "idShort": "orderTakingService" + } + ] + }, + { + "endpoints": [ + { + "address": "http://172.16.160.171:54000/aas/InjectionMouldingMachine", + "type": "http" + } + ], + "modelType": { + "name": "AssetAdministrationShellDescriptor" + }, + "identification": { + "idType": "IRI", + "id": "urn:IOSB:INA:Fraunhofer:CUNA:Production:Id:AAS:InjectionMouldingMachine" + }, + "idShort": "InjectionMouldingMachine", + "asset": { + "identification": { + "idType": "IRI", + "id": "urn:IOSB:INA:Fraunhofer:CUNA:Production:Id:Asset:InjectionMouldingMachine" + }, + "idShort": "InjectionMouldingMachine", + "kind": "Instance", + "modelType": { + "name": "Asset" + }, + "category": "VARIABLE" + }, + "submodels": [ + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:INA:Fraunhofer:CUNA:Production:SemId:Submodel:DigitalNameplate", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:54000/aas/InjectionMouldingMachine/submodels/DigitalNameplate/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:INA:Fraunhofer:CUNA:Production:Id:Submodel:DigitalNameplate" + }, + "idShort": "DigitalNameplate" + }, + { + "semanticId": { + "keys": [ + { + "idType": "IRI", + "index": 0, + "type": "GlobalReference", + "value": "urn:IOSB:INA:Fraunhofer:CUNA:Production:SemId:Submodel:OperationalData", + "local": false + } + ] + }, + "endpoints": [ + { + "address": "http://172.16.160.171:54000/aas/InjectionMouldingMachine/submodels/OperationalData/complete", + "type": "http" + } + ], + "identification": { + "idType": "IRI", + "id": "urn:IOSB:INA:Fraunhofer:CUNA:Production:Id:Submodel:OperationalData" + }, + "idShort": "OperationalData" + } + ] + } +] \ No newline at end of file diff --git a/projects/aas-server/src/test/assets/thumbnail.jpg b/projects/aas-server/src/test/assets/thumbnail.jpg new file mode 100644 index 00000000..a1b57bce Binary files /dev/null and b/projects/aas-server/src/test/assets/thumbnail.jpg differ diff --git a/projects/aas-server/src/test/auth/auth-service.spec.ts b/projects/aas-server/src/test/auth/auth-service.spec.ts new file mode 100644 index 00000000..34f9c0cc --- /dev/null +++ b/projects/aas-server/src/test/auth/auth-service.spec.ts @@ -0,0 +1,202 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import { ApplicationError, UserProfile } from 'common'; + +import { AuthService } from '../../app/auth/auth-service.js'; +import { ERRORS } from '../../app/errors.js'; +import { Mailer } from '../../app/mailer.js'; +import { UserStorage } from '../../app/auth/user-storage.js'; +import { UserData } from '../../app/auth/user-data.js'; +import { CookieStorage } from '../../app/auth/cookie-storage.js'; +import { createSpyObj } from '../utils.js'; +import { Variable } from '../../app/variable.js'; + +describe('AuthService', function () { + let mailer: Mailer; + let auth: AuthService; + let userStorage: jest.Mocked; + let cookieStorage: jest.Mocked; + let variable: jest.Mocked; + let johnDoeData: UserData; + + beforeEach(function () { + mailer = createSpyObj(['sendPassword', 'sendNewPassword']); + userStorage = createSpyObj(['existAsync', 'readAsync', 'writeAsync', 'deleteAsync']); + cookieStorage = createSpyObj(['checkAsync', 'getAsync', 'setAsync', 'deleteAsync']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecret', JWT_EXPIRES_IN: 60 }); + auth = new AuthService(mailer, userStorage, cookieStorage, variable); + + johnDoeData = { + id: "john.doe@email.com", + name: "John", + role: "editor", + password: "$2a$10$6qZT2ZM5jUVU/pLLQUjCvuXplG.GwPnoz48C1Eg/dKqjIrGE8jm0a", + created: new Date("2020-11-02T10:22:56.328Z"), + lastLoggedIn: new Date(0) + }; + }); + + it('should be created', function () { + expect(auth).toBeTruthy(); + }); + + describe('loginAsync', function () { + it('returns a user token.', async function () { + userStorage.readAsync.mockReturnValue(new Promise((result) => result(johnDoeData))); + const result = await auth.loginAsync({ id: 'john.doe@email.com', password: '6iu3hbcc' }); + expect(result?.token).toBeDefined(); + }); + + it('returns a guest token.', async function () { + userStorage.readAsync.mockReturnValue(new Promise((result) => result(johnDoeData))); + const result = await auth.loginAsync(); + expect(result?.token).toBeDefined(); + }); + + it('throws an UnknownUser error.', async function () { + try { + userStorage.readAsync.mockReturnValue(new Promise((result) => result(undefined))); + await auth.loginAsync({ id: 'unknown@iosb-ina.fraunhofer.de', password: '6iu3hbcc' }); + } catch (error) { + expect(error instanceof ApplicationError).toBeTruthy(); + expect(error.name).toEqual(ERRORS.UnknownUser); + } + }); + + it('throws an InvalidPassword error.', async function () { + try { + userStorage.readAsync.mockReturnValue(new Promise((result) => result(johnDoeData))); + await auth.loginAsync({ id: 'john.doe@email.com', password: 'invalid' }); + } catch (error) { + expect(error instanceof ApplicationError).toBeTruthy(); + expect(error.name).toEqual(ERRORS.InvalidPassword); + } + }); + }); + + describe('updateProfileAsync', function () { + let profile: UserProfile; + + beforeEach(function () { + profile = { + id: 'monika.mustermann@email.com', + name: 'Monika', + password: '12345678' + }; + }); + + it('updates the profile of a registered user', async function () { + const monikaData: UserData = { + id: "monika.mustermann@email.com", + name: "Monika", + role: "editor", + password: "$2a$10$6qZT2ZM5jUVU/pLLQUjCvuXplG.GwPnoz48C1Eg/dKqjIrGE8jm0a", + created: new Date("2020-11-02T10:22:56.328Z"), + lastLoggedIn: new Date(0) + }; + + userStorage.readAsync.mockReturnValue(new Promise((result) => result(monikaData))); + const result = await auth.updateProfileAsync('monika.mustermann@email.com', profile); + expect(result.token).toBeDefined(); + }); + + it('throws an error if user is unknown or not authenticated', async function () { + userStorage.readAsync.mockReturnValue(new Promise((result) => result(undefined))); + await expect(auth.updateProfileAsync('unknown', profile)).rejects.toThrowError(); + }); + }); + + describe('registerUserAsync', function () { + let johnDoeProfile: UserProfile; + + beforeEach(function () { + johnDoeProfile = { + id: 'john.doe@email.com', + name: 'John Doe', + password: '12345678' + }; + }); + + it('registers a new user', async function () { + userStorage.existAsync.mockReturnValue(new Promise(result => result(false))); + await expect(auth.registerUserAsync(johnDoeProfile)).resolves.toBeDefined(); + }); + + // it('registers a new user, password is send via e-mail', async function () { + // userStorage.existAsync.mockReturnValue(new Promise(result => result(false))); + // mailer.sendPassword = jest.fn(); + // const result = await auth.registerUserAsync({ + // id: 'john.doe@email.com', + // name: 'John Doe', + // password: '', + // }); + + // expect(result.token).toBeDefined(); + // expect(mailer.sendPassword).toHaveBeenCalled(); + // }); + + it('throws an error if e-mail already registered', async function () { + userStorage.existAsync.mockReturnValue(new Promise(result => result(true))); + await expect(auth.registerUserAsync(johnDoeProfile)).rejects.toThrowError(); + }); + + it('throws an error if e-mail is invalid', async function () { + userStorage.existAsync.mockReturnValue(new Promise(result => result(false))); + await expect(auth.registerUserAsync({ + id: 'invalid', + name: 'John Doe', + password: '12345678' + })).rejects.toThrowError(); + }); + + it('throws an error if password is invalid', async function () { + userStorage.existAsync.mockReturnValue(new Promise(result => result(false))); + await expect(auth.registerUserAsync({ + id: 'john.doe@email.com', + name: 'John Doe', + password: '1' + })).rejects.toThrowError(); + }); + }); + + describe('resetPasswordAsync', function () { + it('sends a new password via e-mail', async function () { + userStorage.readAsync.mockReturnValue(new Promise(result => result(johnDoeData))); + mailer.sendNewPassword = jest.fn(); + await expect(auth.resetPasswordAsync('john.doe@email.com')).resolves.toBeUndefined(); + expect(mailer.sendNewPassword).toHaveBeenCalled(); + }); + }); + + describe('deleteUserAsync', function () { + it('deletes the account of a registered user', async function () { + userStorage.deleteAsync.mockReturnValue(new Promise(result => result(true))); + await expect(auth.deleteUserAsync('john.doe@email.com')).resolves.toBeUndefined(); + }); + + it('throws an error if user is unknown', async function () { + userStorage.deleteAsync.mockReturnValue(new Promise(result => result(false))); + await expect(auth.deleteUserAsync('john.doe@email.com')).rejects.toThrowError(); + }); + }); + + describe('hasUserAsync', function () { + it('authorizes John Doe', async function () { + userStorage.existAsync.mockReturnValue(new Promise(result => result(true))); + await expect(auth.hasUserAsync('john.doe@email.com')).resolves.toBe(true); + }); + + it('does not authorize a guest', async function () { + userStorage.existAsync.mockReturnValue(new Promise(result => result(false))); + await expect(auth.hasUserAsync('unknown')).resolves.toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/auth/locale-cookie-storage.spec.ts b/projects/aas-server/src/test/auth/locale-cookie-storage.spec.ts new file mode 100644 index 00000000..ee81c900 --- /dev/null +++ b/projects/aas-server/src/test/auth/locale-cookie-storage.spec.ts @@ -0,0 +1,117 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import fs from 'fs'; +import { Cookie } from 'common'; +import { CookieStorage } from '../../app/auth/cookie-storage.js'; +import { LocaleCookieStorage } from '../../app/auth/locale-cookie-storage.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import { createSpyObj } from '../utils.js'; +import { Logger } from '../../app/logging/logger.js'; + +describe('LocaleCookieStorage', function () { + let usersDir: string; + let cookieStorage: CookieStorage; + let cookies: Cookie[]; + + beforeEach(async function () { + usersDir = '/users'; + cookies = [ + { + name: 'Cookie1', + data: 'The quick brown fox jumps over the lazy dog.' + }, + { + name: 'Cookie2', + data: '42' + } + ]; + + jest.spyOn(fs.promises, 'readFile').mockImplementation(() => { + return new Promise(resolve => resolve(Buffer.from(JSON.stringify(cookies)))); + }); + + cookieStorage = new LocaleCookieStorage(createSpyObj(['error']), usersDir); + }); + + describe('checkAsync', function () { + it('indicates that "Cookie1" for john.doe@email.com exist', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + await expect(cookieStorage.checkAsync('john.doe@email.com', 'Cookie1')).resolves.toBe(true); + }); + + it('indicates that "unknown" for john.doe@email.com not exist', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + await expect(cookieStorage.checkAsync('john.doe@email.com', 'unknown')).resolves.toBe(false); + }); + + it('indicates that "Cookie1" for jane.doe@email.com not exist', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => false); + await expect(cookieStorage.checkAsync('jane.doe@email.com', 'Cookie1')).resolves.toBe(false); + }); + }); + + // describe('getAsync', function () { + // it('returns the value of "Cookie1" for john.doe@email.com', async function () { + // await expect(cookieStorage.getAsync('john.doe@email.com', 'Cookie1')) + // .resolves.toEqual({ name: 'Cookie1', data: 'The quick brown fox jumps over the lazy dog.' }); + // }); + + // it('returns "undefined" for "unknown" for john.doe@email.com', async function () { + // await expect(cookieStorage.getAsync('john.doe@email.com', 'unknown')) + // .resolves.toBeUndefined(); + // }); + + // it('returns "undefined" for "Cookie1" for jane.doe@email.com', async function () { + // await expect(cookieStorage.getAsync('jane.doe@email.com', 'unknown')) + // .resolves.toBeUndefined(); + // }); + // }); + + // describe('getAllAsync', function () { + // it('returns all cookies for john.doe@email.com', async function () { + // await expect(cookieStorage.getAllAsync('john.doe@email.com')) + // .resolves.toEqual([ + // { + // name: 'Cookie1', + // data: 'The quick brown fox jumps over the lazy dog.' + // }, + // { + // name: 'Cookie2', + // data: '42' + // } + // ]); + // }); + // }); + + // describe('setAsync', function () { + // it('can set a new Cookie3 for john.doe@email.com', async function () { + // await cookieStorage.setAsync('john.doe@email.com', 'Cookie3', 'Hello World!'); + // let items = JSON.parse((await readFile(join(userDir, 'cookies.json'))).toString()) as Cookie[]; + // expect(items.find(item => item.name === 'Cookie3')).toEqual({ name: 'Cookie3', data: 'Hello World!' } as Cookie); + // }); + + // it('can update the existing Cookie2 for john.doe@email.com', async function () { + // await cookieStorage.setAsync('john.doe@email.com', 'Cookie2', 'Hello World!'); + // let items = JSON.parse((await readFile(join(userDir, 'cookies.json'))).toString()) as Cookie[]; + // expect(items.find(item => item.name === 'Cookie2')).toEqual({ name: 'Cookie2', data: 'Hello World!' } as Cookie); + // }); + // }); + + // describe('deleteAsync', function () { + // it('can delete a cookie', async function () { + // await cookieStorage.deleteAsync('john.doe@email.com', 'Cookie1'); + // let items = JSON.parse((await readFile(join(userDir, 'cookies.json'))).toString()) as Cookie[]; + // expect(items.find(item => item.name === 'Cookie1')).toBeUndefined(); + + // await cookieStorage.deleteAsync('john.doe@email.com', 'Cookie2'); + // expect(existsSync(join(userDir, 'cookies.json'))).toBeFalsy(); + // }); + // }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/auth/locale-user-storage.spec.ts b/projects/aas-server/src/test/auth/locale-user-storage.spec.ts new file mode 100644 index 00000000..0708a622 --- /dev/null +++ b/projects/aas-server/src/test/auth/locale-user-storage.spec.ts @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import fs from 'fs'; +import { UserStorage } from '../../app/auth/user-storage.js'; +import { LocaleUserStorage } from '../../app/auth/locale-user-storage.js'; +import { UserData } from '../../app/auth/user-data.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('LocaleUserStorage', function () { + let userStorage: UserStorage; + let johnDoe: UserData; + + beforeEach(function () { + johnDoe = { + id: "john.doe@email.com", + name: "John Doe", + role: "editor", + password: "$2a$10$6qZT2ZM5jUVU/pLLQUjCvuXplG.GwPnoz48C1Eg/dKqjIrGE8jm0a", + created: new Date(), + lastLoggedIn: new Date(0) + }; + + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + userStorage = new LocaleUserStorage('/users'); + }); + + describe('existsSync', function () { + it('indicates that john.doe@email.com exists', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + await expect(userStorage.existAsync('john.doe@email.com')).resolves.toBe(true); + }); + + it('indicates that unknown@email.com does not exist', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => false); + await expect(userStorage.existAsync('unknown@email.com')).resolves.toBe(false); + }); + }); + + describe('writeAsync', function () { + it('writes a new user', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => false); + jest.spyOn(fs.promises, 'mkdir').mockImplementation( + () => new Promise(resolve => resolve(undefined))); + + jest.spyOn(fs.promises, 'writeFile').mockImplementation(() => new Promise(resolve => resolve())); + await userStorage.writeAsync('jane.doe@email.com', { + id: 'jane.doe@email.com', + name: 'Jane Doe', + password: '12345678', + role: 'editor', + created: new Date(), + lastLoggedIn: new Date() + }); + + expect(fs.promises.mkdir).toHaveBeenCalled(); + expect(fs.promises.writeFile).toHaveBeenCalled(); + }); + }); + + describe('readAsync', function () { + it('reads the data of john.doe@email.com', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + jest.spyOn(fs.promises, 'readFile').mockImplementation(() => new Promise( + resolve => resolve(Buffer.from(JSON.stringify(johnDoe))))); + + await expect(userStorage.readAsync('john.doe@email.com')).resolves.toEqual(johnDoe); + }); + + it('reads "undefined" for an unknown user', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => false); + await expect(userStorage.readAsync('unknown@email.com')).resolves.toBeUndefined(); + }); + }); + + describe('deleteAsync', function () { + it('john.doe@email.com', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => true); + jest.spyOn(fs.promises, 'rm').mockImplementation(() => new Promise(resolve => resolve())); + await expect(userStorage.deleteAsync('john.doe@email.com')).resolves.toBe(true); + expect(fs.promises.rm).toHaveBeenCalled(); + }); + + it('indicates that an unknown user was not deleted', async function () { + jest.spyOn(fs, 'existsSync').mockImplementation(() => false); + await expect(userStorage.deleteAsync('unknown@email.com')).resolves.toBe(false); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/auth/mongo-db-cookie-storage.spec.ts b/projects/aas-server/src/test/auth/mongo-db-cookie-storage.spec.ts new file mode 100644 index 00000000..2ea532c0 --- /dev/null +++ b/projects/aas-server/src/test/auth/mongo-db-cookie-storage.spec.ts @@ -0,0 +1,152 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { MongoDBCookieStorage, UserCookies } from '../../app/auth/mongo-db-cookie-storage.js'; +import { describe, beforeAll, beforeEach, it, expect, jest } from '@jest/globals'; + +interface UserCookiesInstance extends UserCookies { + save(): Promise; + deleteOne: () => void; +} + +interface Promisify { + exec(): Promise; +} + +describe('MongoDBCookieStorage', function () { + let cookieStorage: MongoDBCookieStorage; + let userCookies: UserCookies; + + beforeAll(function () { + cookieStorage = new MongoDBCookieStorage(); + }); + + beforeEach(function () { + userCookies = { + id: 'john.doe@email.com', + cookies: [ + { + name: 'Cookie1', + data: 'The quick brown fox jumps over the lazy dog.' + }, + { + name: 'Cookie2', + data: '42' + } + ] + }; + }); + + describe('checkAsync', function () { + it('indicates that "Cookie1" for john.doe@email.com exist', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies)); + await expect(cookieStorage.checkAsync('john.doe@email.com', 'Cookie1')).resolves.toBe(true); + }); + + it('indicates that "unknown" for john.doe@email.com not exist', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies)); + await expect(cookieStorage.checkAsync('john.doe@email.com', 'unknown')).resolves.toBe(false); + }); + + it('indicates that "Cookie1" for jane.doe@email.com not exist', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance()); + await expect(cookieStorage.checkAsync('jane.doe@email.com', 'Cookie1')).resolves.toBe(false); + }); + }); + + describe('getAsync', function () { + it('returns the value of "Cookie1" for john.doe@email.com', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies)); + + await expect(cookieStorage.getAsync('john.doe@email.com', 'Cookie1')) + .resolves.toEqual({ name: 'Cookie1', data: 'The quick brown fox jumps over the lazy dog.' }); + }); + + it('returns "undefined" for "unknown" for john.doe@email.com', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies)); + + await expect(cookieStorage.getAsync('john.doe@email.com', 'unknown')) + .resolves.toBeUndefined(); + }); + + it('returns "undefined" for "Cookie1" for jane.doe@email.com', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance()); + + await expect(cookieStorage.getAsync('jane.doe@email.com', 'unknown')) + .resolves.toBeUndefined(); + }); + }); + + describe('getAllAsync', function () { + it('returns all cookies for john.doe@email.com', async function () { + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies)); + + await expect(cookieStorage.getAllAsync('john.doe@email.com')) + .resolves.toEqual([ + { + name: 'Cookie1', + data: 'The quick brown fox jumps over the lazy dog.' + }, + { + name: 'Cookie2', + data: '42' + } + ]); + }); + }); + + describe('setAsync', function () { + it('can set a new Cookie3 for john.doe@email.com', async function () { + let save = jest.fn<() => Promise>(); + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies, save)); + + await cookieStorage.setAsync('john.doe@email.com', 'Cookie3', 'Hello World!'); + expect(save).toHaveBeenCalled(); + }); + + it('can update the existing Cookie2 for john.doe@email.com', async function () { + let save = jest.fn<() => Promise>(); + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies, save)); + + await cookieStorage.setAsync('john.doe@email.com', 'Cookie2', 'Hello World!'); + expect(save).toHaveBeenCalled(); + }); + }); + + describe('deleteAsync', function () { + it('can delete a cookie', async function () { + let save = jest.fn<() => Promise>(); + let deleteOne = jest.fn<() => Promise>(); + jest.spyOn(cookieStorage.UserCookiesModel, 'findOne').mockReturnValue(getInstance(userCookies, save, deleteOne)); + + await cookieStorage.deleteAsync('john.doe@email.com', 'Cookie1'); + expect(save).toHaveBeenCalled(); + + await cookieStorage.deleteAsync('john.doe@email.com', 'Cookie2'); + expect(deleteOne).toHaveBeenCalled(); + }); + }); + + function getInstance(user?: UserCookies, save?: () => Promise, deleteOne?: () => Promise): any { + if (user) { + return { + exec: () => new Promise((resolve, _) => resolve( + { + ...user, + save: save ?? (() => new Promise((result, _) => result())), + deleteOne: deleteOne ?? (() => new Promise((result, _) => result())) + })) + } as Promisify; + } + + return { + exec: () => new Promise((resolve, _) => resolve(undefined)) + } as Promisify; + } +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/auth/mongo-db-user-storage.spec.ts b/projects/aas-server/src/test/auth/mongo-db-user-storage.spec.ts new file mode 100644 index 00000000..7e4cf0c9 --- /dev/null +++ b/projects/aas-server/src/test/auth/mongo-db-user-storage.spec.ts @@ -0,0 +1,96 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { MongoDBUserStorage } from '../../app/auth/mongo-db-user-storage.js'; +import { UserData } from '../../app/auth/user-data.js'; +import { describe, beforeAll, beforeEach, it, expect, jest } from '@jest/globals'; + +interface UserDataInstance extends UserData { + save(): Promise; +} + +interface Promisify { + exec(): Promise; +} + +describe('MongoDBUserStorage', function () { + let userStorage: MongoDBUserStorage; + let johnDoe: UserData; + + beforeAll(function () { + userStorage = new MongoDBUserStorage(); + }); + + beforeEach(function () { + johnDoe = { + id: "john.doe@email.com", + name: "John Doe", + role: "editor", + password: "$2a$10$6qZT2ZM5jUVU/pLLQUjCvuXplG.GwPnoz48C1Eg/dKqjIrGE8jm0a", + created: new Date(), + lastLoggedIn: new Date(0) + }; + }); + + it('indicates that john.doe@email.com exists', async function () { + jest.spyOn(userStorage.UserDataModel, 'findOne').mockReturnValue(getPromisify(johnDoe)); + await expect(userStorage.existAsync('john.doe@email.com')).resolves.toBe(true); + }); + + it('indicates that unknown@email.com does not exist', async function () { + jest.spyOn(userStorage.UserDataModel, 'findOne').mockReturnValue(getPromisify()); + await expect(userStorage.existAsync('unknown@email.com')).resolves.toBe(false); + }); + + it('reads the data of john.doe@email.com', async function () { + jest.spyOn(userStorage.UserDataModel, 'findOne').mockReturnValue(getPromisify(johnDoe)); + let user = (await userStorage.readAsync('john.doe@email.com'))!; + expect(user).toBeDefined(); + expect(user.id).toEqual(johnDoe.id); + expect(user.name).toEqual(johnDoe.name); + expect(user.role).toEqual(johnDoe.role); + expect(user.password).toEqual(johnDoe.password); + }); + + it('reads "undefined" for an unknown user', async function () { + jest.spyOn(userStorage.UserDataModel, 'findOne').mockReturnValue(getPromisify()); + await expect(userStorage.readAsync('unknown@email.com')).resolves.toBe(undefined); + }); + + it('updates the data of john.doe@email.com', async function () { + let save = jest.fn<() => Promise>(); + jest.spyOn(userStorage.UserDataModel, 'findOne').mockReturnValue(getPromisify(johnDoe, save)); + await userStorage.writeAsync('john.doe@email.com', { ...johnDoe }); + expect(save).toHaveBeenCalled + }); + + it('deletes john.doe@email.com', async function () { + jest.spyOn(userStorage.UserDataModel, 'findOneAndRemove').mockReturnValue(getPromisify(johnDoe)); + await expect(userStorage.deleteAsync('john.doe@email.com')).resolves.toBe(true); + }); + + function getPromisify(user?: UserData, save?: () => Promise): any { + if (user) { + return { + exec: () => new Promise((resolve, _) => resolve(getInstance(user, save))) + } as Promisify; + } + + return { + exec: () => new Promise((resolve, _) => resolve(undefined)) + } as Promisify; + } + + function getInstance(user: UserData, save?: () => Promise): UserDataInstance { + return { + ...user, + save: save ?? (() => new Promise((result, _) => result())) + } + } +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/configuration.spec.ts b/projects/aas-server/src/test/configuration.spec.ts new file mode 100644 index 00000000..c0e5a551 --- /dev/null +++ b/projects/aas-server/src/test/configuration.spec.ts @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { createEndpoint, getEndpointName, getEndpointType } from "../app/configuration.js"; +import { describe, it, expect } from '@jest/globals' + +describe('configuration', function () { + describe('getEndpointName', function () { + it('gets the endpoint name from an URL string', function () { + expect(getEndpointName('http://localhost:1234/?name=Test')).toEqual('Test'); + }); + + it('gets the endpoint name from a URL', function () { + expect(getEndpointName(new URL('http://localhost:1234/?name=Test'))).toEqual('Test'); + }); + + it('gets the default name of an AASX server', function () { + expect(getEndpointName('http://localhost:1234/')).toEqual('http://localhost:1234/'); + }); + + it('gets the default name of an AAS registry', function () { + expect(getEndpointName('http://localhost:1234/v1/registry?type=AASRegistry')) + .toEqual('http://localhost:1234/v1/registry'); + }); + + it('gets the default name of an OPCUA server', function () { + expect(getEndpointName(new URL('opc.tcp://172.16.160.178:30001/I4AASServer'))) + .toEqual('opc.tcp://172.16.160.178:30001/I4AASServer'); + }); + + it('gets the default name of an AASX directory', function () { + expect(getEndpointName('file:///samples')).toEqual('file:///samples'); + }); + }); + + describe('getEndpointType', function () { + it('gets the endpoint type from an URL string', function () { + expect(getEndpointType('http://localhost:1234/?type=AasxDirectory')).toEqual('AasxDirectory'); + }); + + it('gets the endpoint type from a URL', function () { + expect(getEndpointType(new URL('http://localhost:1234/?type=OpcuaServer'))).toEqual('OpcuaServer'); + }); + + it('gets "AasxServer" as default', function () { + expect(getEndpointType('http://localhost:1234/')).toEqual('AasxServer'); + }); + }); + + describe('createEndpoint', function () { + it('creates an endpoint with options', function () { + expect(createEndpoint( + 'http://localhost:1234', + { + name: 'Test', + params: [['version', '3.0']] + }).href) + .toEqual('http://localhost:1234/?name=Test&version=3.0'); + }); + + it('creates an AASX server endpoint', function () { + expect(createEndpoint('http://localhost:1234/?type=AasxServer', 'Test').href) + .toEqual('http://localhost:1234/?name=Test'); + }); + + it('creates an AAS registry endpoint', function () { + expect(createEndpoint('http://localhost:1234/v1/registry?type=AASRegistry', 'Test').href) + .toEqual('http://localhost:1234/v1/registry?name=Test&type=AASRegistry'); + }); + + it('creates an AASX directory endpoint', function () { + expect(createEndpoint('file:///storage/samples', 'Test').href) + .toEqual('file:///storage/samples?name=Test'); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/app-controller.spec.ts b/projects/aas-server/src/test/controller/app-controller.spec.ts new file mode 100644 index 00000000..566dea4d --- /dev/null +++ b/projects/aas-server/src/test/controller/app-controller.spec.ts @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; +import { Logger } from '../../app/logging/logger.js'; +import { Message, PackageInfo } from 'common'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +import { ApplicationInfo } from '../../app/application-info.js'; +import { AuthService } from '../../app/auth/auth-service.js'; +import { createSpyObj } from '../utils.js'; +import { Variable } from '../../app/variable.js'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; + +describe('AppController', function () { + let app: Express; + let logger: Logger; + let auth: jest.Mocked; + let applicationInfo: jest.Mocked; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + applicationInfo = createSpyObj(['getAsync', 'getMessages']); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance(ApplicationInfo, applicationInfo); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + it('getInfo: /api/v1/app/info', async function () { + const data: PackageInfo = { + name: "aas-portal-project", + version: "2.0.0", + description: "Web-based visualization and control of asset administration shells.", + author: "Fraunhofer IOSB-INA e.V.", + homepage: "https://www.iosb-ina.fraunhofer.de/", + license: "Apache-2.0", + libraries: [ + { + name: "Library", + version: "1.0", + description: "A library.", + license: "MIT", + homepage: "https://www.iosb-ina.fraunhofer.de/" + } + ] + }; + + applicationInfo.getAsync.mockReturnValue(new Promise(resolve => resolve(data))); + const response = await request(app) + .get('/api/v1/app/info') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual(data); + }); + + it('getMessages: /api/v1/app/messages', async function () { + const messages: Message[] = [ + { type: 'Info', text: 'An information.', timestamp: 0 }, + { type: 'Error', text: 'An error.', timestamp: 1 } + ]; + + applicationInfo.getMessages.mockReturnValue(messages); + const response = await request(app) + .get('/api/v1/app/messages') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200) + expect(response.body).toEqual(messages); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/auth-controller.spec.ts b/projects/aas-server/src/test/controller/auth-controller.spec.ts new file mode 100644 index 00000000..8ab9aba8 --- /dev/null +++ b/projects/aas-server/src/test/controller/auth-controller.spec.ts @@ -0,0 +1,188 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; +import { AuthResult, Cookie, Credentials } from 'common'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +import { AuthService } from '../../app/auth/auth-service.js'; +import { createSpyObj } from '../utils.js'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Logger } from '../../app/logging/logger.js'; +import { Variable } from '../../app/variable.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; + +describe('AuthController', function () { + let app: Express; + let auth: jest.Mocked; + let logger: Logger; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + describe('guest', function () { + it('creates a guest account', async function () { + const token = getToken(); + auth.loginAsync.mockReturnValue(new Promise(resolve => resolve({ token }))); + + const response = await request(app) + .post('/api/v1/guest'); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual({ token } as AuthResult); + }); + }); + + describe('login', function () { + it('login a registered user', async function () { + const token = getToken('John'); + auth.loginAsync.mockReturnValue(new Promise(resolve => resolve({ token }))); + + const response = await request(app) + .post('/api/v1/login') + .send({ id: 'john.doe@email.com', password: '1234.xyz' } as Credentials); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual({ token } as AuthResult); + }); + }); + + describe('getCookie', function () { + it('GET /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1', async function () { + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + auth.getCookieAsync.mockReturnValue( + new Promise(resolve => resolve({ name: 'Cookie1', data: 'Hello World!' }))); + + const response = await request(app) + .get('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1') + .set('Authorization', `Bearer ${getToken('John')}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual({ name: 'Cookie1', data: 'Hello World!' }); + }); + + // it('Unauthenticated user: GET /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1', async function () { + // authentication.checkAsync.mockReturnValue(new Promise((_, reject) => reject( + // new ApplicationError(ERRORS.UnauthorizedAccess, ERRORS.UnauthorizedAccess)))); + + // const response = await request(app).get('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1'); + // expect(response.statusCode).toBe(401); + // }); + }); + + describe('getCookies', function () { + it('GET /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies', async function () { + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + auth.getCookiesAsync.mockReturnValue( + new Promise(resolve => resolve([ + { name: 'Cookie1', data: 'Hello World!' }, + { name: 'Cookie2', data: '42' } + ]))); + + const response = await request(app) + .get('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies') + .set('Authorization', `Bearer ${getToken('John')}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual([ + { name: 'Cookie1', data: 'Hello World!' }, + { name: 'Cookie2', data: '42' } + ]); + }); + + // it('Unauthenticated user: GET /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies', async function () { + // authentication.checkAsync.mockReturnValue( + // Promise.reject(new ApplicationError(ERRORS.UnauthorizedAccess, ERRORS.UnauthorizedAccess))); + + // const response = await request(app).get('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies'); + // expect(response.statusCode).toBe(401); + // }); + }); + + describe('setCookie', function () { + it('POST /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1', async function () { + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + const response = await request(app) + .post('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1') + .send({ name: 'Cookie1', data: 'Hello World!' } as Cookie) + .set('Authorization', `Bearer ${getToken('John')}`) + .set('Accept', 'application/json'); + + expect(response.statusCode).toBe(204); + expect(auth.setCookieAsync).toHaveBeenCalled(); + }); + + // it('Unauthenticated user: POST /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1', async function () { + // authentication.checkAsync.mockReturnValue( + // Promise.reject(new ApplicationError(ERRORS.UnauthorizedAccess, ERRORS.UnauthorizedAccess))); + + // const response = await request(app) + // .post('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1') + // .send({ name: 'Cookie1', data: 'Hello World!' } as Cookie) + // .set('Accept', 'application/json'); + + // expect(response.statusCode).toBe(401); + // }); + }); + + describe('deleteCookie', function () { + it('DELETE /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1', async function () { + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + const response = await request(app) + .delete('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1') + .set('Authorization', `Bearer ${getToken('John')}`); + + expect(response.statusCode).toBe(204); + expect(auth.deleteCookieAsync).toHaveBeenCalled(); + }); + + // it('Unauthenticated user: DELETE /api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1', async function () { + // authentication.checkAsync.mockReturnValue( + // Promise.reject(new ApplicationError(ERRORS.UnauthorizedAccess, ERRORS.UnauthorizedAccess))); + + // const response = await request(app).delete('/api/v1/users/am9obi5kb2VAZW1haWwuY29t/cookies/Cookie1'); + // expect(response.statusCode).toBe(401); + // }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/containers-controller.spec.ts b/projects/aas-server/src/test/controller/containers-controller.spec.ts new file mode 100644 index 00000000..f6eeaca5 --- /dev/null +++ b/projects/aas-server/src/test/controller/containers-controller.spec.ts @@ -0,0 +1,255 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; +import { Readable } from 'stream'; +import { resolve } from 'path'; +import { aas } from 'common'; + +import { Logger } from '../../app/logging/logger.js'; +import { AuthService } from '../../app/auth/auth-service.js'; +import { AASProvider } from '../../app/aas-provider/aas-provider.js'; +import { sampleDocument } from '../assets/sample-document.js'; +import { Container } from '../../app/aas-provider/container.js'; +import { createSpyObj } from '../utils.js'; +import { Variable } from '../../app/variable.js'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; + +describe('ContainersController', function () { + let app: Express; + let logger: Logger; + let auth: jest.Mocked; + let aasProvider: jest.Mocked; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + aasProvider = createSpyObj( + [ + 'updateDocumentAsync', + 'getWorkspaces', + 'getContainer', + 'getContentAsync', + 'getDocuments', + 'getDocument', + 'getDocumentAsync', + 'addDocumentsAsync', + 'deleteDocumentAsync', + 'getDataElementValueAsync', + 'invoke', + 'resetAsync' + ]); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance(AASProvider, aasProvider); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + it('getDocuments: /api/v1/containers/:url/documents', async function () { + aasProvider.getDocuments.mockReturnValue([sampleDocument]); + const response = await request(app) + .get('/api/v1/containers/aHR0cDovL2xvY2FsaG9zdC90ZXN0L2NvbnRhaW5lcg/documents') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual([sampleDocument]); + expect(aasProvider.getDocuments).toHaveBeenCalled(); + }); + + it('getDocument: /api/v1/containers/:url/documents/:id', async function () { + aasProvider.getDocumentAsync.mockReturnValue(new Promise(resolve => { + const s = new Readable(); + s.push('Hello World!'); + s.push(null); + resolve(s); + })); + + const response = await request(app) + .get(`/api/v1/containers/aHR0cDovL2xvY2FsaG9zdC90ZXN0L2NvbnRhaW5lcg/documents/aHR0cDovL2N1c3RvbWVyLmNvbS9hYXMvOTE3NV83MDEzXzcwOTFfOTE2OA`) + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toBeTruthy(); + expect(aasProvider.getDocumentAsync).toHaveBeenCalled(); + }); + + it('addDocuments: /api/v1/containers/:url/documents', async function () { + const container = createSpyObj({}, { url: new URL('file:///samples') }); + aasProvider.getContainer.mockReturnValue(container); + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + const response = await request(app) + .post('/api/v1/containers/ZmlsZTovLy9zYW1wbGVz/documents') + .set('Authorization', `Bearer ${getToken('John')}`) + .attach('files', resolve('./src/test/assets/samples/example-motor.aasx')); + + expect(response.statusCode).toBe(204); + expect(aasProvider.addDocumentsAsync).toHaveBeenCalled(); + }); + + it('deleteDocument: /api/v1/containers/:url/documents/:id', async function () { + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + const response = await request(app) + .delete('/api/v1/containers/aHR0cDovL2xvY2FsaG9zdC90ZXN0L2NvbnRhaW5lcg/documents/aHR0cDovL2N1c3RvbWVyLmNvbS9hYXMvOTE3NV83MDEzXzcwOTFfOTE2OA') + .set('Authorization', `Bearer ${getToken('John')}`); + + expect(response.statusCode).toBe(204); + expect(aasProvider.deleteDocumentAsync).toHaveBeenCalled(); + }); + + it('getDocumentContent: /api/v1/containers/:url/documents/:id/content', async function () { + aasProvider.getContentAsync.mockReturnValue(new Promise(resolve => { + resolve({ assetAdministrationShells: [], submodels: [], conceptDescriptions: [] }); + })); + + const response = await request(app) + .get('/api/v1/containers/Y29udGFpbmVy/documents/ZG9jdW1lbnQ/content') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(aasProvider.getContentAsync).toHaveBeenCalled(); + }); + + it('reset: /api/v1/containers/reset', async function () { + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + aasProvider.resetAsync.mockReturnValue(new Promise(resolve => resolve())); + const response = await request(app) + .delete('/api/v1/containers/reset') + .set('Authorization', `Bearer ${getToken('John')}`); + + expect(response.statusCode).toBe(204); + expect(aasProvider.resetAsync).toHaveBeenCalled(); + }); + + describe('getDataElementValue: /api/v1/containers/:url/documents/:id/submodels/:smId/submodel-elements/:path/value', function () { + it('gets the value of a File that represents an image', async function () { + aasProvider.getDataElementValueAsync.mockReturnValue(new Promise(resolve => { + const s = new Readable(); + s.push('Hello World!'); + s.push(null); + resolve(s); + })); + + const response = await request(app) + .get('/api/v1/containers/Y29udGFpbmVy/documents/ZG9jdW1lbnQ/submodels/U3VibW9kZWw/submodel-elements/collection.file/value?width=200&height=100') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(aasProvider.getDataElementValueAsync).toHaveBeenCalled(); + }); + + it('gets the value of a File', async function () { + aasProvider.getDataElementValueAsync.mockReturnValue(new Promise(resolve => { + const s = new Readable(); + s.push('Hello World!'); + s.push(null); + resolve(s); + })); + + const response = await request(app) + .get('/api/v1/containers/Y29udGFpbmVy/documents/ZG9jdW1lbnQ/submodels/U3VibW9kZWw/submodel-elements/collection.file/value') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.text).toEqual('Hello World!'); + expect(aasProvider.getDataElementValueAsync).toHaveBeenCalled(); + }); + + it('gets the value of a Blob', async function () { + aasProvider.getDataElementValueAsync.mockReturnValue(new Promise(resolve => { + const s = new Readable(); + s.push(Buffer.from('Hello world!').toString('base64')); + s.push(null); + resolve(s); + })); + + const response = await request(app) + .get(`/api/v1/containers/Y29udGFpbmVy/documents/ZG9jdW1lbnQ/submodels/U3VibW9kZWw/submodel-elements/collection.blob/value`) + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.text).toEqual(Buffer.from('Hello world!').toString('base64')); + expect(aasProvider.getDataElementValueAsync).toHaveBeenCalled(); + }); + }); + + it('updateDocument: /api/v1/containers/:url/documents/:id', async function () { + const content: aas.Environment = { + assetAdministrationShells: [], + submodels: [], + conceptDescriptions: [] + }; + + aasProvider.updateDocumentAsync.mockReturnValue(Promise.resolve([])); + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + + const url = Buffer.from('http://localhost/container').toString('base64url'); + const id = Buffer.from('http://localhost/document').toString('base64url'); + + const response = await request(app) + .put(`/api/v1/containers/${url}/documents/${id}`) + .set('Authorization', `Bearer ${getToken('John')}`) + .send(content); + + expect(response.statusCode).toBe(200); + expect(aasProvider.updateDocumentAsync).toHaveBeenCalled(); + }); + + it('invokeOperation: /api/v1/containers/:url/documents/:id/invoke', async function () { + const operation: aas.Operation = { + idShort: 'noop', + modelType: 'Operation', + }; + + aasProvider.invoke.mockReturnValue(Promise.resolve(operation)); + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + + const url = Buffer.from('http://localhost/container').toString('base64url'); + const id = Buffer.from('http://localhost/document').toString('base64url'); + const response = await request(app) + .post(`/api/v1/containers/${url}/documents/${id}/invoke`) + .set('Authorization', `Bearer ${getToken('John')}`) + .send(operation); + + expect(response.statusCode).toBe(200); + expect(aasProvider.invoke).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/documents-controller.spec.ts b/projects/aas-server/src/test/controller/documents-controller.spec.ts new file mode 100644 index 00000000..26c06037 --- /dev/null +++ b/projects/aas-server/src/test/controller/documents-controller.spec.ts @@ -0,0 +1,94 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; + +import { Logger } from '../../app/logging/logger.js'; +import { AuthService } from '../../app/auth/auth-service.js'; +import { AASProvider } from '../../app/aas-provider/aas-provider.js'; +import { sampleDocument } from '../assets/sample-document.js'; +import { createSpyObj } from '../utils.js'; +import { Variable } from '../../app/variable.js'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; + +describe('DocumentsController', function () { + let app: Express; + let logger: Logger; + let auth: jest.Mocked; + let aasProvider: jest.Mocked; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + + aasProvider = createSpyObj( + [ + 'updateDocumentAsync', + 'getWorkspaces', + 'getContainer', + 'getContentAsync', + 'getDocuments', + 'getDocument', + 'getDocumentAsync', + 'addDocumentsAsync', + 'deleteDocumentAsync', + 'getDataElementValueAsync', + 'invoke', + 'resetAsync' + ]); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance(AASProvider, aasProvider); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + it('getDocument: /api/v1/documents/:id', async function () { + aasProvider.getDocument.mockReturnValue(sampleDocument); + const response = await request(app) + .get('/api/v1/documents/aHR0cDovL2N1c3RvbWVyLmNvbS9hYXMvOTE3NV83MDEzXzcwOTFfOTE2OA') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual(sampleDocument); + expect(aasProvider.getDocument).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/endpoints-controller.spec.ts b/projects/aas-server/src/test/controller/endpoints-controller.spec.ts new file mode 100644 index 00000000..9aa02222 --- /dev/null +++ b/projects/aas-server/src/test/controller/endpoints-controller.spec.ts @@ -0,0 +1,95 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; + +import { Logger } from '../../app/logging/logger.js'; +import { AuthService } from '../../app/auth/auth-service.js'; +import { AASProvider } from '../../app/aas-provider/aas-provider.js'; +import { createSpyObj } from '../utils.js'; +import { Variable } from '../../app/variable.js'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; + +describe('EndpointsController', function () { + let app: Express; + let logger: Logger; + let auth: jest.Mocked; + let aasProvider: jest.Mocked; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + aasProvider = createSpyObj( + [ + 'addEndpointAsync', + 'removeEndpointAsync', + ]); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance(AASProvider, aasProvider); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + it('POST: /api/v1/endpoints/:name', async function () { + const url = new URL('file:///assets/samples'); + url.searchParams.append('type', 'AasxDirectory'); + aasProvider.addEndpointAsync.mockReturnValue(new Promise(resolve => resolve())); + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + const response = await request(app).post('/api/v1/endpoints/samples') + .set('Authorization', `Bearer ${getToken('John')}`) + .send({ url: url.href }); + + expect(response.statusCode).toBe(204); + expect(aasProvider.addEndpointAsync).toHaveBeenCalled(); + }); + + it('DELETE: /api/v1/endpoints/:name', async function () { + aasProvider.removeEndpointAsync.mockReturnValue(new Promise(resolve => resolve())); + auth.hasUserAsync.mockReturnValue(new Promise(resolve => resolve(true))); + const response = await request(app) + .delete('/api/v1/endpoints/samples') + .set('Authorization', `Bearer ${getToken('John')}`); + + expect(response.statusCode).toBe(204); + expect(aasProvider.removeEndpointAsync).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/templates-controller.spec.ts b/projects/aas-server/src/test/controller/templates-controller.spec.ts new file mode 100644 index 00000000..9e941c71 --- /dev/null +++ b/projects/aas-server/src/test/controller/templates-controller.spec.ts @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; + +import { Logger } from '../../app/logging/logger.js'; +import { TemplateDescriptor } from 'common'; +import { AuthService } from '../../app/auth/auth-service.js'; +import { createSpyObj } from '../utils.js'; +import { Variable } from '../../app/variable.js'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; +import { TemplateStorage } from '../../app/template/template-storage.js'; + +describe('TemplateController', function () { + let app: Express; + let logger: Logger; + let auth: jest.Mocked; + let templateStorage: jest.Mocked; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + templateStorage = createSpyObj(['readAsync']); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance('TemplateStorage', templateStorage); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + it('getTemplates: /api/v1/templates', async function () { + const templates: TemplateDescriptor[] = [{ name: 'TestTemplate' }]; + templateStorage.readAsync.mockReturnValue(new Promise(resolve => resolve(templates))); + const response = await request(app) + .get('/api/v1/templates') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200) + expect(response.body).toEqual(templates); + expect(templateStorage.readAsync).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/controller/workspaces-controller.spec.ts b/projects/aas-server/src/test/controller/workspaces-controller.spec.ts new file mode 100644 index 00000000..6f2c63a0 --- /dev/null +++ b/projects/aas-server/src/test/controller/workspaces-controller.spec.ts @@ -0,0 +1,87 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { container } from 'tsyringe'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import express, { Express, json, urlencoded } from 'express'; +import morgan from 'morgan'; +import request from 'supertest'; + +import { Logger } from '../../app/logging/logger.js'; +import { AuthService } from '../../app/auth/auth-service.js'; +import { AASProvider } from '../../app/aas-provider/aas-provider.js'; +import { Variable } from '../../app/variable.js'; +import { createSpyObj } from '../utils.js'; +import { AASWorkspace } from 'common'; +import { getToken, guestPayload } from '../assets/json-web-token.js'; +import { RegisterRoutes } from '../../app/routes/routes.js'; +import { Authentication } from '../../app/controller/authentication.js'; +import { errorHandler } from '../assets/error-handler.js'; + +describe('WorkspacesController', function () { + let app: Express; + let logger: Logger; + let auth: jest.Mocked; + let aasProvider: jest.Mocked; + let variable: jest.Mocked; + let authentication: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + variable = createSpyObj({}, { JWT_SECRET: 'SecretSecretSecretSecretSecretSecret' }); + auth = createSpyObj( + [ + 'hasUserAsync', + 'loginAsync', + 'getCookieAsync', + 'getCookiesAsync', + 'setCookieAsync', + 'deleteCookieAsync' + ]); + + aasProvider = createSpyObj( + [ + 'getWorkspaces', + ]); + + authentication = createSpyObj(['checkAsync']); + authentication.checkAsync.mockResolvedValue(guestPayload); + + container.registerInstance(AuthService, auth); + container.registerInstance('Logger', logger); + container.registerInstance(Variable, variable); + container.registerInstance(AASProvider, aasProvider); + container.registerInstance(Authentication, authentication); + + app = express(); + app.use(json()); + app.use(urlencoded({ extended: true })); + app.use(morgan('dev')); + app.set('trust proxy', 1); + + RegisterRoutes(app); + app.use(errorHandler); + }); + + it('getWorkspaces: /api/v1/workspaces', async function () { + const workspace: AASWorkspace = { + name: 'Test', + containers: [] + }; + + aasProvider.getWorkspaces.mockReturnValue([workspace]); + const response = await request(app) + .get('/api/v1/workspaces') + .set('Authorization', `Bearer ${getToken()}`); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual([workspace]); + expect(aasProvider.getWorkspaces).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/convert.spec.ts b/projects/aas-server/src/test/convert.spec.ts new file mode 100644 index 00000000..98ddb084 --- /dev/null +++ b/projects/aas-server/src/test/convert.spec.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { decodeBase64Url, encodeBase64Url } from '../app/convert.js'; +import { describe, it, expect } from '@jest/globals'; + +describe('convert', function () { + describe('atob', function () { + it('converts ascii to base64', function () { + expect(encodeBase64Url('https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237')) + .toEqual('aHR0cHM6Ly9pb3NiLWluYS5mcmF1bmhvZmVyLmRlL2lkcy9hYXMvNTE3NF83MDAxXzAxMjJfOTIzNw'); + }); + }); + + describe('btoa', function () { + it('converts base64 to ascii', function () { + expect(decodeBase64Url('aHR0cHM6Ly9pb3NiLWluYS5mcmF1bmhvZmVyLmRlL2lkcy9hYXMvNTE3NF83MDAxXzAxMjJfOTIzNw')) + .toEqual('https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237'); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/image-processing.spec.ts b/projects/aas-server/src/test/image-processing.spec.ts new file mode 100644 index 00000000..c6ed17fc --- /dev/null +++ b/projects/aas-server/src/test/image-processing.spec.ts @@ -0,0 +1,26 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import fs from 'fs'; +import Jimp from 'jimp'; +import { ImageProcessing } from '../app/image-processing.js'; +import { describe, it, expect } from '@jest/globals'; + +describe('image processing', function () { + it('resizes an image to 128 x 128 pixels', async function () { + const source = fs.createReadStream('./src/test/assets/thumbnail.jpg'); + const stream = await ImageProcessing.resizeAsync(source, 128, 128); + expect(stream).toBeTruthy(); + }); + + it('converts a tiff-image to a png-image', async function() { + const source = fs.createReadStream('./src/test/assets/image.tiff'); + const stream = await ImageProcessing.convertAsync(source, Jimp.MIME_PNG); + expect(stream).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/live/http/http-subscription.spec.ts b/projects/aas-server/src/test/live/http/http-subscription.spec.ts new file mode 100644 index 00000000..71af53db --- /dev/null +++ b/projects/aas-server/src/test/live/http/http-subscription.spec.ts @@ -0,0 +1,70 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Logger } from '../../../app/logging/logger.js'; +import { HttpSubscription } from '../../../app/live/http/http-subscription.js'; +import { SocketClient } from '../../../app/live/socket-client.js'; +import { aas, LiveRequest } from 'common'; +import { AasxServer } from '../../../app/packages/aasx-server/aasx-server.js'; +import env from '../../assets/aas-environment.js'; +import { createSpyObj, DoneFn } from '../../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('HttpSubscription', function () { + let aasxServer: jest.Mocked; + let logger: jest.Mocked; + let client: jest.Mocked; + let subscription: HttpSubscription; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + client = createSpyObj(['has', 'subscribe', 'notify']); + aasxServer = createSpyObj( + ['getShellsAsync', 'commitAsync', 'openFileAsync', 'readValueAsync', 'resolveNodeId']); + + const reference: aas.Reference = { + type: 'ModelReference', + keys: [{ + type: 'Submodel', + value: 'http://i40.customer.com/type/1/1/F13E8576F6488342' + }, + { + type: 'Property', + value: 'GLN', + }] + }; + + const request: LiveRequest = { + type: 'file', + url: 'file://doc', + id: 'http://customer.com/aas/9175_7013_7091_9168', + nodes: [{ + nodeId: JSON.stringify(reference), + valueType: 'xs:integer' + }], + }; + + subscription = new HttpSubscription(logger, aasxServer, client, request, env); + }); + + it('should be created', function () { + expect(subscription).toBeTruthy(); + }); + + it('open/close subscription', function (done: DoneFn) { + jest.useFakeTimers(); + aasxServer.readValueAsync.mockReturnValue(new Promise(result => { + expect(true).toBeTruthy(); + result(42); + subscription.close(); + done(); + })); + + subscription.open(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/live/http/opcua-socket-item.spec.ts b/projects/aas-server/src/test/live/http/opcua-socket-item.spec.ts new file mode 100644 index 00000000..7ec7f11f --- /dev/null +++ b/projects/aas-server/src/test/live/http/opcua-socket-item.spec.ts @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { Logger } from '../../../app/logging/logger.js'; +import { createSpyObj } from '../../utils.js'; +import { SocketClient } from '../../../app/live/socket-client.js'; +import { HttpSocketItem } from '../../../app/live/http/http-socket-item.js'; + +describe('HttpSocketItem', function () { + let item: HttpSocketItem; + let logger: jest.Mocked; + let client: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + client = createSpyObj([]); + item = new HttpSocketItem({ nodeId: '', valueType: 'xs:integer' }, 'http://localhost:1234'); + }); + + it('should be created', function() { + expect(item).toBeTruthy(); + expect(item.url).toEqual('http://localhost:1234'); + expect(item.node).toEqual({ nodeId: '', valueType: 'xs:integer' }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/live/opcua/opcua-socket-item.spec.ts b/projects/aas-server/src/test/live/opcua/opcua-socket-item.spec.ts new file mode 100644 index 00000000..d04b4ead --- /dev/null +++ b/projects/aas-server/src/test/live/opcua/opcua-socket-item.spec.ts @@ -0,0 +1,40 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { OpcuaSocketItem } from '../../../app/live/opcua/opcua-socket-item.js'; +import { Logger } from '../../../app/logging/logger.js'; +import { createSpyObj } from '../../utils.js'; +import { SocketClient } from '../../../app/live/socket-client.js'; +import { ClientMonitoredItem } from 'node-opcua'; + +describe('OpcuaSocketItem', function () { + let item: OpcuaSocketItem; + let logger: jest.Mocked; + let client: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + client = createSpyObj([]); + item = new OpcuaSocketItem(logger, client, { nodeId: '', valueType: 'xs:integer' }); + }); + + it('should be created', function() { + expect(item).toBeTruthy(); + }); + + it('can subscribe/unsubscribe', function() { + const monitoredItem = createSpyObj(['on', 'off', 'terminate']); + item.subscribe(monitoredItem); + expect(monitoredItem.on).toHaveBeenCalled(); + + item.unsubscribe(); + expect(monitoredItem.off).toHaveBeenCalled(); + expect(monitoredItem.terminate).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/live/opcua/opcua-subscription.spec.ts b/projects/aas-server/src/test/live/opcua/opcua-subscription.spec.ts new file mode 100644 index 00000000..e2e89da6 --- /dev/null +++ b/projects/aas-server/src/test/live/opcua/opcua-subscription.spec.ts @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { OpcuaSubscription } from '../../../app/live/opcua/opcua-subscription.js'; +import { createSpyObj } from '../../utils.js'; +import { Logger } from '../../../app/logging/logger.js'; +import { SocketClient } from '../../../app/live/socket-client.js'; +import { OpcuaServer } from '../../../app/packages/opcua/opcua-server.js'; + +describe('OpcuaSubscription', function () { + let subscription: OpcuaSubscription; + let logger: jest.Mocked; + let client: jest.Mocked; + let server: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + client = createSpyObj(['has', 'subscribe', 'notify']); + server = createSpyObj(['getSession']); + subscription = new OpcuaSubscription(logger, client, server, [{ + nodeId: 'ns=1;i=42', + valueType: 'xs:integer' + }]); + }); + + it('should be created', function() { + expect(subscription).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/live/socket-client.spec.ts b/projects/aas-server/src/test/live/socket-client.spec.ts new file mode 100644 index 00000000..fb8919f2 --- /dev/null +++ b/projects/aas-server/src/test/live/socket-client.spec.ts @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import { WebSocket } from 'ws'; +import { SocketClient } from '../../app/live/socket-client.js'; +import { createSpyObj } from '../utils.js'; +import { SocketSubscription } from '../../app/live/socket-subscription.js'; + +describe('SocketClient', function () { + let client: SocketClient; + let ws: jest.Mocked; + + beforeEach(function () { + ws = createSpyObj(['on', 'send']); + client = new SocketClient(ws); + }); + + it('should be created', function () { + expect(client).toBeTruthy(); + }); + + it('can subscribe for notifications', function () { + expect(client.has('test')).toBeFalsy(); + const subscription = createSpyObj(['open', 'close']); + client.subscribe('test', subscription); + expect(client.has('test')).toBeTruthy(); + + client.notify({ type: 'test', data: 42 }); + expect(ws.send).toHaveBeenCalled(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/memory-logger.spec.ts b/projects/aas-server/src/test/memory-logger.spec.ts new file mode 100644 index 00000000..805b7a7b --- /dev/null +++ b/projects/aas-server/src/test/memory-logger.spec.ts @@ -0,0 +1,128 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import { MemoryLogger, MemoryLoggerLevel } from '../app/logging/memory-logger.js'; +import { DebugConsole } from '../app/logging/logger.js'; +import { createSpyObj } from './utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('MemoryLogger', function () { + describe('log level Info', function () { + let logger: MemoryLogger; + + beforeEach(function () { + logger = new MemoryLogger( + MemoryLoggerLevel.Info, + createSpyObj(['debug'])); + }); + + it('should create', function () { + expect(logger).toBeTruthy(); + }); + + it('logs all message types', function () { + logger.start('test'); + logger.info('This is an info.'); + logger.warning('This is a warning.'); + logger.error('This is an error'); + logger.stop(); + expect(logger.getMessages().length).toEqual(3); + }); + + it('logs message objects', function () { + logger.start('test'); + logger.log({ type: 'Info', text: 'This is an info.', timestamp: Date.now() }); + logger.log({ type: 'Warning', text: 'This is a warning.', timestamp: Date.now() }); + logger.log({ type: 'Error', text: 'This is an error.', timestamp: Date.now() }); + logger.stop(); + expect(logger.getMessages().length).toEqual(3); + }); + + it('logs only different errors', function () { + logger.start('test'); + logger.error('This is a first error.'); + logger.error(new Error('This is a first error.')); + logger.error('This is a seconde error.'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + + it('logs only different warnings', function () { + logger.start('test'); + logger.warning('This is a first warning.'); + logger.warning('This is a first warning.'); + logger.warning('This is a seconde warning.'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + + it('logs only different info messages', function () { + logger.start('test'); + logger.info('This is a first info.'); + logger.info('This is a seconde info.'); + logger.info('This is a seconde info.'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + }); + + describe('log level Error', function () { + let logger: MemoryLogger; + + beforeEach(function () { + logger = new MemoryLogger(MemoryLoggerLevel.Error, createSpyObj(['debug'])); + }); + + it('logs ony errors', function () { + logger.start('test'); + logger.info('This is an info.'); + logger.warning('This is a warning.'); + logger.error('This is an error'); + logger.stop(); + expect(logger.getMessages().length).toEqual(1); + }); + }); + + describe('log level Warning', function () { + let logger: MemoryLogger; + + beforeEach(function () { + logger = new MemoryLogger(MemoryLoggerLevel.Warning, createSpyObj(['debug'])); + }); + + it('logs ony errors and warnings', function () { + logger.start('test'); + logger.info('This is an info.'); + logger.warning('This is a warning.'); + logger.error('This is an error'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + }); + + describe('log debug', function () { + let logger: MemoryLogger; + let console: jest.Mocked; + + beforeEach(function () { + console = createSpyObj(['debug']); + logger = new MemoryLogger(MemoryLoggerLevel.All, console); + }); + + it('logs debug messages to a console', function () { + logger.debug('This is a debug message.'); + expect(console.debug).toHaveBeenCalled(); + }); + + it('logs errors to a console', function () { + logger.debug(new Error('This is a debug message.')); + expect(console.debug).toHaveBeenCalled(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/messages.txt b/projects/aas-server/src/test/messages.txt new file mode 100644 index 00000000..a4369f44 --- /dev/null +++ b/projects/aas-server/src/test/messages.txt @@ -0,0 +1,3 @@ +{"level":"info","message":"This is an info.","timestamp":"2022-01-03T18:42:24.474Z"} +{"level":"error","message":"Scanning OPC-UA server 'opc.tcp://172.16.160.188:30001/I4AASServer' failed: The connection cannot be established with server opc.tcp://172.16.160.188:30001/I4AASServer .\nPlease check that the server is up and running or your network configuration.\nErr = (connect ECONNREFUSED 172.16.160.188:30001)","timestamp":"2022-01-03T18:42:40.173Z"} +{"level":"warn","message":"This is a warning","timestamp":"2022-01-03T18:43:17.745Z"} \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/aasx-server/aasx-package.spec.ts b/projects/aas-server/src/test/packages/aasx-server/aasx-package.spec.ts new file mode 100644 index 00000000..709cee69 --- /dev/null +++ b/projects/aas-server/src/test/packages/aasx-server/aasx-package.spec.ts @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AasxPackage } from '../../../app/packages/aasx-directory/aasx-package.js' +import { AasxDirectory } from '../../../app/packages/aasx-directory/aasx-directory.js'; +import { Logger } from '../../../app/logging/logger.js'; +import { LocalFileStorage } from '../../../app/file-storage/local-file-storage.js'; +import { createSpyObj, fail } from '../../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; +import { FileStorage } from '../../../app/file-storage/file-storage.js'; + +describe('AasxPackage', function () { + let logger: jest.Mocked; + let source: AasxDirectory; + let fileStorage: FileStorage; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + fileStorage = new LocalFileStorage('./src/test/assets/samples'); + source = new AasxDirectory(logger, 'file:///samples', fileStorage); + }); + + describe('createDocumentAsync', function () { + it('creates a document from a xml origin', async function () { + try { + await source.openAsync(); + const aasxPackage = new AasxPackage(logger, source, 'xml-origin.aasx'); + const document = aasxPackage.createDocumentAsync(); + expect(document).toBeDefined(); + } catch (error) { + fail(error?.message) + } finally { + await source.closeAsync(); + } + }); + + it('creates a document from a json origin', async function () { + try { + await source.openAsync(); + const aasxPackage = new AasxPackage(logger, source, 'json-origin.aasx'); + const document = aasxPackage.createDocumentAsync(); + expect(document).toBeDefined(); + } catch (error) { + fail(error?.message); + } finally { + await source.closeAsync(); + } + }); + }); +}); diff --git a/projects/aas-server/src/test/packages/aasx-server/aasx-server-package.spec.ts b/projects/aas-server/src/test/packages/aasx-server/aasx-server-package.spec.ts new file mode 100644 index 00000000..b0022895 --- /dev/null +++ b/projects/aas-server/src/test/packages/aasx-server/aasx-server-package.spec.ts @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { aas } from 'common'; +import { Logger } from '../../../app/logging/logger.js'; +import { AasxServer } from '../../../app/packages/aasx-server/aasx-server.js'; +import { AasxServerPackage } from '../../../app/packages/aasx-server/aasx-server-package.js'; +import { createSpyObj } from '../../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('AasxServerPackage', function () { + let aasPackage: AasxServerPackage; + let logger: jest.Mocked; + let server: jest.Mocked; + let env: aas.Environment; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + server = createSpyObj(['readEnvironmentAsync'], { + url: new URL('http:/localhost:1234'), + baseUrl: new URL('http:/localhost:1234') + }); + + aasPackage = new AasxServerPackage(logger, server, 'CunaCup_Becher1'); + env = { + assetAdministrationShells: [{ + id: 'Sample AAS', + idShort: 'http://www.fraunhofer.de/aas', + modelType: 'AssetAdministrationShell', + assetInformation: { assetKind: 'Instance' } + }], submodels: [], conceptDescriptions: [] + }; + }); + + it('creates a document', async function () { + server.readEnvironmentAsync.mockReturnValue( + new Promise((resolve, _) => resolve(env))); + + await expect(aasPackage.createDocumentAsync()).resolves.toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/aasx-server/aasx-server-v0.spec.ts b/projects/aas-server/src/test/packages/aasx-server/aasx-server-v0.spec.ts new file mode 100644 index 00000000..75f00da0 --- /dev/null +++ b/projects/aas-server/src/test/packages/aasx-server/aasx-server-v0.spec.ts @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import http, { IncomingMessage } from 'http'; +import { Socket } from 'net'; +import { AasxServer } from '../../../app/packages/aasx-server/aasx-server.js'; +import listaas from '../../assets/test-aas/listaas.js'; +import becher1 from '../../assets/test-aas/cuna-cup-becher1.js'; +import submodels from '../../assets/test-aas/submodels.js'; +import nameplate from '../../assets/test-aas/nameplate-becher1.js'; +import digitalProductPassport from '../../assets/test-aas/digital-product-passport-becher1.js'; +import customerFeedback from '../../assets/test-aas/customer-feedback-becher1.js'; +import { AasxServerV0 } from '../../../app/packages/aasx-server/aasx-server-v0.js'; +import { aas, selectElement } from 'common'; +import { Logger } from '../../../app/logging/logger.js'; +import aasEnvironment from '../../assets/aas-environment.js'; +import { createSpyObj } from '../../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('AasxServerV0', function () { + let logger: jest.Mocked; + let server: AasxServer; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + server = new AasxServerV0(logger, 'http://localhost:1234'); + }); + + it('returns the AAS list', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify(listaas)); + stream.push(null); + stream.statusCode = 200, + stream.statusMessage = 'OK', + (callback as (res: IncomingMessage) => void)(stream); + return new http.ClientRequest('http://localhost:1234'); + }); + + await expect(server.getShellsAsync()).resolves.toEqual([ + 'AssistanceSystem_Dte', + 'CunaCup_Becher1', + 'CunaCup_Becher2', + 'DTOrchestrator']); + }); + + it('gets the AAS with the specified idShort', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + let value: any; + switch ((options as http.RequestOptions).path) { + case '/aas/CunaCup_Becher1/submodels': + value = submodels; + break; + case '/aas/CunaCup_Becher1/submodels/Nameplate_Becher1/complete': + value = nameplate; + break; + case '/aas/CunaCup_Becher1/submodels/DigitalProductPassport_Becher1/complete': + value = digitalProductPassport; + break; + case '/aas/CunaCup_Becher1/submodels/CustomerFeedback_Becher1/complete': + value = customerFeedback; + break; + default: + value = becher1; + break; + } + + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify(value)); + stream.push(null); + stream.statusCode = 200, + stream.statusMessage = 'OK', + (callback as (res: IncomingMessage) => void)(stream); + + return new http.ClientRequest('http://localhost:1234'); + }); + + await expect(server.readEnvironmentAsync('CunaCup_Becher1')).resolves.toBeTruthy(); + }); + + it('can open a file', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify({ + "aaslist": [ + "0 : ExampleMotor : [IRI] http://customer.com/aas/9175_7013_7091_9168 : ", + ] + })); + stream.push(null); + stream.statusCode = 200, + stream.statusMessage = 'OK', + (callback as (res: IncomingMessage) => void)(stream); + + return new http.ClientRequest('http://localhost:1234'); + }); + + await expect( + server.openFileAsync(aasEnvironment.assetAdministrationShells[0], + selectElement(aasEnvironment, 'Documentation', 'OperatingManual', 'DigitalFile_PDF')!)).resolves.toBeTruthy(); + }); + + it('reads the current value of a data element', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify({ value: 42 })); + stream.push(null); + stream.statusCode = 200, + stream.statusMessage = 'OK', + (callback as (res: IncomingMessage) => void)(stream); + + return new http.ClientRequest('http://localhost:1234'); + }); + + await expect(server.readValueAsync('http://localhost:1234', 'xs:int')).resolves.toBe(42); + }); + + describe('resolveNodeId', function () { + let shell: jest.Mocked; + + beforeEach(function () { + shell = createSpyObj( + {}, + { idShort: 'aas1' }); + }); + + it('returns the URL to "property1"', function () { + const smId = Buffer.from('http://localhost/test/submodel1').toString('base64'); + const nodeId = smId + '.submodel1/property1'; + expect(server.resolveNodeId(shell, nodeId)).toEqual( + `http://localhost:1234/aas/aas1/submodels/submodel1/elements/property1/value`); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/aasx-server/aasx-server-v3.spec.ts b/projects/aas-server/src/test/packages/aasx-server/aasx-server-v3.spec.ts new file mode 100644 index 00000000..be62d9cc --- /dev/null +++ b/projects/aas-server/src/test/packages/aasx-server/aasx-server-v3.spec.ts @@ -0,0 +1,256 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import http, { IncomingMessage } from 'http'; + import env from '../../assets/aas-environment.js'; +import { AasxServerV3, OperationResult } from '../../../app/packages/aasx-server/aasx-server-v3.js'; +import { aas, DifferenceItem } from 'common'; +import { cloneDeep } from 'lodash-es'; +import { Socket } from 'net'; +import { Logger } from '../../../app/logging/logger.js'; +import { createSpyObj } from '../../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('AasxServerV3', function () { + let logger: Logger; + let server: AasxServerV3; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + server = new AasxServerV3(logger, 'http://localhost:1234'); + }); + + describe('resolveNodeId', function () { + let shell: jest.Mocked; + + beforeEach(function () { + shell = createSpyObj( + {}, + { id: 'http://localhost/test/aas' }); + }); + + it('returns the URL to "property1"', function () { + const aasId = Buffer.from('http://localhost/test/aas').toString('base64url'); + const smId = Buffer.from('http://localhost/test/submodel1').toString('base64url'); + const nodeId = smId + '.submodel1/property1'; + expect(server.resolveNodeId(shell, nodeId)).toEqual( + `http://localhost:1234/shells/${aasId}/aas/submodels/${smId}/submodel/submodel-elements/property1`); + }); + }); + + describe('commitAsync', function () { + let source: aas.Environment; + let destination: aas.Environment; + + beforeEach(async function () { + source = env; + destination = cloneDeep(source); + }); + + it('inserts a submodel', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Submodel inserted.')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 201; + stream.statusMessage = 'Created'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const diffs: DifferenceItem[] = [{ + type: 'inserted', + sourceElement: source.submodels[0] + }]; + + await expect(server.commitAsync(source, destination, diffs)).resolves.toEqual(['Submodel inserted.']); + }); + + it('inserts a submodel-element', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('SubmodelElement inserted.')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 201; + stream.statusMessage = 'Created'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const diffs: DifferenceItem[] = [{ + type: 'inserted', + sourceParent: source.submodels[0], + sourceElement: source.submodels[0].submodelElements![0], + destinationParent: destination.submodels[0] + }]; + + await expect(server.commitAsync(source, destination, diffs)).resolves.toEqual(['SubmodelElement inserted.']); + }); + + it('updates a submodel', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Submodel updated.')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 200; + stream.statusMessage = 'OK'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const diffs: DifferenceItem[] = [{ + type: 'changed', + sourceElement: source.submodels[0], + destinationElement: destination.submodels[0] + }]; + + await expect(server.commitAsync(source, destination, diffs)).resolves.toEqual(['Submodel updated.']); + }); + + it('updates a submodel-element', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('SubmodelElement updated.')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 200; + stream.statusMessage = 'OK'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const diffs: DifferenceItem[] = [{ + type: 'changed', + sourceParent: source.submodels[0], + sourceElement: source.submodels[0].submodelElements![0], + destinationParent: destination.submodels[0], + destinationElement: destination.submodels[0].submodelElements![0] + }]; + + await expect(server.commitAsync(source, destination, diffs)).resolves.toEqual(['SubmodelElement updated.']); + }); + + it('deletes a submodel', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Submodel deleted.')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 204; + stream.statusMessage = 'No Content'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const diffs: DifferenceItem[] = [{ + type: 'deleted', + destinationElement: destination.submodels[0] + }]; + + await expect(server.commitAsync(source, destination, diffs)).resolves.toEqual(['Submodel deleted.']); + }); + + it('deletes a submodel-element', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('SubmodelElement deleted.')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 204; + stream.statusMessage = 'No Content'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const diffs: DifferenceItem[] = [{ + type: 'deleted', + destinationParent: destination.submodels[0], + destinationElement: destination.submodels[0].submodelElements![0] + }]; + + await expect(server.commitAsync(source, destination, diffs)).resolves.toEqual(['SubmodelElement deleted.']); + }); + }); + + describe('invoke', function () { + it('invokes an operation synchronously', async function () { + const result: OperationResult = { + executionState: 'Completed', + success: true + }; + + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify(result)); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 204; + stream.statusMessage = 'No Content'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const operation: aas.Operation = { + idShort: 'noop', + modelType: 'Operation', + parent: { + type: 'ModelReference', + keys: [{ type: 'Submodel', value: 'http://i40.customer.com/type/1/1/F13E8576F6488342' }] + } + } + + await expect(server.invoke(env, operation)).resolves.toEqual(operation); + }); + + it('throws an error if the server returns with status code 500', async function () { + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 500; + stream.statusMessage = 'Internal server error.'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const operation: aas.Operation = { + idShort: 'noop', + modelType: 'Operation', + parent: { + type: 'ModelReference', + keys: [{ type: 'Submodel', value: 'http://i40.customer.com/type/1/1/F13E8576F6488342' }] + } + } + + await expect(server.invoke(env, operation)).rejects.toThrowError(); + }); + + it('throws an error if the operation fails', async function () { + const result: OperationResult = { + messages: [{messageType: 'Error', text: 'Operation failed.'}], + executionState: 'Failed', + success: false + }; + + jest.spyOn(http, 'request').mockImplementation((options, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify(result)); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 204; + stream.statusMessage = 'No Content'; + return new http.ClientRequest('http://localhost:1234'); + }); + + const operation: aas.Operation = { + idShort: 'noop', + modelType: 'Operation', + parent: { + type: 'ModelReference', + keys: [{ type: 'Submodel', value: 'http://i40.customer.com/type/1/1/F13E8576F6488342' }] + } + } + + await expect(server.invoke(env, operation)).rejects.toThrowError(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/json-reader-v2.spec.ts b/projects/aas-server/src/test/packages/json-reader-v2.spec.ts new file mode 100644 index 00000000..b34fa580 --- /dev/null +++ b/projects/aas-server/src/test/packages/json-reader-v2.spec.ts @@ -0,0 +1,34 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Logger } from '../../app/logging/logger.js'; +import { readFile } from 'fs/promises'; +import { JsonReaderV2 } from '../../app/packages/json-reader-v2.js' +import { createSpyObj } from '../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('JsonReaderV2', function () { + let reader: JsonReaderV2; + let logger: jest.Mocked; + let json: string; + + beforeEach(async function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + json = (await readFile('./src/test/assets/aas-example-v2.json')).toString(); + reader = new JsonReaderV2(logger, json); + }); + + it('should be created', function () { + expect(reader).toBeTruthy(); + }); + + it('reads the AAS environment from a JSON source', function () { + let env = reader.readEnvironment(); + expect(env).toBeDefined(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/json-reader.spec.ts b/projects/aas-server/src/test/packages/json-reader.spec.ts new file mode 100644 index 00000000..8c01aee7 --- /dev/null +++ b/projects/aas-server/src/test/packages/json-reader.spec.ts @@ -0,0 +1,35 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Logger } from '../../app/logging/logger.js'; +import { readFile } from 'fs/promises'; +import { JsonReader } from '../../app/packages/json-reader.js' +import { resolve } from 'path'; +import { createSpyObj } from '../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('JsonReader', function () { + let reader: JsonReader; + let logger: jest.Mocked; + let json: string; + + beforeEach(async function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + json = (await readFile(resolve('./src/test/assets/aas-example.json'))).toString(); + reader = new JsonReader(logger, json); + }); + + it('should be created', function () { + expect(reader).toBeTruthy(); + }); + + it('reads the AAS environment from a JSON source', function () { + let env = reader.readEnvironment(); + expect(env).toBeDefined(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/json-writer-v2.spec.ts b/projects/aas-server/src/test/packages/json-writer-v2.spec.ts new file mode 100644 index 00000000..47ddc2ae --- /dev/null +++ b/projects/aas-server/src/test/packages/json-writer-v2.spec.ts @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { JsonWriterV2 } from '../../app/packages/json-writer-v2.js'; +import env from '../assets/aas-environment.js'; +import { describe, beforeEach, it, expect } from '@jest/globals'; + +describe('JsonWriterV2', function () { + describe('writeEnvironment', function () { + let writer: JsonWriterV2; + + beforeEach(function(){ + writer = new JsonWriterV2(); + }); + + it('is not implemented', function() { + expect(() => writer.writeEnvironment(env)).toThrowError(); + }) + }); + + describe('write', function() { + let writer: JsonWriterV2; + + beforeEach(function(){ + writer = new JsonWriterV2(); + }); + + it('does not support writing an AAS', function() { + expect(() => writer.write(env.assetAdministrationShells[0])).toThrowError(); + }); + + it('writes a submodel', function() { + expect(writer.write(env.submodels[0])).toBeDefined(); + }) + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/json-writer.spec.ts b/projects/aas-server/src/test/packages/json-writer.spec.ts new file mode 100644 index 00000000..6d812464 --- /dev/null +++ b/projects/aas-server/src/test/packages/json-writer.spec.ts @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { JsonWriter } from '../../app/packages/json-writer.js'; +import env from '../assets/aas-environment.js'; +import { describe, beforeEach, it, expect } from '@jest/globals'; + +describe('JsonWriter', function () { + describe('writeEnvironment', function () { + let writer: JsonWriter; + + beforeEach(function(){ + writer = new JsonWriter(); + }); + + it('writes an AAS environment', function() { + expect(writer.writeEnvironment(env)).toBeDefined(); + }) + }); + + describe('write', function() { + let writer: JsonWriter; + + beforeEach(function(){ + writer = new JsonWriter(); + }); + + it('does not support writing an AAS', function() { + expect(() => writer.write(env.assetAdministrationShells[0])).toThrowError(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/opcua/opcua-package.spec.ts b/projects/aas-server/src/test/packages/opcua/opcua-package.spec.ts new file mode 100644 index 00000000..e3e11746 --- /dev/null +++ b/projects/aas-server/src/test/packages/opcua/opcua-package.spec.ts @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { beforeEach, describe, expect, it, jest } from "@jest/globals"; +import { OpcuaPackage } from "../../../app/packages/opcua/opcua-package.js"; +import { Logger } from "../../../app/logging/logger.js"; +import { createSpyObj } from "../../utils.js"; +import { OpcuaServer } from "../../../app/packages/opcua/opcua-server.js"; + +describe('OpcuaPackage', function () { + let aasPackage: OpcuaPackage; + let logger: jest.Mocked; + let server: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + server = createSpyObj(['openAsync', 'closeAsync', 'getSession'], { isOpen: true }); + aasPackage = new OpcuaPackage(logger, server, 'ns=1;i=42'); + }); + + it('should be created', function () { + expect(aasPackage).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/opcua/opcua-reader.spec.ts b/projects/aas-server/src/test/packages/opcua/opcua-reader.spec.ts new file mode 100644 index 00000000..903a405e --- /dev/null +++ b/projects/aas-server/src/test/packages/opcua/opcua-reader.spec.ts @@ -0,0 +1,32 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { Logger } from "../../../app/logging/logger.js"; +import { OpcuaReader } from '../../../app/packages/opcua/opcua-reader.js'; +import { OPCUAComponent } from "../../../app/packages/opcua/opcua.js"; +import { OpcuaDataTypeDictionary } from "../../../app/packages/opcua/opcua-data-type-dictionary.js"; +import { createSpyObj } from '../../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('OPCUAReader', function () { + let reader: OpcuaReader; + let logger: jest.Mocked; + let origin: jest.Mocked; + let dataTypes: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + origin = createSpyObj({}, ['displayName', 'hasProperty', 'nodeClass']); + dataTypes = createSpyObj(['get']); + reader = new OpcuaReader(logger, origin, dataTypes); + }); + + it('should be created', function () { + expect(reader).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/opcua/opcua-server.spec.ts b/projects/aas-server/src/test/packages/opcua/opcua-server.spec.ts new file mode 100644 index 00000000..805446a7 --- /dev/null +++ b/projects/aas-server/src/test/packages/opcua/opcua-server.spec.ts @@ -0,0 +1,225 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { beforeEach, describe, expect, it, jest } from '@jest/globals'; +import { OpcuaServer } from '../../../app/packages/opcua/opcua-server.js'; +import { Logger } from '../../../app/logging/logger.js'; +import { createSpyObj } from '../../utils.js'; +import { CallMethodRequestLike, CallMethodResult, ClientSession, OPCUAClient, StatusCodes, Variant } from 'node-opcua'; +import { SocketClient } from '../../../app/live/socket-client.js'; +import { LiveRequest, aas } from 'common'; +import env from '../../assets/aas-environment.js'; + +type CallMethod = (methodToCall: CallMethodRequestLike) => Promise; + +describe('OpcuaServer', function () { + let server: OpcuaServer; + let logger: jest.Mocked; + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + server = new OpcuaServer(logger, 'opc.tcp://localhost:1234/I4AASServer'); + }); + + it('should be created', function () { + expect(server).toBeTruthy(); + }); + + describe('testAsync', function () { + let client: jest.Mocked; + let session: jest.Mocked; + + beforeEach(function () { + client = createSpyObj(['connect', 'createSession', 'closeSession', 'disconnect']); + session = createSpyObj([]); + }); + + it('returns for a valid URL to an OPC-UA server', async function () { + client.connect.mockImplementation(() => new Promise(resolve => resolve())); + client.createSession.mockImplementation(() => new Promise(resolve => resolve(session))); + jest.spyOn(OPCUAClient, 'create').mockReturnValue(client); + await expect(server.testAsync()).resolves.toBeUndefined(); + }); + + it('throws an Error for an invalid URL', async function () { + client.connect.mockImplementation(() => new Promise((_, reject) => reject(new Error('Connection failed.')))); + client.createSession.mockImplementation(() => new Promise(resolve => resolve(session))); + jest.spyOn(OPCUAClient, 'create').mockReturnValue(client); + await expect(server.testAsync()).rejects.toThrowError(); + }); + }); + + describe('openAsync/closeAsync', function () { + let client: jest.Mocked; + let session: jest.Mocked; + + beforeEach(function () { + client = createSpyObj(['connect', 'createSession', 'closeSession', 'disconnect']); + session = createSpyObj([]); + }); + + it('can open/close a connection to an OPC-UA server', async function () { + client.connect.mockImplementation(() => new Promise(resolve => resolve())); + client.createSession.mockImplementation(() => new Promise(resolve => resolve(session))); + jest.spyOn(OPCUAClient, 'create').mockReturnValue(client); + await expect(server.openAsync()).resolves.toBeUndefined(); + expect(server.isOpen).toBeTruthy(); + await expect(server.closeAsync()).resolves.toBeUndefined(); + expect(server.isOpen).toBeFalsy(); + }); + }); + + describe('getSession', function () { + let client: jest.Mocked; + let session: jest.Mocked; + + beforeEach(function () { + client = createSpyObj(['connect', 'createSession', 'closeSession', 'disconnect']); + session = createSpyObj([]); + client.connect.mockImplementation(() => new Promise(resolve => resolve())); + client.createSession.mockImplementation(() => new Promise(resolve => resolve(session))); + jest.spyOn(OPCUAClient, 'create').mockReturnValue(client); + }); + + it('returns the current session', async function () { + await server.openAsync(); + expect(server.getSession()).toBe(session); + await server.closeAsync(); + }); + + it('throws an Error if no connection is established', function () { + expect(() => server.getSession()).toThrowError(); + }); + }); + + describe('createPackage', function () { + it('creates a new OpcuaPackage instance', function () { + expect(server.createPackage('ns=1;i=42')).toBeTruthy(); + }); + }); + + describe('createSubscription', function () { + it('creates a new OpcuaSubscription instance', function () { + const request: LiveRequest = { + type: 'opc', + id: 'opc.tcp://localhost:1234/I4AASServer', + url: 'http://customer.com/aas/9175_7013_7091_9168', + nodes: [{ + nodeId: 'ns=1;i=4711', + valueType: 'xs:integer' + }] + }; + + expect(server.createSubscription(createSpyObj({}), request)).toBeTruthy(); + }); + }); + + describe('getPackageAsync', function () { + it('is not implemented', function () { + expect(() => server.getPackageAsync('aasId', 'name')).toThrowError(); + }); + }); + + describe('postPackageAsync', function () { + it('is not implemented', function () { + expect(() => server.postPackageAsync(createSpyObj({}))).toThrowError(); + }); + }); + + describe('deletePackageAsync', function () { + it('is not implemented', function () { + expect(() => server.getPackageAsync('aasId', 'name')).toThrowError(); + }); + }); + + describe('invoke', function () { + let client: jest.Mocked; + let session: jest.Mocked; + + beforeEach(function () { + client = createSpyObj(['connect', 'createSession', 'closeSession', 'disconnect']); + session = createSpyObj(['call']); + client.connect.mockImplementation(() => new Promise(resolve => resolve())); + client.createSession.mockImplementation(() => new Promise(resolve => resolve(session))); + jest.spyOn(OPCUAClient, 'create').mockReturnValue(client); + }); + + it('invokes an operation', async function () { + const result = createSpyObj([], { + statusCode: StatusCodes.Good, + outputArguments: [ + { value: '3' } as Variant + ] + }); + + const call: CallMethod = () => { + return new Promise(resolve => resolve(result)); + }; + + session.call.mockImplementation(call as any); + const operation: aas.Operation = { + idShort: 'add', + modelType: 'Operation', + methodId: 'ns=1;i=4711', + objectId: 'ns=1;i=0815', + inputVariables: [ + { value: { idShort: 'a', modelType: 'Property', valueType: 'xs:int', value: '1' } as aas.Property }, + { value: { idShort: 'b', modelType: 'Property', valueType: 'xs:int', value: '2' } as aas.Property } + ], + outputVariables: [ + { value: { idShort: 'sum', modelType: 'Property', valueType: 'xs:int', value: '3' } as aas.Property }, + ], + parent: { + type: 'ModelReference', + keys: [{ type: 'Submodel', value: 'http://i40.customer.com/type/1/1/F13E8576F6488342' }] + } + }; + + await server.openAsync(); + await expect(server.invoke(env, operation)).resolves.toEqual(operation); + await server.closeAsync(); + }); + + + it('throw an Error if the call result is not "Good"', async function () { + const result = createSpyObj([], { + statusCode: StatusCodes.Bad, + outputArguments: [ + { value: '3' } as Variant + ] + }); + + const call: CallMethod = () => { + return new Promise(resolve => resolve(result)); + }; + + session.call.mockImplementation(call as any); + const operation: aas.Operation = { + idShort: 'add', + modelType: 'Operation', + methodId: 'ns=1;i=4711', + objectId: 'ns=1;i=0815', + inputVariables: [ + { value: { idShort: 'a', modelType: 'Property', valueType: 'xs:int', value: '1' } as aas.Property }, + { value: { idShort: 'b', modelType: 'Property', valueType: 'xs:int', value: '2' } as aas.Property } + ], + outputVariables: [ + { value: { idShort: 'sum', modelType: 'Property', valueType: 'xs:int', value: '3' } as aas.Property }, + ], + parent: { + type: 'ModelReference', + keys: [{ type: 'Submodel', value: 'http://i40.customer.com/type/1/1/F13E8576F6488342' }] + } + }; + + await server.openAsync(); + await expect(server.invoke(env, operation)).rejects.toThrowError(); + await server.closeAsync(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/server-message.spec.ts b/projects/aas-server/src/test/packages/server-message.spec.ts new file mode 100644 index 00000000..dcea9a59 --- /dev/null +++ b/projects/aas-server/src/test/packages/server-message.spec.ts @@ -0,0 +1,152 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import net from 'net'; +import http, { IncomingMessage } from 'http'; +import { Socket } from 'net'; +import { ServerMessage } from "../../app/packages/server-message.js"; +import { createSpyObj } from '../utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('ServerMessage', function () { + let server: ServerMessage; + + beforeEach(function () { + server = new ServerMessage(); + }); + + it('should created', function () { + expect(server).toBeTruthy(); + }); + + describe('get', function () { + beforeEach(function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Hello World!')); + stream.push(null); + stream.statusCode = 200, + stream.statusMessage = 'OK', + (callback as (res: IncomingMessage) => void)(stream); + return new http.ClientRequest('http://localhost:1234/hello/world'); + }); + }); + + it('gets an object from a server', async function () { + await expect(server.get(new URL('http://localhost:1234/hello/world'))) + .resolves.toBe('Hello World!'); + }); + }); + + describe('getResponse', function () { + beforeEach(function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Hello World!')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + return new http.ClientRequest('http://localhost:1234/hello/world'); + }); + }); + + it('gets the message response', async function () { + await expect(server.getResponse(new URL('http://localhost:1234/hello/world'))).resolves.toBeTruthy(); + }) + }); + + describe('put', function () { + beforeEach(function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('OK')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 200; + stream.statusMessage = 'OK'; + return new http.ClientRequest('http://localhost:1234/hello/world'); + }); + }); + + it('updates an object on a server', async function () { + await expect(server.put(new URL('http://localhost:1234/hello/world'), { text: 'Hello World!' })) + .resolves.toEqual('OK'); + }); + }); + + describe('post', function () { + beforeEach(function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Created')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 201; + stream.statusMessage = 'Created'; + return new http.ClientRequest('http://localhost:1234/hello/world'); + }); + }); + + it('updates an object on a server', async function () { + await expect(server.post(new URL('http://localhost:1234/hello/world'), 'Hello World!')) + .resolves.toEqual('Created'); + }); + }); + + describe('delete', function () { + beforeEach(function () { + jest.spyOn(http, 'request').mockImplementation((_, callback) => { + const stream = new IncomingMessage(new Socket()); + stream.push(JSON.stringify('Deleted')); + stream.push(null); + (callback as (res: IncomingMessage) => void)(stream); + stream.statusCode = 204; + stream.statusMessage = 'No Content'; + return new http.ClientRequest('http://localhost:1234/hello/world'); + }); + }); + + it('updates an object on a server', async function () { + await expect(server.delete(new URL('http://localhost:1234/hello/world'))) + .resolves.toEqual('Deleted'); + }); + }); + + describe('checkUrlExist', function () { + let socket: jest.Mocked; + + beforeEach(function () { + socket = createSpyObj(['setTimeout', 'on', 'end', 'destroy']); + }); + + it('validates a connection', async function () { + socket.on.mockImplementation((event, listener) => { + if (event === 'connect') { + setTimeout(() => (listener as () => void)()); + } + + return socket; + }); + + jest.spyOn(net, 'createConnection').mockReturnValue(socket); + await expect(server.checkUrlExist('http://localhost:1234')).resolves.toBeUndefined(); + }); + + it('throws an error if a connection does not exist', async function () { + socket.on.mockImplementation((event, listener) => { + if (event === 'timeout') { + setTimeout(() => (listener as () => void)()); + } + + return socket; + }); + + jest.spyOn(net, 'createConnection').mockReturnValue(socket); + await expect(server.checkUrlExist('http://localhost:9876')).rejects.toThrowError(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/packages/xml-reader.spec.ts b/projects/aas-server/src/test/packages/xml-reader.spec.ts new file mode 100644 index 00000000..8003c101 --- /dev/null +++ b/projects/aas-server/src/test/packages/xml-reader.spec.ts @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { readFile } from "fs/promises"; +import { resolve } from "path"; +import { Logger } from "../../app/logging/logger.js"; +import { XmlReader } from '../../app/packages/xml-reader.js' +import { createSpyObj } from '../utils.js'; +import { describe, beforeAll, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('XmlReader', function () { + describe('with default namespace v2.0', function () { + let reader: XmlReader; + let logger: jest.Mocked; + let xml: string; + let path: string; + + beforeAll(async function () { + path = resolve('./src/test/assets/aas-default-namespace.xml'); + xml = (await readFile(path)).toString(); + }); + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + reader = new XmlReader(logger, xml); + }); + + it('should be created', function () { + expect(reader).toBeTruthy(); + }); + + it('reads the AAS environment from a xml source', function() { + let environment = reader.readEnvironment(); + expect(environment).toBeDefined(); + }); + }); + + describe('with prefix namespace v1.0', function () { + let reader: XmlReader; + let logger: jest.Mocked; + let xml: string; + let path: string; + + beforeAll(async function () { + path = resolve('./src/test/assets/aas-prefix-namespace.xml'); + xml = (await readFile(path)).toString(); + }); + + beforeEach(function () { + logger = createSpyObj(['error', 'warning', 'info', 'debug', 'start', 'stop']); + reader = new XmlReader(logger, xml); + }); + + it('should be created', function () { + expect(reader).toBeTruthy(); + }); + + it('reads the AAS environment from a xml source', function() { + let environment = reader.readEnvironment(); + expect(environment).toBeDefined(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/src/test/utils.ts b/projects/aas-server/src/test/utils.ts new file mode 100644 index 00000000..55aa401d --- /dev/null +++ b/projects/aas-server/src/test/utils.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { expect, jest } from '@jest/globals' + +type Func = (...args: any[]) => any; + +export type SpyObjMethodNames = T extends undefined + ? ReadonlyArray | { [methodName: string]: any } + : ReadonlyArray | { [P in keyof T]?: T[P] extends Func ? ReturnType : any }; + +export type SpyObjPropertyNames = T extends undefined + ? ReadonlyArray | { [propertyName: string]: any } + : ReadonlyArray | { [P in keyof T]?: T[P] }; + +export function createSpyObj(methodNames: SpyObjMethodNames, propertyNames?: SpyObjPropertyNames): jest.Mocked { + let obj: any = {}; + + if (Array.isArray(methodNames)) { + for (let i = 0; i < methodNames.length; i++) { + obj[methodNames[i] as string] = jest.fn(); + } + } else { + for (const methodName in methodNames) { + obj[methodName] = jest.fn(); + } + } + + if (propertyNames) { + if (Array.isArray(propertyNames)) { + for (const propertyName of propertyNames) { + obj[propertyName] = undefined; + } + } else { + for (const propertyName in propertyNames) { + obj[propertyName] = propertyNames[propertyName]; + } + } + } + + return obj as jest.Mocked; +} + +export type DoneFn = (...args: any[]) => void; + +export function fail(message?: string) { + expect(false).toBe(true); +} \ No newline at end of file diff --git a/projects/aas-server/src/test/winston-logger.spec.ts b/projects/aas-server/src/test/winston-logger.spec.ts new file mode 100644 index 00000000..8ffb4377 --- /dev/null +++ b/projects/aas-server/src/test/winston-logger.spec.ts @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import 'reflect-metadata'; +import winston from 'winston'; +import { FileLogger } from '../app/logging/file-logger.js'; +import { createSpyObj } from './utils.js'; +import { describe, beforeEach, it, expect, jest } from '@jest/globals'; + +describe('WinstonLogger', function () { + describe('log level Info', function () { + let logger: FileLogger; + let winstonLogger: jest.Mocked; + + beforeEach(function () { + winstonLogger = createSpyObj(['error', 'warn', 'info', 'isErrorEnabled', 'isInfoEnabled', 'isWarnEnabled']); + winstonLogger.isErrorEnabled.mockReturnValue(true); + winstonLogger.isWarnEnabled.mockReturnValue(true); + winstonLogger.isInfoEnabled.mockReturnValue(true); + logger = new FileLogger(winstonLogger); + }); + + it('logs all message types', function () { + logger.start('test'); + logger.info('This is an info.'); + logger.warning('This is a warning.'); + logger.error('This is an error'); + logger.stop(); + expect(logger.getMessages().length).toEqual(3); + }); + + it('logs message objects', function () { + logger.start('test'); + logger.log({ type: 'Info', text: 'This is an info.', timestamp: Date.now() }); + logger.log({ type: 'Warning', text: 'This is a warning.', timestamp: Date.now() }); + logger.log({ type: 'Error', text: 'This is an error.', timestamp: Date.now() }); + logger.stop(); + expect(logger.getMessages().length).toEqual(3); + }); + + it('logs only different errors', function () { + logger.start('test'); + logger.error('This is a first error.'); + logger.error(new Error('This is a first error.')); + logger.error('This is a seconde error.'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + + it('logs only different warnings', function () { + logger.start('test'); + logger.warning('This is a first warning.'); + logger.warning('This is a first warning.'); + logger.warning('This is a seconde warning.'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + + it('logs only different info messages', function () { + logger.start('test'); + logger.info('This is a first info.'); + logger.info('This is a seconde info.'); + logger.info('This is a seconde info.'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + }); + + describe('log level Error', function () { + let logger: FileLogger; + let winstonLogger: jest.Mocked; + + beforeEach(function () { + winstonLogger = createSpyObj(['error', 'warn', 'info', 'isErrorEnabled', 'isInfoEnabled', 'isWarnEnabled']); + winstonLogger.isErrorEnabled.mockReturnValue(true); + winstonLogger.isWarnEnabled.mockReturnValue(false); + winstonLogger.isInfoEnabled.mockReturnValue(false); + logger = new FileLogger(winstonLogger); + }); + + it('logs ony errors', function () { + logger.start('test'); + logger.info('This is an info.'); + logger.warning('This is a warning.'); + logger.error('This is an error'); + logger.stop(); + expect(logger.getMessages().length).toEqual(1); + }); + }); + + describe('log level Warning', function () { + let logger: FileLogger; + let winstonLogger: jest.Mocked; + + beforeEach(function () { + winstonLogger = createSpyObj(['error', 'warn', 'info', 'isErrorEnabled', 'isInfoEnabled', 'isWarnEnabled']); + winstonLogger.isErrorEnabled.mockReturnValue(true); + winstonLogger.isWarnEnabled.mockReturnValue(true); + winstonLogger.isInfoEnabled.mockReturnValue(false); + logger = new FileLogger(winstonLogger); + }); + + it('logs warnings and errors', function () { + logger.start('test'); + logger.info('This is an info.'); + logger.warning('This is a warning.'); + logger.error('This is an error'); + logger.stop(); + expect(logger.getMessages().length).toEqual(2); + }); + }); + + describe('log debug', function () { + let logger: FileLogger; + let winstonLogger: jest.Mocked; + + beforeEach(function () { + winstonLogger = createSpyObj(['error', 'warn', 'info', 'debug', 'isErrorEnabled', 'isInfoEnabled', 'isWarnEnabled', 'isDebugEnabled']); + winstonLogger.isErrorEnabled.mockReturnValue(true); + winstonLogger.isWarnEnabled.mockReturnValue(true); + winstonLogger.isInfoEnabled.mockReturnValue(true); + winstonLogger.isDebugEnabled.mockReturnValue(true); + logger = new FileLogger(winstonLogger); + }); + + it('logs debug messages to a console', function () { + logger.debug('This is a debug message.'); + expect(winstonLogger.debug).toHaveBeenCalled(); + }); + + it('logs errors to a console', function () { + logger.debug(new Error('This is a debug message.')); + expect(winstonLogger.debug).toHaveBeenCalled(); + }); + }); +}); \ No newline at end of file diff --git a/projects/aas-server/tsconfig.app.json b/projects/aas-server/tsconfig.app.json new file mode 100644 index 00000000..e196a869 --- /dev/null +++ b/projects/aas-server/tsconfig.app.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./build" + }, + "include": [ + "./src/app/**/*.ts" + ] +} \ No newline at end of file diff --git a/projects/aas-server/tsconfig.json b/projects/aas-server/tsconfig.json new file mode 100644 index 00000000..9caeb7db --- /dev/null +++ b/projects/aas-server/tsconfig.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compileOnSave": false, + "compilerOptions": { + "outDir": "./build", + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "nodenext", + "strict": true, + "noImplicitAny": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "sourceMap": true, + "alwaysStrict": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "useUnknownInCatchVariables": false, + "downlevelIteration": true, + "removeComments": true, + "useDefineForClassFields": false, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "lib": [ + "es2022" + ], + "types": [ + "node" + ], + "paths": { + "*": [ + "./src/app/types/*" + ] + } + } +} \ No newline at end of file diff --git a/projects/aas-server/tsoa.json b/projects/aas-server/tsoa.json new file mode 100644 index 00000000..128c3ecd --- /dev/null +++ b/projects/aas-server/tsoa.json @@ -0,0 +1,37 @@ +{ + "entryFile": "src/app/aas-server.ts", + "noImplicitAdditionalProperties": "silently-remove-extras", + "controllerPathGlobs": [ + "src/app/controller/**/*controller.ts" + ], + "multerOpts": { + "dest": "/temp" + }, + "spec": { + "outputDirectory": "./src/app", + "specVersion": 3, + "schemes": [ + "http" + ], + "securityDefinitions": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + }, + "api_key": { + "type": "apiKey", + "name": "access_token", + "in": "query" + } + }, + "yaml": false + }, + "routes": { + "routesDir": "./src/app/routes", + "iocModule": "src/app/controller/ioc-container", + "middleware": "express", + "authenticationModule": "./src/app/controller/authentication", + "esm": true + } +} \ No newline at end of file diff --git a/projects/common/.eslintrc b/projects/common/.eslintrc new file mode 100644 index 00000000..c939dc42 --- /dev/null +++ b/projects/common/.eslintrc @@ -0,0 +1,7 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "extends": ["plugin:@typescript-eslint/recommended"], + "parserOptions": { "ecmaVersion": 2018, "sourceType": "module" }, + "rules": {} + } \ No newline at end of file diff --git a/projects/common/esbuild.dev.js b/projects/common/esbuild.dev.js new file mode 100644 index 00000000..12d6d38b --- /dev/null +++ b/projects/common/esbuild.dev.js @@ -0,0 +1,20 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as esbuild from 'esbuild'; + +await esbuild.build({ + entryPoints: ['./src/lib/index.ts'], + outfile: './dist/common.js', + bundle: true, + platform: 'neutral', + format: 'esm', + target: 'es2022', + tsconfig: 'tsconfig.lib.json', + external: ['lodash-es'] +}); \ No newline at end of file diff --git a/projects/common/esbuild.prod.js b/projects/common/esbuild.prod.js new file mode 100644 index 00000000..667094cb --- /dev/null +++ b/projects/common/esbuild.prod.js @@ -0,0 +1,21 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as esbuild from 'esbuild'; + +await esbuild.build({ + entryPoints: ['./src/lib/index.ts'], + outfile: './dist/common.js', + bundle: true, + platform: 'neutral', + format: 'esm', + target: 'es2022', + tsconfig: 'tsconfig.lib.json', + minify: true, + external: ['lodash-es'] +}); \ No newline at end of file diff --git a/projects/common/jest.config.js b/projects/common/jest.config.js new file mode 100644 index 00000000..c9667194 --- /dev/null +++ b/projects/common/jest.config.js @@ -0,0 +1,28 @@ +export default { + clearMocks: true, + collectCoverage: true, + collectCoverageFrom: [ + '/src/lib/**/*.ts' + ], + coverageDirectory: '/../../reports/common', + coverageReporters: ['html', 'json-summary', 'cobertura'], + extensionsToTreatAsEsm: ['.ts'], + moduleNameMapper: { + "^(\\.{1,2}/.*)\\.js$": "$1" + }, + preset: 'ts-jest/presets/default-esm', + rootDir: '.', + roots: ['/src/'], + testEnvironment: 'node', + testMatch: [ + '**/?(*.)+(spec|test).[tj]s?(x)' + ], + transform: { + "^.+\\.tsx?$": [ + "ts-jest", + { + useESM: true + } + ] + } +}; diff --git a/projects/common/package.json b/projects/common/package.json new file mode 100644 index 00000000..55b11e4b --- /dev/null +++ b/projects/common/package.json @@ -0,0 +1,24 @@ +{ + "name": "common", + "version": "3.0.0", + "description": "Common types and utilities for the Web-AAS project", + "module": "./dist/lib/index.js", + "main": "./dist/common.js", + "types": "./dist/types/index.d.ts", + "author": "Fraunhofer IOSB-INA", + "license": "Apache-2.0", + "private": true, + "type": "module", + "scripts": { + "test": "node --experimental-vm-modules --no-warnings ../../node_modules/jest/bin/jest.js -c jest.config.js", + "test:debug": "node --experimental-vm-modules --no-warnings ../../node_modules/jest/bin/jest.js -c jest.config.js --runInBand --no-cache --verbose --watchAll=true", + "build": "rimraf dist && tsc -p tsconfig.lib.json && node esbuild.prod.js", + "build:debug": "rimraf dist && tsc -p tsconfig.lib.json && node esbuild.dev.js", + "tsc": "rimraf build && tsc -p tsconfig.json", + "lint": "eslint src/lib/**/*.ts", + "format": "eslint src/lib/**/*.ts --fix" + }, + "peerDependencies": { + "lodash-es": "^4.17.21" + } +} \ No newline at end of file diff --git a/projects/common/src/lib/aas.ts b/projects/common/src/lib/aas.ts new file mode 100644 index 00000000..1df5c1e6 --- /dev/null +++ b/projects/common/src/lib/aas.ts @@ -0,0 +1,401 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export type AasSubmodelElements = + 'AnnotatedRelationshipElement' | + 'BasicEventElement' | + 'Blob' | + 'Capability' | + 'DataElement' | + 'Entity' | + 'EventElement' | + 'File' | + 'MultiLanguageProperty' | + 'Operation' | + 'Property' | + 'Range' | + 'ReferenceElement' | + 'RelationshipElement' | + 'SubmodelElement' | + 'SubmodelElementCollection' | + 'SubmodelElementList'; + +export interface AdministrativeInformation extends HasDataSpecification { + version?: string; + revision?: string; + creator?: Reference; + template?: string; +} + +export interface AnnotatedRelationshipElement extends RelationshipElement { + annotations: DataElement[]; +} + +export interface AssetAdministrationShell extends Identifiable, HasDataSpecification { + derivedFrom?: Reference; + assetInformation: AssetInformation; + submodels?: Reference[]; +} + +export interface AssetInformation { + assetKind: AssetKind; + globalAssetId?: string; + specificAssetIds?: SpecificAssetId[]; + assetType?: string; + defaultThumbnail?: Resource; +} + +export type AssetKind = 'Type' | 'NotApplicable' | 'Instance'; + +export interface BasicEventElement extends EventElement { + observed: Reference; + direction: Direction; + state: StateOfEvent; + messageTopic?: string; + messageBroker?: Reference; + lastUpdate?: string; + minInterval?: string; + maxInterval?: string; +} + +export interface Blob extends DataElement { + contentType: string; + value?: string; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface Capability extends SubmodelElement { +} + +export interface ConceptDescription extends Identifiable, HasDataSpecification { + isCaseOf?: Reference[]; +} + +export interface DataElement extends SubmodelElement { + /** OPC UA */ + nodeId?: string; +} + +export interface DataSpecificationContent { + modelType: ModelType; +} + +export interface DataSpecificationIEC61360 extends DataSpecificationContent { + preferredName: LangString[]; + shortName?: LangString[]; + unit?: string; + unitId?: Reference; + sourceOfDefinition?: string; + symbol?: string; + dataType?: DataTypeIEC61360; + definition?: LangString[]; + valueFormat?: string; + valueList?: ValueList; + value?: string; + levelType?: LevelType; +} + +export type DataTypeDefXsd = + 'xs:anyURI' | + 'xs:base64Binary' | + 'xs:boolean' | + 'xs:byte' | + 'xs:date' | + 'xs:dateTime' | + 'xs:decimal' | + 'xs:double' | + 'xs:duration' | + 'xs:float' | + 'xs:gDay' | + 'xs:gMonth' | + 'xs:gMonthDay' | + 'xs:gYear' | + 'xs:gYearMonth' | + 'xs:hexBinary' | + 'xs:int' | + 'xs:integer' | + 'xs:long' | + 'xs:negativeInteger' | + 'xs:nonNegativeInteger' | + 'xs:nonPositiveInteger' | + 'xs:positiveInteger' | + 'xs:short' | + 'xs:string' | + 'xs:time' | + 'xs:unsignedByte' | + 'xs:unsignedInt' | + 'xs:unsignedLong' | + 'xs:unsignedShort'; + +export type DataTypeIEC61360 = + 'BLOB' | + 'BOOLEAN' | + 'DATE' | + 'FILE' | + 'HTML' | + 'INTEGER_COUNT' | + 'INTEGER_CURRENCY' | + 'INTEGER_MEASURE' | + 'IRDI' | + 'IRI' | + 'RATIONAL' | + 'RATIONAL_MEASURE' | + 'REAL_COUNT' | + 'REAL_CURRENCY' | + 'REAL_MEASURE' | + 'STRING' | + 'STRING_TRANSLATABLE' | + 'TIME' | + 'TIMESTAMP'; + +export type Direction = 'input' | 'output'; + +export interface EmbeddedDataSpecification { + dataSpecification: Reference; + dataSpecificationContent: DataSpecificationContent; +} + +export interface Entity extends SubmodelElement { + statements?: SubmodelElement[]; + entityType: EntityType; + globalAssetId?: string; + specificAssetId?: SpecificAssetId; +} + +export type EntityType = 'CoManagedEntity' | 'SelfManagedEntity'; + +export interface Environment { + assetAdministrationShells: AssetAdministrationShell[]; + submodels: Submodel[]; + conceptDescriptions: ConceptDescription[]; +} + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface EventElement extends SubmodelElement { +} + +export interface EventPayload extends SubmodelElement { + source: Reference; + sourceSemanticId?: Reference; + observableReference: Reference; + observableSemanticId?: Reference; + topic?: string; + subjectId?: Reference; + timeStamp: string; + payload?: string; +} + +export interface Extension extends HasSemantic { + name: string; + valueType?: DataTypeDefXsd; + value?: string; + refersTo?: Reference; +} + +export interface File extends DataElement { + contentType: string; + value?: string; +} + +export interface HasDataSpecification { + embeddedDataSpecifications?: EmbeddedDataSpecification[]; +} + +export interface HasExtensions { + extensions?: Extension[]; +} + +export interface HasKind { + kind?: ModellingKind; +} + +export interface HasSemantic { + semanticId?: Reference; + supplementalSemanticIds?: Reference; +} + +export interface Identifiable extends Referable { + administration?: AdministrativeInformation; + id: string; +} + +export interface Key { + type: KeyTypes; + value: string; +} + +export type KeyTypes = + 'AnnotatedRelationshipElement' | + 'AssetAdministrationShell' | + 'BasicEventElement' | + 'Blob' | + 'Capability' | + 'ConceptDescription' | + 'DataElement' | + 'Entity' | + 'EventElement' | + 'File' | + 'FragmentReference' | + 'GlobalReference' | + 'Identifiable' | + 'MultiLanguageProperty' | + 'Operation' | + 'Property' | + 'Range' | + 'Referable' | + 'ReferenceElement' | + 'RelationshipElement' | + 'Submodel' | + 'SubmodelElement' | + 'SubmodelElementCollection' | + 'SubmodelElementList'; + +export interface LangString { + language: string; + text: string; +} + +export type LevelType = 'Max' | 'Min' | 'Nom' | 'Typ'; + +export type ModelType = + 'AnnotatedRelationshipElement' | + 'AssetAdministrationShell' | + 'BasicEventElement' | + 'Blob' | + 'Capability' | + 'ConceptDescription' | + 'DataSpecificationIEC61360' | + 'Entity' | + 'File' | + 'MultiLanguageProperty' | + 'Operation' | + 'Property' | + 'Range' | + 'ReferenceElement' | + 'RelationshipElement' | + 'Submodel' | + 'SubmodelElementCollection' | + 'SubmodelElementList'; + +export type ModellingKind = 'Template' | 'Instance'; + +export interface MultiLanguageProperty extends DataElement { + value: LangString[]; + valueId?: Reference; +} + +export interface Operation extends SubmodelElement { + inputVariables?: OperationVariable[]; + outputVariables?: OperationVariable[]; + inoutputVariables?: OperationVariable[]; + /** The node ID of the operation node. */ + methodId?: string; + /** The node ID of the operation submodel element. */ + objectId?: string; +} + +export interface OperationVariable { + value: SubmodelElement; +} + +export interface Property extends DataElement { + valueType: DataTypeDefXsd; + value?: string; + valueId?: Reference; +} + +export interface Qualifiable { + qualifiers?: Qualifier[]; +} + +export interface Qualifier extends HasSemantic { + kind?: QualifierKind; + type: string; + valueType: DataTypeDefXsd; + value?: string; + valueId?: Reference; +} + +export type QualifierKind = 'ConceptQualifier' | 'TemplateQualifier' | 'ValueQualifier'; + +export interface Range extends DataElement { + valueType: DataTypeDefXsd; + min?: string; + max?: string; +} + +/** Metainformation if SubmodelElement is DataElement */ +export type Category = 'CONSTANT' | 'PARAMETER' | 'VARIABLE'; + +export interface Referable { + category?: string; + idShort: string; + displayName?: LangString[]; + descriptions?: LangString[]; + modelType: ModelType; + /** For internal use. */ + parent?: Reference; +} + +export interface Reference { + type: ReferenceTypes; + referredSemanticId?: Reference; + keys: Key[]; +} + +export interface ReferenceElement extends DataElement { + value: Reference; +} + +export type ReferenceTypes = 'ExternalReference' | 'ModelReference'; + +export interface RelationshipElement extends SubmodelElement { + first: Reference; + second: Reference; +} + +export interface Resource { + path: string; + contentType?: string; +} + +export interface SpecificAssetId extends HasSemantic { + name: string; + value: string; + externalSubjectId: Reference; +} + +export type StateOfEvent = 'on' | 'off'; + +export interface Submodel extends Identifiable, HasKind, HasSemantic, Qualifiable, HasDataSpecification { + submodelElements?: SubmodelElement[]; +} + +export interface SubmodelElement extends Referable, HasKind, HasSemantic, Qualifiable, HasDataSpecification { +} + +export interface SubmodelElementCollection extends SubmodelElement { + value?: SubmodelElement[]; +} + +export interface SubmodelElementList extends SubmodelElement { + orderRelevant?: boolean; + semanticIdListElement?: Reference; + typeValueListElement: AasSubmodelElements; + valueTypeListElement?: DataTypeDefXsd; + value?: SubmodelElement[]; +} + +export interface ValueList { + valueReferencePairs: ValueReferencePair[] +} + +export interface ValueReferencePair { + value: string; + valueId: Reference; +} \ No newline at end of file diff --git a/projects/common/src/lib/application-error.ts b/projects/common/src/lib/application-error.ts new file mode 100644 index 00000000..b3a9af09 --- /dev/null +++ b/projects/common/src/lib/application-error.ts @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + + export class ApplicationError extends Error { + /** + * @constructor + * @param message The error message. + * @param name The name of the error. + * @param args Additional arguments for the error message. + */ + constructor(message: string, name: string, ...args: Parameters) { + super(message); + + this.name = name ?? "Application error"; + this.args = args ?? []; + } + + /** Gets the additional arguments. */ + public readonly args: Parameters; +} \ No newline at end of file diff --git a/projects/common/src/lib/authentication.ts b/projects/common/src/lib/authentication.ts new file mode 100644 index 00000000..c4f64e1d --- /dev/null +++ b/projects/common/src/lib/authentication.ts @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { capitalize } from "lodash-es"; + +export type UserRole = "guest" | "editor" | "admin"; + +export const priority: UserRole[] = ['guest', 'editor', 'admin']; + +/** The user roles. */ +export const USER_ROLES: { [key: string]: string } = { + admin: "admin", + editor: "editor", + guest: "guest" +}; + +/** The user profile. */ +export interface UserProfile { + /** A valid e-mail address of the user. */ + id: string; + /** The name or alias of the user. */ + name: string; + /** The password. */ + password?: string; +} + +/** The credentials. */ +export interface Credentials { + /** A unique identifier. */ + id: string; + /** The password. */ + password?: string; +} + +/** Result of a login or profile update message. */ +export interface AuthResult { + token: string; +} + +/** JSON web token private claim. */ +export interface JWTPayload { + sub?: string; + name?: string; + role: UserRole; + exp?: number; + iat?: number; +} + +/** + * Extracts a user name from the specified e-mail. + * @param email The e-mail. + * @returns The user name. + */ +export function getUserNameFromEMail(email: string): string { + let name: string; + const index = email.indexOf('@'); + if (index > 0) { + name = email.substring(0, index).replace(/[.-]/, ' ').split(' ').map(item => capitalize(item)).join(' '); + } else { + name = email; + } + + return name; +} + +/** + * Determines whether the current user is authorized for the specified roles. + * @param actual The actual role. + * @param expected The expected role. + */ +export function isUserAuthorized(actual: UserRole, expected: UserRole): boolean { + const i = priority.indexOf(expected); + const j = priority.indexOf(actual); + return i >= 0 && j >= 0 && i <= j; +} \ No newline at end of file diff --git a/projects/common/src/lib/convert.ts b/projects/common/src/lib/convert.ts new file mode 100644 index 00000000..14f4a166 --- /dev/null +++ b/projects/common/src/lib/convert.ts @@ -0,0 +1,665 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { DataTypeDefXsd, LangString } from './aas.js'; + +const dateTimeFormat: Intl.DateTimeFormatOptions = { + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour: "numeric", + minute: "numeric", + second: "numeric" +}; + +const invariantDecimalSeparator = '.'; +const invariantGroupSeparator = ','; + +export type DefaultType = string | number | boolean | bigint; + +/** + * Converts a value into an other data type. + * @param value The current value. + * @param type The destination data type. + * @param localId The locale identifier. + * @returns The converted value. + */ +export function changeType(value: any, type: DataTypeDefXsd, localId?: string): DefaultType | undefined { + switch (type) { + case 'xs:boolean': + return toBoolean(value); + case 'xs:anyURI': + return convertToString(value); + case 'xs:double': + case 'xs:float': + case 'xs:decimal': + return toDouble(value, localId); + case 'xs:integer': + case 'xs:int': + case 'xs:byte': + case 'xs:short': + case 'xs:unsignedByte': + case 'xs:unsignedInt': + case 'xs:unsignedShort': + return toInteger(value); + case 'xs:long': + case 'xs:unsignedLong': + return toBigInt(value); + case 'xs:date': + case 'xs:dateTime': + case 'xs:time': + return toTime(value, localId); + case 'xs:string': + return convertToString(value, localId); + default: + return value; + } +} + +/** + * Converts a value to an equivalent string expression. + * @param value The current value. + * @param localeId The locale identifier. + * @returns A string expression that represents the specified value. + */ +export function convertToString(value: unknown, localeId?: string): string { + let s = ''; + if (value != null) { + if (typeof value === 'string') { + s = value; + } else if (typeof value === 'boolean') { + s = value ? 'true' : 'false'; + } else if (typeof value === 'number') { + s = localeId ? value.toLocaleString(localeId) : value.toString(); + } else if (value instanceof Date) { + s = localeId ? value.toLocaleString(localeId, dateTimeFormat) : value.toString(); + } else if (typeof value === 'bigint') { + s = localeId ? value.toLocaleString(localeId) : value.toString(); + } else if (Array.isArray(value)) { + s = `[${getItems(value).join(', ')}]`; + } else if (typeof value === 'object') { + s = `{ ${getProperties(value).join(', ')} }`; + } + } + + return s; + + function getProperties(obj: object): string[] { + const items: string[] = []; + for (const property in obj) { + items.push(`${property}: ${convertToString((obj)[property], localeId)}`) + } + + return items; + } + + function getItems(array: any[]): string[] { + return array.map(item => convertToString(item, localeId)); + } +} + +/** + * Converts a string expression to an equivalent value of the specified type. + * @param s The string expression. + * @param valueType The value type. + * @param localeId The locale identifier. + * @returns A value of the specified type. + */ +export function convertFromString( + s: string | null | undefined, + valueType: DataTypeDefXsd, + localeId?: string): DefaultType | undefined { + if (!s) { + return undefined; + } + + switch (valueType) { + case 'xs:boolean': + return stringToBoolean(s); + case 'xs:anyURI': + return s; + case 'xs:unsignedByte': + return stringToByte(s); + case 'xs:byte': + return stringToSByte(s); + case 'xs:double': + case 'xs:float': + case 'xs:decimal': + return toDouble(s, localeId); + case 'xs:integer': + case 'xs:int': + case 'xs:short': + case 'xs:unsignedInt': + case 'xs:unsignedShort': + return toInteger(s); + case 'xs:long': + case 'xs:unsignedLong': + return toBigInt(s); + case 'xs:date': + case 'xs:dateTime': + case 'xs:time': + return parseDate(s, localeId)?.getTime(); + case 'xs:string': + return s; + default: + return undefined; + } +} + +/** + * Converts a string expression to a number. + * @param s The string expression. + * @param localeId The locale identifier. + * @returns A number. + */ +export function parseNumber(s: string, localeId?: string): number { + let decimalSeparator: string; + let groupSeparator: string; + if (localeId) { + const parts = Intl.NumberFormat(localeId).formatToParts(1234.56789); + decimalSeparator = parts.find(part => part.type === 'decimal')!.value; + groupSeparator = parts.find(part => part.type === 'group')!.value; + } else { + decimalSeparator = invariantDecimalSeparator; + groupSeparator = invariantGroupSeparator; + } + + const items = s.split(decimalSeparator); + s = items[0].split(groupSeparator).join(''); + if (items.length > 1) { + s += invariantDecimalSeparator + items[1]; + } + + return Number(s); +} + +/** + * Parses a localized string expression into a Date. + * @param s The string expression that represents a date and time. + * @param localeId The locale identifier. + */ +export function parseDate(s: string, localeId?: string): Date | undefined { + const format = new Intl.DateTimeFormat(localeId, dateTimeFormat); + const now = new Date(); + const parts = format.formatToParts(now); + const tuple = getFormatInfo(parts); + + let date: Date | undefined; + if (s) { + s = s.trim().toLowerCase(); + if (localeId) { + let dateItems: string[] | undefined; + let timeTuple: { items: string[], timePeriod?: string } | undefined; + if (s.indexOf(',') < 0) { + if (s.indexOf(tuple.dateDelimiter) >= 0) { + dateItems = s.split(tuple.dateDelimiter); + const day = getDay(dateItems); + date = day + ? new Date(getYear(dateItems), getMonth(dateItems), getDay(dateItems)) + : new Date(getYear(dateItems), getMonth(dateItems)); + } else { + timeTuple = splitTime(s); + date = new Date( + now.getFullYear(), + now.getMonth(), + now.getDate(), + getHours(timeTuple?.items, timeTuple?.timePeriod), + getMinutes(timeTuple?.items), + getSeconds(timeTuple?.items)); + + } + } else { + const dateTime = s.split(','); + dateItems = dateTime[0].split(tuple.dateDelimiter); + timeTuple = splitTime(dateTime[1]); + date = new Date( + getYear(dateItems), + getMonth(dateItems), + getDay(dateItems), + getHours(timeTuple?.items, timeTuple?.timePeriod), + getMinutes(timeTuple?.items), + getSeconds(timeTuple?.items)); + } + + } else { + date = new Date(s); + if (date.toString() === 'Invalid Date') { + date = parseDate(s, 'en'); + } + } + } + + return date; + + function getFormatInfo(parts: Intl.DateTimeFormatPart[]): { + dateDelimiter: string, + timeDelimiter: string, + indexOfYear: number, + indexOfMonth: number, + indexOfDay: number, + hours24: boolean + } { + const items = ['year', 'month', 'day'] + .sort((a, b) => parts.findIndex(item => item.type === a) - parts.findIndex(item => item.type === b)); + + return { + dateDelimiter: parts[3].value, + timeDelimiter: parts[9].value, + indexOfDay: items.indexOf('day'), + indexOfMonth: items.indexOf('month'), + indexOfYear: items.indexOf('year'), + hours24: parts.findIndex(part => part.type === 'dayPeriod') < 0 + }; + } + + function splitTime(exp: string): { items: string[], timePeriod?: string } { + if (exp.endsWith('am')) { + return { items: exp.substring(0, exp.length - 2).split(tuple.timeDelimiter), timePeriod: 'am' }; + } + + if (exp.endsWith('pm')) { + return { items: exp.substring(0, exp.length - 2).split(tuple.timeDelimiter), timePeriod: 'pm' }; + } + + return { items: exp.split(tuple.timeDelimiter) }; + } + + function getYear(items?: string[]): number { + if (items) { + if (items.length >= 3) { + return Number(items[tuple.indexOfYear].trim()); + } + + if (items.length === 1) { + return Number(items[0].trim()); + } + + if (items.length === 2) { + return tuple.indexOfMonth < tuple.indexOfYear ? Number(items[1].trim()) : Number(items[0].trim()); + } + } + + return 0; + } + + function getMonth(items?: string[]): number { + if (items) { + if (items.length >= 3) { + return Number(items[tuple.indexOfMonth].trim()) - 1; + } + + if (items.length === 2) { + return (tuple.indexOfMonth < tuple.indexOfYear ? Number(items[0].trim()) : Number(items[1].trim())) - 1; + } + } + + return 0; + } + + function getDay(items?: string[]): number | undefined { + return items && items.length >= 3 ? Number(items[tuple.indexOfDay].trim()) : undefined; + } + + function getHours(items?: string[], timePeriod?: string): number { + if (items && items.length > 0) { + return Number(items[0].trim()) + (timePeriod === 'pm' ? 12 : 0); + } + + return now.getDate(); + } + + function getMinutes(items?: string[]): number { + return items && items.length > 1 ? Number(items[1].trim()) : 0; + } + + function getSeconds(items?: string[]): number { + return items && items.length > 2 ? Number(items[2].trim()) : 0; + } +} + +/** + * Determines the data type from the specified string expression. + * @param value The value or a string expression. + * @returns The data type. + */ +export function determineType(value: any): DataTypeDefXsd | undefined { + if (typeof value === 'string') { + value = value.trim(); + if (value.length > 0) { + const d = Number(value); + if (!Number.isNaN(d)) { + return Number.isInteger(d) ? 'xs:int' : 'xs:double'; + } + + if (value.toLocaleLowerCase() === 'true' || value.toLocaleLowerCase() === 'false') { + return 'xs:boolean'; + } + + if (!Number.isNaN(Date.parse(value))) { + return 'xs:dateTime'; + } + + // ToDo: How to check if expression is bigint? + } + + return 'xs:string'; + } else if (typeof value === 'number') { + return Number.isInteger(value) ? 'xs:int' : 'xs:double'; + } else if (typeof value === 'boolean') { + return 'xs:boolean'; + } else if (typeof value === 'bigint') { + return 'xs:long'; + } else if (value instanceof Date) { + return 'xs:dateTime'; + } + + return undefined; +} + +/** + * Gets a default value for the specified data type. + * @param type The data type. + * @returns A default value. + */ +export function getDefaultValue(type: DataTypeDefXsd): any { + switch (type) { + case 'xs:boolean': + return false; + case 'xs:anyURI': + return ''; + case 'xs:byte': + case 'xs:double': + case 'xs:float': + case 'xs:decimal': + case 'xs:integer': + case 'xs:int': + case 'xs:short': + case 'xs:unsignedByte': + case 'xs:unsignedInt': + case 'xs:unsignedShort': + return 0; + case 'xs:long': + case 'xs:unsignedLong': + return BigInt(0); + case 'xs:date': + case 'xs:dateTime': + case 'xs:time': + return 0; + case 'xs:string': + return ''; + default: + throw new Error(`Data type "${type}" is not supported.`); + } +} + +/** + * Returns the value for the specified language. + * @param value The localizable string. + * @param localeId The locale identifier. + * @returns The locale value. + */ +export function getLocaleValue(value?: LangString[], localeId?: string): string | undefined { + let localeValue: string | undefined; + if (value) { + if (localeId) { + const language = getLanguage(localeId); + for (const item of value) { + const lcid = item.language.toLowerCase(); + if (lcid === localeId || lcid === language) { + localeValue = item.text; + break; + } + else if (!localeValue && getLanguage(item.language) === language) { + localeValue = item.text; + } + } + } + + if (!localeValue && value.length > 0) { + localeValue = value[0].text; + } + } + + return localeValue; + + function getLanguage(value: string): string { + return value.split('-')[0].toLowerCase(); + } + + function getRegion(value: string): string | null { + const items = value.split('-'); + return items.length > 1 ? items[1].toLowerCase() : null; + } +} + +/** + * Indicates whether the specified data type corresponds to `boolean`. + * @param type The data type. + */ +export function isBooleanType(type: DataTypeDefXsd): boolean { + return type === 'xs:boolean'; +} + +/** + * Converts a locale invariant string representation of the current value into a localized. + * @param value The locale invariant string representation of a value. + * @param valueType The value type. + * @param localeId The target language. + */ +export function toLocale(value: string | undefined, valueType: DataTypeDefXsd, localeId: string): string | undefined { + if (!value) { + return value; + } + + switch (valueType) { + case 'xs:float': + case 'xs:double': + const d = parseNumber(value); + return Number.isNaN(d) ? undefined : d.toLocaleString(localeId); + case 'xs:integer': + case 'xs:int': + case 'xs:unsignedInt': + case 'xs:unsignedShort': + const i = parseNumber(value); + return Number.isNaN(i) ? undefined : i.toLocaleString(localeId); + case 'xs:date': + case 'xs:dateTime': + return parseDate(value)?.toLocaleString(localeId, dateTimeFormat); + case 'xs:unsignedLong': + case 'xs:long': + default: + return value; + } +} + +/** + * Converts a localized string representation of the current value into a locale invariant. + * @param value The localized string representation of a value. + * @param valueType The value type. + * @param localeId The source language. + */ +export function toInvariant(value: string | undefined, valueType: DataTypeDefXsd, localeId: string): string | undefined { + if (!value) { + return value; + } + + switch (valueType) { + case 'xs:float': + case 'xs:double': + const d = parseNumber(value, localeId); + return Number.isNaN(d) ? undefined : d.toString(); + case 'xs:integer': + case 'xs:int': + case 'xs:unsignedInt': + case 'xs:unsignedShort': + const i = parseNumber(value, localeId); + return Number.isNaN(i) ? undefined : i.toString(); + case 'xs:date': + case 'xs:dateTime': + case 'xs:time': + return parseDate(value, localeId)!.toUTCString(); + default: + return value; + } +} + +/** + * Indicates wether the specified value type represents a number. + * @param valueType The current value type. + * @returns `true` if the specified value type represents a number; otherwise, `false`. + */ +export function isNumberType(valueType: DataTypeDefXsd): boolean { + switch (valueType) { + case 'xs:float': + case 'xs:double': + case 'xs:integer': + case 'xs:int': + case 'xs:unsignedInt': + case 'xs:unsignedShort': + return true; + default: + return false; + } +} + +/** + * Converts the specified value to an equivalent boolean. + * @param value The current value. + * @returns A boolean value. + */ +export function toBoolean(value: any): boolean { + if (typeof value === 'boolean') { + return value; + } + + if (typeof value === 'string') { + value = value.toLocaleLowerCase(); + if (value === 'false' || value.length === 0) { + return false; + } + + if (value === 'true') { + return true; + } + + return Number(value) !== 0 ? true : false + } + + if (typeof value === 'number') { + return value !== 0.0; + } + + return false; +} + +function stringToBoolean(value: string): boolean { + return value?.toLocaleLowerCase() === 'true'; +} + +function stringToSByte(value: string): number | undefined { + const b = Number(value); + if (Number.isNaN(b) || b < -256) { + return undefined + } + + return b < 128 ? b : b - 256; +} + +function stringToByte(value: string): number | undefined { + const b = Number(value); + if (Number.isNaN(b) || b < 0) { + return undefined; + } + + return b; +} + +function toDouble(value: any, localeId?: string): number | undefined { + if (typeof value === 'number') { + return value; + } + + if (typeof value === 'string') { + if (localeId) { + const decimalPart = Intl.NumberFormat(localeId).formatToParts(1.23).find(part => part.type === 'decimal'); + if (decimalPart) { + value = value.replace(decimalPart.value, '.'); + } + } + + const d = Number(value); + if (!Number.isNaN(d)) { + return d; + } + } + + if (typeof value === 'boolean') { + return value ? 1 : 0; + } + + if (value instanceof Date) { + return value.getTime(); + } + + return undefined; +} + +function toInteger(value: any): number | undefined { + if (typeof value === 'number') { + return value; + } + + if (typeof value === 'string') { + const d = Number.parseInt(value); + if (!Number.isNaN(d)) { + return d; + } + } + + if (typeof value === 'boolean') { + return value ? 0 : 1; + } + + if (value instanceof Date) { + return value.getTime(); + } + + return undefined; +} + +function toTime(value: any, localeId?: string): number | undefined { + if (value instanceof Date) { + return value.getTime(); + } + + if (typeof value === 'number') { + return value; + } + + if (typeof value === 'string') { + parseDate(value, localeId)?.getTime(); + } + + return undefined; +} + +function toBigInt(value: any): bigint | undefined { + if (typeof value === 'bigint') { + return value; + } + + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + try { + return BigInt(value); + } catch (error) { + return undefined; + } + } + + return undefined; +} \ No newline at end of file diff --git a/projects/common/src/lib/document.ts b/projects/common/src/lib/document.ts new file mode 100644 index 00000000..c2735ba0 --- /dev/null +++ b/projects/common/src/lib/document.ts @@ -0,0 +1,993 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { isEqual } from 'lodash-es'; +import * as aas from './aas.js'; +import { equalUrls } from './index.js'; +import { AASDocument, AASAbbreviation } from './types.js'; + +/** Represents a difference. */ +export interface DifferenceItem { + type: 'deleted' | 'inserted' | 'changed' | 'moved'; + sourceParent?: aas.Referable; + sourceElement?: aas.Referable; + sourceIndex?: number; + destinationParent?: aas.Referable; + destinationElement?: aas.Referable; + destinationIndex?: number; +} + +/** + * Determines whether the specified documents are equal. + * @param a The first document. + * @param b The second document. + * @returns `true` if the specified documents are equal. + */ +export function equalDocument(a: AASDocument | null, b: AASDocument | null): boolean { + return a === b || a != null && b != null && a.id === b.id && equalUrls(a.container, b.container); +} + +/** + * Gets the parent of the specified element. + * @param env The Asset Administration Shell environment. + * @param referable The element to check. + * @returns The parent element or `undefined` if element is the root. + */ +export function getParent( + env: aas.Environment, + referable: aas.Referable): aas.Referable | undefined { + return referable.parent ? selectReferable(env, referable.parent) : undefined; +} + +/** + * Goes up the hierarchy to the submodel. + * @param env The AAS environment. + * @param referable An element of the AAS. + * @returns The submodel or `undefined`. + */ +export function selectSubmodel(env: aas.Environment, referable: aas.Referable): aas.Submodel | undefined { + if (referable.modelType === 'Submodel') { + return referable as aas.Submodel; + } + + if (env.submodels && referable.parent && referable.parent.keys[0].type === 'Submodel') { + const id = referable.parent.keys[0].value; + return env.submodels.find(item => item.id === id); + } + + return undefined; +} + +/** + * Determines wether the specified element is a descendant of the given ancestor. + * @param root The root element. + * @param ancestor An ancestor element. + * @param element An element to check. + * @returns `true` if the element is a descendant of the given ancestor; otherwise, `false`. + */ +export function isDescendant( + env: aas.Environment, + ancestor: aas.Referable, + element: aas.Referable): boolean { + for (let referable = getParent(env, element); referable; referable = getParent(env, referable)) { + if (referable === ancestor) { + return true; + } + } + + return false; +} + +/** + * Removes equal elements or descendants of an element. + * @param aas The root element. + * @param elements The elements to normalize. + * @returns An array of elements. + */ +export function normalize( + env: aas.Environment, + elements: T[], + access: (item: T) => aas.Referable = (item) => item as aas.Referable): T[] { + let items: T[] = elements; + let temp: T[] = []; + for (let i = 0; i < items.length; ++i) { + for (let j = 0; j < items.length; j++) { + if (i !== j) { + if (items[i] !== items[j] && + !isDescendant(env, access(items[i]), access(items[j]))) { + temp.push(items[j]); + } + } + else { + temp.push(items[i]); + } + } + + items = temp; + temp = []; + } + + return items; +} + +/** + * Iterates over all descendants of the specified element and the element itself. + * @param referable The start element. + * @returns All descendants of the specified element and the element itself. + */ +export function* traverse(root: aas.Referable): Generator<[string, [aas.Referable | undefined, aas.Referable]]> { + yield ['/', [undefined, root]]; + + for (const item of traverseChildren(root, '/' + root.idShort)) { + yield item; + } + + function* traverseChildren(parent: aas.Referable, path: string): Generator<[string, [aas.Referable, aas.Referable]]> { + for (const child of getChildren(parent)) { + const childPath = path + child.idShort; + yield [path + child.idShort, [parent, child]]; + + for (const item of traverseChildren(child, childPath)) { + yield item; + } + } + } +} + +/** + * Determines the differences between the specified source and destination referable. + * @param sourceEnv The source element. + * @param targetEnv The destination element. + * @returns The differences between the source and destination element. + */ +export function diff( + sourceEnv: aas.Environment, + targetEnv: aas.Environment): DifferenceItem[] { + if (sourceEnv && targetEnv && sourceEnv === targetEnv) { + return []; + } + + return [ + ...diffCollection(sourceEnv.assetAdministrationShells, targetEnv.assetAdministrationShells), + ...diffCollection(sourceEnv.submodels, targetEnv.submodels), + ...diffCollection(sourceEnv.conceptDescriptions, targetEnv.conceptDescriptions)]; + + function diffCollection(sources: aas.Referable[], targets: aas.Referable[]): DifferenceItem[] { + const diffs: DifferenceItem[] = []; + for (let i = 0; i < sources.length; i++) { + const j = targets.findIndex(item => item.idShort === sources[i].idShort); + if (j < 0) { + diffs.push({ type: 'inserted', sourceIndex: i, sourceElement: sources[i] }) + } else { + diffs.push(...diffReferable(sources[i], targets[j])); + } + } + + for (let i = 0; i < targets.length; i++) { + const j = sources.findIndex(item => item.idShort === targets[i].idShort); + if (j < 0) { + diffs.push({ type: 'deleted', destinationIndex: i, destinationElement: targets[i] }); + } + } + + return diffs; + } + + function diffReferable(source: aas.Referable, target: aas.Referable): DifferenceItem[] { + const sourceMap = new Map(traverse(source)); + const destinationMap = new Map(traverse(target)); + let deleted: DifferenceItem[] = []; + let inserted: DifferenceItem[] = []; + const changed: DifferenceItem[] = []; + const moved: DifferenceItem[] = []; + + for (const destinationItem of destinationMap) { + const sourceTuple = sourceMap.get(destinationItem[0]); + if (sourceTuple) { + const src = sourceTuple[1]; + const srcParent = sourceTuple[0]; + const dst = destinationItem[1][1]; + const dstParent = destinationItem[1][0]; + if (!isEqualReferable(src, dst)) { + changed.push({ + type: 'changed', + sourceParent: srcParent, + sourceElement: src, + sourceIndex: indexOf(srcParent, src), + destinationParent: dstParent, + destinationElement: dst, + destinationIndex: indexOf(dstParent, dst) + }); + } else { + const i = indexOf(srcParent, src); + const j = indexOf(dstParent, dst); + if (twins(srcParent, dstParent) && i !== j) { + moved.push({ + type: 'moved', + sourceParent: srcParent, + sourceElement: src, + sourceIndex: i, + destinationParent: dstParent, + destinationElement: dst, + destinationIndex: j + }); + } + } + } else { + deleted.push({ + type: 'deleted', + sourceParent: getParent(targetEnv, destinationItem[1][1]), + destinationParent: destinationItem[1][0], + destinationElement: destinationItem[1][1], + destinationIndex: indexOf(destinationItem[1][0], destinationItem[1][1]) + }); + } + } + + for (const item of sourceMap) { + if (!destinationMap.has(item[0])) { + inserted.push({ + type: 'inserted', + sourceParent: item[1][0], + sourceElement: item[1][1], + sourceIndex: indexOf(item[1][0], item[1][1]), + destinationParent: getParent(targetEnv, item[1][1]) + }); + } + } + + deleted = normalize(targetEnv, deleted, item => item.destinationElement as aas.Referable); + inserted = normalize(sourceEnv, inserted, item => item.sourceElement as aas.Referable); + + return [...deleted, ...inserted, ...moved, ...changed]; + } + + function twins(a?: aas.Referable, b?: aas.Referable): boolean { + return a && b ? a === b || equalReference(a.parent, b.parent) && a.idShort === b.idShort : false; + } + + function indexOf(parent: aas.Referable | undefined, child: aas.Referable): number { + return parent ? getChildren(parent).indexOf(child) : -1; + } + + function isEqualReferable(a: aas.Referable, b: aas.Referable): boolean { + let equal = false; + if (a === b) { + equal = true; + } else if (a.modelType === b.modelType) { + if (a.modelType === 'SubmodelElementCollection') { + equal = isEqual( + { ...a, value: undefined } as aas.SubmodelElementCollection, + { ...b, value: undefined } as aas.SubmodelElementCollection); + } else if (a.modelType === 'SubmodelElementList') { + equal = isEqual( + { ...a, value: undefined } as aas.SubmodelElementList, + { ...b, value: undefined } as aas.SubmodelElementList); + } else if (a.modelType === 'Submodel') { + equal = isEqual( + { ...a, submodelElements: undefined } as aas.Submodel, + { ...b, submodelElements: undefined } as aas.Submodel); + } else if (a.modelType === 'AssetAdministrationShell') { + equal = isEqual( + { ...a, submodels: undefined } as aas.AssetAdministrationShell, + { ...b, submodels: undefined } as aas.AssetAdministrationShell); + } else { + equal = isEqual(a, b); + } + } + + return equal; + } +} + +/** + * Determines the differences between the specified source and destination AAS Element. + * @param source The source element. + * @param destination The destination element. + * @returns The differences between the source and destination element. + */ +export function diffAsync(source: aas.Environment, destination: aas.Environment): Promise { + return new Promise((result, reject) => { + try { + result(diff(source, destination)); + } catch (error) { + reject(error); + } + }); +} + +/** + * Compares two trees for equality. + * @param a The root element of the first tree. + * @param b The root element of the second tree. + * @returns `true` if both trees are equal; otherwise, `false`. + */ +export function isDeepEqual(a?: aas.Environment, b?: aas.Environment): boolean { + const queue: [aas.Referable, aas.Referable][] = []; + if (a && b) { + if (!equalLength(a.assetAdministrationShells, b.assetAdministrationShells) || + !equalLength(a.submodels, b.submodels) || + !equalLength(a.conceptDescriptions, b.conceptDescriptions)) { + return false; + } + + if (!queueReferables(a.assetAdministrationShells, b.assetAdministrationShells) || + !queueReferables(a.submodels, b.submodels) || + !queueReferables(a.conceptDescriptions, b.conceptDescriptions)) { + return false; + } + + while (queue.length > 0) { + const pair = queue.pop(); + if (!pair || !equal(pair[0], pair[1])) { + return false; + } + } + } + + return true; + + function equalLength(a?: T[], b?: T[]): boolean { + return a != null && b != null && a.length === b.length; + } + + function queueReferables(a?: aas.Referable[], b?: aas.Referable[]): boolean { + if (a === b) { + return true; + } + + if (a && b && a.length === b.length) { + for (let i = 0, n = a.length; i < n; i++) { + queue.push([a[i], b[i]]); + } + + return true; + } + + return false; + } + + function equal(a: aas.Referable, b: aas.Referable): boolean { + switch (a.modelType) { + case 'Property': + return equalProperty(a as aas.Property, b as aas.Property); + case 'MultiLanguageProperty': + return equalMultiLanguageProperty(a as aas.MultiLanguageProperty, b as aas.MultiLanguageProperty); + case 'Submodel': + return equalSubmodel(a as aas.Submodel, b as aas.Submodel); + case 'SubmodelElementCollection': + return equalSubmodelElementCollection(a as aas.SubmodelElementCollection, b as aas.SubmodelElementCollection); + case 'SubmodelElementList': + return equalSubmodelElementList(a as aas.SubmodelElementList, b as aas.SubmodelElementList); + case 'AssetAdministrationShell': + return equalShell(a as aas.AssetAdministrationShell, b as aas.AssetAdministrationShell); + case 'ReferenceElement': + return equalReferenceElement(a as aas.ReferenceElement, b as aas.ReferenceElement); + case 'Entity': + return equalEntity(a as aas.Entity, b as aas.Entity); + case 'File': + return equalFile(a as aas.File, b as aas.File); + case 'Blob': + return equalBlob(a as aas.Blob, b as aas.Blob); + case 'ConceptDescription': + return equalConceptDescription(a as aas.ConceptDescription, b as aas.ConceptDescription); + default: + return true; + } + } + + function equalIdentifiable(a: aas.Identifiable, b: aas.Identifiable): boolean { + return equalReferable(a, b) && + a.id === b.id && + equalAdministrativeInformation(a.administration, b.administration); + } + + function equalAdministrativeInformation(a?: aas.AdministrativeInformation, b?: aas.AdministrativeInformation): boolean { + if (a === b) { + return true; + } + + if (!a || !b) { + return false; + } + + return a.version === b.version && a.revision === b.revision; + } + + function equalHasDataSpecification(a: aas.HasDataSpecification, b: aas.HasDataSpecification): boolean { + return equalEmbeddedDataSpecifications(a.embeddedDataSpecifications, b.embeddedDataSpecifications); + } + + function equalEmbeddedDataSpecifications(a?: aas.EmbeddedDataSpecification[], b?: aas.EmbeddedDataSpecification[]): boolean { + if (a === b) { + return true; + } + + if (a && b && a.length === b.length) { + for (let i = 0, n = a.length; i < n; i++) { + if (!equalEmbeddedDataSpecification(a[i], b[i])) { + return false; + } + } + + return true; + } + + return false; + } + + function equalEmbeddedDataSpecification(a: aas.EmbeddedDataSpecification, b: aas.EmbeddedDataSpecification): boolean { + return equalReference(a.dataSpecification, b.dataSpecification) && + equalDataSpecificationContent(a.dataSpecificationContent, b.dataSpecificationContent); + } + + function equalDataSpecificationContent(a: aas.DataSpecificationContent, b: aas.DataSpecificationContent): boolean { + // ToDo: + return true; + } + + function equalHasSemantic(a: aas.HasSemantic, b: aas.HasSemantic): boolean { + return equalReference(a.semanticId, b.semanticId); + } + + function equalQualifiable(a: aas.Qualifiable, b: aas.Qualifiable): boolean { + return equalQualifiers(a.qualifiers, b.qualifiers); + } + + function equalQualifiers(a?: aas.Qualifier[], b?: aas.Qualifier[]): boolean { + if (a === b) { + return true; + } + + if (a && b && a.length === b.length) { + for (let i = 0, n = a.length; i < n; i++) { + if (!equalQualifier(a[i], b[i])) { + return false; + } + } + + return true; + } + + return false; + } + + function equalQualifier(a: aas.Qualifier, b: aas.Qualifier) { + return a.kind === b.kind && a.type === b.type && a.valueType === b.valueType && a.value === b.value && + equalReference(a.valueId, b.valueId); + } + + function equalHasKind(a: aas.HasKind, b: aas.HasKind): boolean { + return a.kind === b.kind; + } + + function equalShell(a: aas.AssetAdministrationShell, b: aas.AssetAdministrationShell): boolean { + if (!equalIdentifiable(a, b) || !equalHasDataSpecification(a, b)) { + return false; + } + + return equalReferences(a.submodels, b.submodels) && + equalAssetInformation(a.assetInformation, b.assetInformation) && + equalReference(a.derivedFrom, b.derivedFrom); + } + + function equalAssetInformation(a: aas.AssetInformation, b: aas.AssetInformation): boolean { + return a.assetKind === b.assetKind && + a.globalAssetId === b.globalAssetId && + equalSpecificIds(a.specificAssetIds, b.specificAssetIds) && + equalResource(a.defaultThumbnail, b.defaultThumbnail); + } + + function equalSpecificIds(a?: aas.SpecificAssetId[], b?: aas.SpecificAssetId[]): boolean { + if (a === b) { + return true; + } + + if (a && b && a.length === b.length) { + for (let i = 0, n = a.length; i < n; i++) { + if (!equalSpecificAssetId(a[i], b[i])) { + return false; + } + } + + return true; + } + + return false; + } + + function equalResource(a?: aas.Resource, b?: aas.Resource): boolean { + return a === b || (a != null && b != null && a.contentType === b.contentType && a.path === b.path); + } + + function equalSubmodel(a: aas.Submodel, b: aas.Submodel): boolean { + return equalIdentifiable(a, b) && + equalHasDataSpecification(a, b) && + equalHasSemantic(a, b) && + equalQualifiable(a, b) && + equalHasKind(a, b) && + queueReferables(a.submodelElements, b.submodelElements); + } + + function equalReferable(a: aas.Referable, b: aas.Referable): boolean { + return a.modelType === b.modelType && + a.idShort === b.idShort && + a.category === b.category && + equalLangStrings(a.descriptions, b.descriptions) && + equalReference(a.parent, b.parent); + } + + function equalSubmodelElement(a: aas.SubmodelElement, b: aas.SubmodelElement): boolean { + return equalReferable(a, b) && + equalHasDataSpecification(a, b) && + equalHasSemantic(a, b) && + equalQualifiable(a, b) && + equalHasKind(a, b); + } + + function equalProperty(a: aas.Property, b: aas.Property): boolean { + if (!equalSubmodelElement(a, b)) { + return false; + } + + if (a.valueType !== b.valueType) { + return false; + } + + if (a.category === 'CONSTANT' || a.category === 'PARAMETER') { + if (a.value !== b.value) { + return false; + } + } + + return equalReference(a.valueId, b.valueId); + } + + function equalMultiLanguageProperty(a: aas.MultiLanguageProperty, b: aas.MultiLanguageProperty): boolean { + return equalSubmodelElement(a, b) && equalLangStrings(a.value, b.value); + } + + function equalSubmodelElementCollection(a: aas.SubmodelElementCollection, b: aas.SubmodelElementCollection): boolean { + return equalSubmodelElement(a, b) && + queueReferables(a.value, b.value); + } + + function equalSubmodelElementList(a: aas.SubmodelElementList, b: aas.SubmodelElementList): boolean { + return equalSubmodelElement(a, b) && + a.orderRelevant === b.orderRelevant && + a.typeValueListElement === b.typeValueListElement && + equalReference(a.semanticIdListElement, b.semanticIdListElement) && + queueReferables(a.value, b.value); + } + + function equalLangStrings(a?: aas.LangString[], b?: aas.LangString[]): boolean { + if (a === b) { + return true; + } + + if (a && b && a.length === b.length) { + for (let i = 0, n = a.length; i < n; i++) { + if (!equalLangString(a[i], b[i])) { + return false; + } + } + + return true; + } + + return false; + } + + function equalReferenceElement(a: aas.ReferenceElement, b: aas.ReferenceElement): boolean { + return equalSubmodelElement(a, b) && equalReference(a.value, b.value); + } + + function equalEntity(a: aas.Entity, b: aas.Entity): boolean { + return equalSubmodelElement(a, b) && + a.entityType == b.entityType && + a.globalAssetId === b.globalAssetId && + equalSpecificAssetId(a.specificAssetId, b.specificAssetId) && + queueReferables(a.statements, b.statements); + } + + function equalSpecificAssetId(a?: aas.SpecificAssetId, b?: aas.SpecificAssetId): boolean { + return a === b || + a != null && b != null && equalHasSemantic(a, b) && a.name === b.name && a.value === b.value && + equalReference(a.externalSubjectId, b.externalSubjectId); + } + + function equalFile(a: aas.File, b: aas.File): boolean { + return equalSubmodelElement(a, b) && a.contentType === b.contentType && a.value === b.value; + } + + function equalBlob(a: aas.Blob, b: aas.Blob): boolean { + return equalSubmodelElement(a, b) && a.contentType === b.contentType && a.value === b.value; + } + + function equalConceptDescription(a: aas.ConceptDescription, b: aas.ConceptDescription): boolean { + return equalSubmodelElement(a, b) && equalReferences(a.isCaseOf, b.isCaseOf); + } + + function equalLangString(a: aas.LangString, b: aas.LangString): boolean { + return a.language === b.language && a.text === b.text; + } + + function equalReferences(a?: aas.Reference[], b?: aas.Reference[]): boolean { + if (a === b) { + return true; + } + + if (a && b && a.length === b.length) { + for (let i = 0, n = a.length; i < n; i++) { + if (!equalReference(a[i], b[i])) { + return false; + } + } + + return true; + } + + return false; + } + + function equalReference(a?: aas.Reference, b?: aas.Reference): boolean { + if (a === b) { + return true; + } + + if (a && b && a.keys && b.keys && (a.keys.length === b.keys.length)) { + for (let i = 0, n = a.keys.length; i < n; i++) { + if (!equalKey(a.keys[i], b.keys[i])) { + return false; + } + } + + return true; + } + + return false; + } + + function equalKey(a: aas.Key, b: aas.Key): boolean { + return a.type === b.type && a.value === b.value; + } +} + +/** + * Removes the specified element form the given parent. + * @param parent The parent. + * @param child The element to be removed. + */ +export function remove(parent: aas.Referable, child: aas.Referable): void { + const children = getChildren(parent); + const index = children.indexOf(child); + if (index >= 0) { + children.splice(index, 1); + } +} + +/** + * Gets the abbreviation for the specified AAS model type. + * @param modelType The AAS model type. + * @returns The corresponding abbreviation. + */ +export function getAbbreviation(modelType: aas.ModelType): AASAbbreviation | undefined { + switch (modelType) { + case 'AnnotatedRelationshipElement': + return 'RelA'; + case 'AssetAdministrationShell': + return 'AAS'; + case 'Capability': + return 'Cap'; + case 'ConceptDescription': + return 'CD'; + case 'Property': + return 'Prop'; + case 'MultiLanguageProperty': + return 'MLP'; + case 'Range': + return 'Range'; + case 'Entity': + return 'Ent'; + case 'BasicEventElement': + return 'Evt'; + case 'File': + return 'File'; + case 'Blob': + return 'Blob'; + case 'Operation': + return 'Opr'; + case 'ReferenceElement': + return 'Ref'; + case 'RelationshipElement': + return 'Rel' + case 'Submodel': + return 'SM'; + case 'SubmodelElementCollection': + return 'SMC'; + case 'SubmodelElementList': + return 'SML'; + default: + return undefined; + } +} + +/** + * Gets the model type that corresponds to the specified abbreviation. + * @param abbreviation The abbreviation. + */ +export function getModelTypeFromAbbreviation(abbreviation: AASAbbreviation): aas.ModelType | undefined { + switch (abbreviation.toLowerCase()) { + case 'aas': + return 'AssetAdministrationShell'; + case 'sm': + return 'Submodel'; + case 'smc': + return 'SubmodelElementCollection'; + case 'sml': + return 'SubmodelElementList'; + case 'prop': + return 'Property'; + case 'mlp': + return 'MultiLanguageProperty'; + case 'ref': + return 'ReferenceElement'; + case 'ent': + return 'Entity'; + case 'file': + return 'File'; + case 'opr': + return 'Operation'; + default: + return undefined; + } +} + +/** + * Selects the referable that belongs to the specified reference. + * @param env The AssetAdministration Shell environment. + * @param reference The reference. + * @returns The referable or `undefined`. + */ +export function selectReferable( + env: aas.Environment, + reference: aas.Reference): T | undefined { + let referable: aas.Referable | undefined; + for (const key of reference.keys) { + switch (key.type) { + case 'AssetAdministrationShell': + referable = env.assetAdministrationShells.find(item => item.id === key.value); + break; + case 'ConceptDescription': + referable = env.conceptDescriptions.find(item => item.id === key.value); + break; + case 'Submodel': + referable = env.submodels.find(item => item.id === key.value); + break; + default: + referable = referable && getChildren(referable).find(item => item.idShort === key.value); + break; + } + + if (!referable) { + break; + } + } + + return referable as T; +} + +/** + * Selects the referable with the specified path in the given AAS environment. + * @param env The Asset Administration Shell environment. + * @param args The path to the SubmodelElement. + * @returns The `Referable` at the specified path. + */ +export function selectElement(env: aas.Environment, ...args: string[]): T | undefined { + let current: aas.Referable | undefined; + if (args.length > 0) { + current = env.submodels?.find(item => item.idShort === args[0] || item.id === args[0]); + if (current) { + for (const idShort of args.slice(1).flatMap(item => item.split('.'))) { + if (current.modelType === 'Submodel') { + current = (current as aas.Submodel).submodelElements?.find(item => item.idShort === idShort); + } else if (current.modelType === 'SubmodelElementCollection') { + current = (current as aas.SubmodelElementCollection).value?.find(item => item.idShort === idShort) + } else if (current.modelType === 'SubmodelElementList') { + current = (current as aas.SubmodelElementList).value?.find(item => item.idShort === idShort) + } + + if (!current) { + break; + } + } + } + } + + return current as T; +} + +/** + * Resolves the specified reference. + * @param env The Asset Administration Shell environment. + * @param reference The reference. + * @returns The referables that belongs to the specified reference. + */ +export function resolveReference( + env: aas.Environment, + reference: aas.Reference): aas.Referable[] | undefined { + let parent: aas.Referable | undefined; + const referables: aas.Referable[] = []; + for (const key of reference.keys) { + let referable: aas.Referable | undefined = undefined; + let children: aas.SubmodelElement[] | undefined = undefined; + if (parent) { + switch (parent.modelType) { + case 'Submodel': + children = (parent as aas.Submodel).submodelElements; + break; + case 'SubmodelElementCollection': + children = (parent as aas.SubmodelElementCollection).value; + break; + case 'SubmodelElementList': + children = (parent as aas.SubmodelElementList).value; + break; + default: + return undefined; + } + + referable = children?.find(child => child.idShort === key.value); + } else { + if (key.type === 'Submodel') { + referable = env.submodels.find(item => item.id === key.value); + } else if (key.type === 'AssetAdministrationShell') { + referable = env.assetAdministrationShells.find(item => item.id === key.value); + } else if (key.type === 'ConceptDescription') { + referable = env.conceptDescriptions.find(item => item.id === key.value); + } + } + + if (!referable) { + return undefined; + } + + referables.push(referable); + parent = referable; + } + + return referables; +} + +/** + * + * @param env + * @param referable + * @returns + */ +export function getIEC61360Content( + env: aas.Environment, + referable: aas.Referable): aas.DataSpecificationIEC61360 | undefined { + const hasDataSpecification = referable as aas.HasDataSpecification; + if (hasDataSpecification.embeddedDataSpecifications) { + for (const item of hasDataSpecification.embeddedDataSpecifications) { + if (item.dataSpecification.keys[0].value === 'http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360') { + return item.dataSpecificationContent as aas.DataSpecificationIEC61360; + } + } + } else { + const semanticId = (referable as aas.HasSemantic).semanticId; + if (semanticId) { + const conceptDescription = selectReferable(env, semanticId); + if (conceptDescription) { + return getIEC61360Content(env, conceptDescription); + } + } + } + + return undefined; +} + +/** + * + * @param env + * @param referable + */ +export function getUnit(env: aas.Environment, referable: aas.Referable): string | undefined { + return getIEC61360Content(env, referable)?.unit; +} + +/** + * + * @param env + * @param referable + * @returns + */ +export function getPreferredName(env: aas.Environment, referable: aas.Referable): aas.LangString[] | undefined { + return getIEC61360Content(env, referable)?.preferredName; +} + +/** + * Returns the children of the specified parent. + * @param parent The current referable. + * @param env The Asset Administration Shell environment. + * @returns The children of the current parent. + */ +export function getChildren(parent: aas.Referable, env?: aas.Environment): aas.Referable[] { + if (parent) { + switch (parent.modelType) { + case 'SubmodelElementCollection': + return (parent as aas.SubmodelElementCollection).value ?? []; + case 'SubmodelElementList': + return (parent as aas.SubmodelElementList).value ?? []; + case 'Submodel': + return (parent as aas.Submodel).submodelElements ?? []; + case 'AssetAdministrationShell': + return env && env.submodels ? env.submodels : []; + } + } + + return []; +} + +/** + * Returns the absolute path of the specified referable. The path starts with identifier of the Submodel + * followed by the names (idShort) up to the specified referable. + * @param referable The referable that is a descendant of a submodel. + * @returns An array where the first element is the identifier of the submodel. + */ +export function getAbsolutePath(referable: aas.Referable): string[] { + if (!referable.parent) { + throw new Error('Argument undefined.'); + } + + const path = referable.parent.keys.map(key => key.value); + path.push(referable.idShort); + return path; +} + +/** + * Gets the idShort path of the specified + * @param referable The current referable. + * @returns The idShort path of the specified referable. + */ +export function getIdShortPath(referable: aas.Referable): string { + if (!referable.parent) { + throw new Error('Invalid operation'); + } + + let idShortPath = ''; + const keys = referable.parent.keys; + for (let i = 1, n = keys.length; i < n; i++) { + idShortPath += keys[i].value + '.'; + } + + idShortPath += referable.idShort; + return idShortPath; +} + +function equalReference(a?: aas.Reference, b?: aas.Reference): boolean { + if (a && b) { + if (a === b) { + return true; + } + + if (a.keys.length === b.keys.length && a.type === b.type && + equalReference(a.referredSemanticId, b.referredSemanticId)) { + for (let i = 0; i < a.keys.length; i++) { + if (a.keys[i].type !== b.keys[i].type || a.keys[i].value === b.keys[i].value) { + return false; + } + } + + return true; + } + } + + return false; +} + diff --git a/projects/common/src/lib/index.ts b/projects/common/src/lib/index.ts new file mode 100644 index 00000000..b5a7dd6c --- /dev/null +++ b/projects/common/src/lib/index.ts @@ -0,0 +1,223 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { + AssetAdministrationShell, + Blob, + Identifiable, + MultiLanguageProperty, + Property, + Referable, + ReferenceElement, + Submodel, + SubmodelElement, + SubmodelElementCollection +} from './aas.js'; + +export * from './document.js'; +export * from './types.js'; +export * from './authentication.js'; +export * from './convert.js'; +export * from './server-message.js'; +export * as aas from './aas.js'; +export * from './application-error.js'; +export * from './multi-key-map.js'; +export * from './keyed-list.js'; + +/** + * Determines whether the specified value represents a valid e-mail. + * @param value The value + * @returns `true` if the specified value represents a valid e-mail; otherwise, `false`. + */ +export function isValidEMail(value: string | undefined): boolean { + return typeof value === 'string' && + value.length >= 5 && + /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value); +} + +/** + * Determines whether the specified value represents a valid password. + * @param value A text expression. + * @returns `true` if the specified value represents a valid password; otherwise, `false`. + */ +export function isValidPassword(value: string | undefined): boolean { + return typeof value === 'string' && + /^[\S]+$/.test(value) && + value.length >= 8 && + value.length <= 20 && + /^[a-zA-Z0-9-+_$%!§?#*~.,;:/]+$/.test(value); +} + +/** + * Converts the value of objects to strings based on the formats specified and inserts them into another string. + * @param format A composite format string. + * @param args An object array that contains zero or more objects to format. + * @returns A copy of format in which the format items have been replaced by the string representation of the corresponding objects in args. + */ +export function stringFormat(format: string, ...args: any[]) { + try { + return format.replace(/{(\d+)}/g, (match, index) => { + index = Number(index); + const arg: any = index >= 0 && index < args.length ? args[index] : undefined; + if (typeof arg === 'undefined') { + return ''; + } else if (arg === null) { + return ''; + } else if (typeof arg === 'string') { + return arg; + } else if (typeof arg === 'number') { + return arg.toString(); + } else if (typeof arg === 'boolean') { + return arg ? 'true' : 'false'; + } else if ('toString' in arg) { + return arg.toString(); + } else { + return match; + } + }); + } catch (error) { + return format; + } +} + +/** + * Compares two URls for equality. + * @param url1 The first URL. + * @param url2 The seconde URL. + * @returns `true` if both URLs are equal; otherwise, `false`. + */ +export function equalUrls(url1: string, url2: string): boolean { + try { + return url1 === url2 || equals(new URL(url1), new URL(url2)); + } catch (_) { + return false; + } + + function equals(a: URL, b: URL): boolean { + return a.protocol === b.protocol && a.host === b.host && a.pathname === b.pathname; + } +} + +/** + * Determines whether the specified value represents a submodel element. + * @param value The current value. + * @returns `true` if the specified value represents a submodel element; otherwise, `false`. + */ +export function isSubmodelElement(value: any): value is SubmodelElement { + if (value && (value as Referable).modelType) { + switch ((value as Referable).modelType) { + case 'ReferenceElement': + case 'Property': + case 'MultiLanguageProperty': + case 'Range': + case 'Blob': + case 'File': + case 'RelationshipElement': + case 'Capability': + case 'SubmodelElementCollection': + case 'SubmodelElementList': + case 'Operation': + case 'BasicEventElement': + case 'Entity': + case 'AnnotatedRelationshipElement': + return true; + default: + return false; + } + } + + return false; +} + +/** + * Indicates whether the specified referable if of type Identifiable. + * @param referable The referable. + * @returns `true` if the specified referable is of type Identifiable. + */ +export function isIdentifiable(referable?: Referable | null): referable is Identifiable { + switch (referable?.modelType) { + case 'AssetAdministrationShell': + case 'Submodel': + case 'ConceptDescription': + return true; + default: + return false; + } +} + +/** + * Determines whether the specified referable represents a `AssetAdministrationShell`. + * @param value The current referable. + * @returns `true` if the specified referable represents a `AssetAdministrationShell`; otherwise, `false`. + */ +export function isAssetAdministrationShell(referable?: Referable | null): referable is AssetAdministrationShell { + return referable?.modelType === 'AssetAdministrationShell'; +} + +/** + * Determines whether the specified referable represents a `Submodel`. + * @param value The current referable. + * @returns `true` if the specified referable represents a `Submodel`; otherwise, `false`. + */ +export function isSubmodel(referable?: Referable | null): referable is Submodel { + return referable?.modelType === 'Submodel'; +} + +/** + * Determines whether the specified referable represents a `Property`. + * @param value The current referable. + * @returns `true` if the specified referable represents a `Property`; otherwise, `false`. + */ +export function isProperty(referable?: Referable | null): referable is Property { + return referable?.modelType === 'Property'; +} + +/** + * Determines whether the specified referable represents a `Blob`. + * @param value The current referable. + * @returns `true` if the specified referable represents a `Blob`; otherwise, `false`. + */ +export function isBlob(referable?: Referable | null): referable is Blob { + return referable?.modelType === 'Blob'; +} + +/** + * Determines whether the specified referable represents a `MultiLanguageProperty`. + * @param value The current referable. + * @returns `true` if the specified referable represents a `MultiLanguageProperty`; otherwise, `false`. + */ +export function isMultiLanguageProperty(referable?: Referable | null): referable is MultiLanguageProperty { + return referable?.modelType === 'MultiLanguageProperty'; +} + +/** + * Determines whether the specified referable represents a reference element. + * @param value The current referable. + * @returns `true` if the specified referable represents a `ReferenceElement`; otherwise, `false`. + */ +export function isReferenceElement(referable?: Referable | null): referable is ReferenceElement { + return referable?.modelType === 'ReferenceElement'; +} + +/** + * Determines whether the specified referable represents a reference element. + * @param value The current referable. + * @returns `true` if the specified referable represents a `SubmodelElementCollection`; otherwise, `false`. + */ +export function isSubmodelElementCollection(referable?: Referable | null): referable is SubmodelElementCollection { + return referable?.modelType === 'SubmodelElementCollection'; +} + +/** + * Checks if the specified string is url-safe-base64 encoded + * @param s The string to test. + * @return true if url-safe-base64 encoded + */ +export function isUrlSafeBase64(s: string): boolean { + return /^[A-Za-z0-9_-]*[.=]{0,2}$/.test(s); +} \ No newline at end of file diff --git a/projects/common/src/lib/keyed-list.ts b/projects/common/src/lib/keyed-list.ts new file mode 100644 index 00000000..7d30d3fb --- /dev/null +++ b/projects/common/src/lib/keyed-list.ts @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export class KeyedList { + private readonly map = new Map(); + private readonly list: TValue[] = []; + + constructor(private readonly getKey: (value: TValue) => TKey, values?: TValue[]) { + if (values) { + values.forEach(value => this.set(value)); + } + } + + public get length(): number { + return this.list.length; + } + + public *values(): Generator { + for (const value of this.list) { + yield value; + } + } + + public keys(): IterableIterator { + return this.map.keys(); + } + + public getValue(index: number): TValue { + return this.list[index]; + } + + public has(key: TKey): boolean { + return this.map.has(key); + } + + public get(key: TKey): TValue | undefined { + return this.map.get(key); + } + + public set(value: TValue): void { + const key = this.getKey(value); + if (this.map.has(key)) { + this.list[this.list.findIndex(item => this.getKey(item) === key)] = value; + } else { + this.list.push(value); + } + + this.map.set(key, value); + } + + public delete(key: TKey): boolean { + const index = this.list.findIndex(item => this.getKey(item) === key); + if (index >= 0) { + this.list.splice(index, 1); + this.map.delete(key); + return true; + } + + return false; + } + + public clear(): void { + this.list.splice(0, this.list.length); + this.map.clear(); + } +} \ No newline at end of file diff --git a/projects/common/src/lib/multi-key-map.ts b/projects/common/src/lib/multi-key-map.ts new file mode 100644 index 00000000..fe1b55ca --- /dev/null +++ b/projects/common/src/lib/multi-key-map.ts @@ -0,0 +1,77 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +export class MultiKeyMap { + private _keyMap = new Map(); + private _valueMap = new Map(); + + public get size(): number { + return this._keyMap.size; + } + + public values(): IterableIterator { + return this._valueMap.keys(); + } + + public keys(): IterableIterator { + return this._keyMap.keys(); + } + + public set(key: TKey, value: TValue) { + if (this._valueMap.has(value)) { + throw new Error(`The value ${value} already exists.`); + } + + const oldValue = this._keyMap.get(key); + if (oldValue) { + this._valueMap.delete(oldValue); + } + + this._keyMap.set(key, value); + this._valueMap.set(value, key); + } + + public getValue(key: TKey): TValue | undefined { + return this._keyMap.get(key); + } + + public getKey(value: TValue): TKey | undefined { + return this._valueMap.get(value); + } + + public hasValue(key: TKey): boolean { + return this._keyMap.has(key); + } + + public hasKey(value: TValue): boolean { + return this._valueMap.has(value); + } + + public deleteValue(key: TKey): boolean { + const value = this._keyMap.get(key); + if (value) { + this._valueMap.delete(value); + } + + return this._keyMap.delete(key); + } + + public deleteKey(value: TValue): boolean { + const key = this._valueMap.get(value); + if (key) { + this._keyMap.delete(key); + } + + return this._valueMap.delete(value); + } + + public clear(): void { + this._keyMap.clear(); + this._valueMap.clear(); + } +} \ No newline at end of file diff --git a/projects/common/src/lib/server-message.ts b/projects/common/src/lib/server-message.ts new file mode 100644 index 00000000..c2066c62 --- /dev/null +++ b/projects/common/src/lib/server-message.ts @@ -0,0 +1,33 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { AASContainer, AASDocument } from './types.js'; + +/** Defines the message types. */ +export type AASServerMessageType = + 'Added' | + 'Removed' | + 'Changed' | + 'Offline' | + 'ContainerAdded' | + 'ContainerRemoved' | + 'EndpointAdded' | + 'EndpointRemoved' | + 'Reset'; + +/** Server message. */ +export interface AASServerMessage { + /** The type of change. */ + type: AASServerMessageType; + /** The container if type `ContainerAdded` and `ContainerRemoved`. */ + container?: AASContainer; + /** The endpoint if type `ContainerAdded`, `ContainerRemoved`, `EndpointAdded`, `EndpointRemoved`. */ + endpoint?: string; + /** The document if type `Added`, `Removed` or `Changed` */ + document?: AASDocument; +} \ No newline at end of file diff --git a/projects/common/src/lib/types.ts b/projects/common/src/lib/types.ts new file mode 100644 index 00000000..4c86bfb7 --- /dev/null +++ b/projects/common/src/lib/types.ts @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as aas from "./aas.js"; + +/** Defines the supported endpoint types. */ +export type EndpointType = 'file' | 'http' | 'opc'; + +/** Represents an endpoint of a AAS resource. */ +export interface Endpoint { + address: string; + type: EndpointType; +} + +/** Abbreviations for AAS model elements. */ +export type AASAbbreviation = + 'AAS' | + 'Cap' | + 'CD' | + 'DE' | + 'DST' | + 'Ent' | + 'Evt' | + 'InOut' | + 'In' | + 'Id' | + 'MLP' | + 'File' | + 'Blob' | + 'Opr' | + 'Out' | + 'Qfr' | + 'Prop' | + 'Range' | + 'Ref' | + 'Rel' | + 'RelA' | + 'SM' | + 'SMC' | + 'SME' | + 'SML' ; + +/** Represents a server (AASX, OPC-UA) or file directory (AASX package files). */ +export interface AASContainer { + /** The URL of the container endpoint. */ + url: string; + /** An alias for the container. */ + name: string; + /** The AAS documents that this container provides. */ + documents?: AASDocument[]; +} + +/** Represents an Asset Administration Shell */ +export interface AASDocument { + /** The identification of the Asset Administration Shell. */ + id: string; + /** The name of the AAS. */ + idShort: string; + /** The address of the resource containing the AAS. */ + endpoint: Endpoint; + /** The reference of the container from which the AAS comes. */ + container: string; + /** A time stamp that represents the current state of the AAS. */ + timeStamp: number; + /** Indicates whether the document can be edited. */ + readonly: boolean; + /** Indicates whether the document is modified. */ + modified?: boolean; + /** Indicates whether communication can be established with the system represented by the AAS. */ + onlineReady?: boolean; + /** The root element of the AAS structure (content), `null` if the content is not loaded or + * `undefined` if the content is not available. */ + content?: aas.Environment | null; +} + +/** Describes a template. */ +export interface TemplateDescriptor { + name: string; + endpoint?: Endpoint; + format?: '.json' | '.xml'; + template?: aas.Referable; +} + +/** Represents a named source of Asset Administration Shells. */ +export interface AASWorkspace { + /** The configuration name. */ + name: string; + /** The assigned containers */ + containers: AASContainer[]; +} + +export interface LiveValue { + nodeId: string; + value?: any; + timeStamp?: number; +} + +export interface LiveNode { + nodeId: string; + value?: any; + valueType: aas.DataTypeDefXsd; + timeStamp?: number; +} + +export interface LiveRequest { + type: EndpointType; + url: string; + id: string; + nodes: LiveNode[] +} + +/** The kind of AAS container or server. */ +export type AASEndpointType = 'AasxDirectory' | 'AasxServer' | 'OpcuaServer' | 'AASRegistry'; + +export interface PackageInfo { + name: string; + version: string; + author: string; + description: string; + license: string; + homepage: string; + libraries: Library[]; +} + +export type DirEntry = { + type: 'file' | 'dir'; + name: string; + dir: string; + size: number; + mtime: Date; + url: string | null; +}; + +/** */ +export interface ErrorData { + method: string; + type: string; + name: string; + message: string; + args: any[]; +} + +/** Provides information about a 3rd-party package. */ +export interface Library { + name: string; + version?: string; + description?: string; + license?: string; + homepage?: string; +} + +/** Defines the message types. */ +export type MessageType = 'Error' | 'Warning' | 'Info'; + +/** Represents a AAS-Server message. */ +export interface Message { + /** The message type. */ + type: MessageType; + /** The time when the message occurred. */ + timestamp: number; + /** The message. */ + text: string; +} + +/** Represents a cookie. */ +export interface Cookie { + name: string; + data: string; +} + +/** The Websocket data. */ +export interface WebSocketData { + /** The message type. */ + type: string; + /** The data. */ + data: any; +} diff --git a/projects/common/src/test/assets/aas-environment.ts b/projects/common/src/test/assets/aas-environment.ts new file mode 100644 index 00000000..bc592003 --- /dev/null +++ b/projects/common/src/test/assets/aas-environment.ts @@ -0,0 +1,1491 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as aas from "../../lib/aas.js"; + +const data = { + "assetAdministrationShells": [ + { + "idShort": "ExampleMotor", + "modelType": "AssetAdministrationShell", + "category": "CONSTANT", + "id": "http://customer.com/aas/9175_7013_7091_9168", + "assetInformation": { + "assetKind": "Instance", + "globalAssetId": { + "type": "ModelReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://customer.com/assets/KHBVZJSQKIY" + } + ] + } + }, + "submodels": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + } + ] + } + ], + "submodels": [ + { + "idShort": "Identification", + "modelType": "Submodel", + "category": "CONSTANT", + "descriptions": [ + { + "language": "EN", + "text": "Identification from Manufacturer" + } + ], + "id": "http://i40.customer.com/type/1/1/F13E8576F6488342", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-ADN198#009" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "Manufacturer", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAO677#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH" + }, + { + "idShort": "GLN", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAY812#001" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "10101010" + }, + { + "idShort": "ProductDesignation", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAW338#001" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "I40 Capable Servo Motor (EN)" + }, + { + "idShort": "SerialNumber", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/F13E8576F6488342" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#02-AAM556#002" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "P12345678I40" + } + ] + }, + { + "idShort": "TechnicalData", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "MaxRotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAA120#008" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "5000" + }, + { + "idShort": "MaxTorque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE098#004" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "200" + }, + { + "idShort": "CoolingType", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http.//i40.customer.com/type/1/1/7A7104BDAB57E184" + } + ] + }, + "category": "PARAMETER", + "descriptions": [ + { + "language": "EN", + "text": "open circuit, external cooling" + } + ], + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-BAE122#006" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "BAB657" + } + ] + }, + { + "idShort": "Documentation", + "modelType": "Submodel", + "category": "CONSTANT", + "id": "http://i40.customer.com/type/1/1/1A7B62B529F19152", + "semanticId": { + "type": "ModelReference", + "keys": [] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "OperatingManual", + "modelType": "SubmodelElementCollection", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document" + } + ] + }, + "kind": "Instance", + "value": [ + { + "idShort": "DocumentId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "CONSTANT", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "3 608 870 A47" + }, + { + "idShort": "DocumentClassId", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "03-02", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassId" + }, + { + "idShort": "DocumentClassName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operation (EN) Bedienung (DE)", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassName" + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "VDI2770:2018", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/DocumentClassificationSystem" + }, + { + "idShort": "OrganizationName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationName" + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "CUSTOMER GmbH", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/OrganizationOfficialName" + }, + { + "idShort": "Title", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title" + } + ] + }, + "kind": "Instance", + "valueType": "langString", + "value": "Operating Manual Servo Motor", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Title" + }, + { + "idShort": "Language", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language" + } + ] + }, + "kind": "Instance", + "valueType": "xs:string", + "value": "en-US", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vdHlwZS8xLzEvMUE3QjYyQjUyOUYxOTE1Mg.Documentation/OperatingManual/Language" + }, + { + "idShort": "DigitalFile_PDF", + "modelType": "File", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + "type": "SubmodelElementCollection", + "value": "OperatingManual" + } + ] + }, + "category": "PARAMETER", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile" + } + ] + }, + "kind": "Instance", + "contentType": "application/pdf", + "value": "/aasx/OperatingManual.pdf" + } + ] + } + ] + }, + { + "idShort": "OperationalData", + "modelType": "Submodel", + "category": "VARIABLE", + "id": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935", + "semanticId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#01-AFZ615#016" + } + ] + }, + "qualifiers": [], + "kind": "Instance", + "submodelElements": [ + { + "idShort": "RotationSpeed", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D895" + } + ] + }, + "kind": "Instance", + "valueType": "xs:integer", + "value": "4370", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/RotationSpeed" + }, + { + "idShort": "Torque", + "modelType": "Property", + "parent": { + "type": "ModelReference", + "keys": [ + { + "type": "Submodel", + "value": "http://i40.customer.com/instance/1/1/AC69B1CB44F07935" + } + ] + }, + "category": "VARIABLE", + "semanticId": { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "http://customer.com/cd//1/1/18EBD56F6B43D896" + } + ] + }, + "kind": "Instance", + "valueType": "xs:float", + "value": "117.4", + "nodeId": "aHR0cDovL2k0MC5jdXN0b21lci5jb20vaW5zdGFuY2UvMS8xL0FDNjlCMUNCNDRGMDc5MzU.OperationalData/Torque" + } + ] + } + ], + "conceptDescriptions": [ + { + "idShort": "Document", + "modelType": "ConceptDescription", + "descriptions": [], + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Document", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "ENTITY", + "definition": [ + { + "language": "DE", + "text": "Feste und geordnete Menge von für die Verwendung durch Personen bestimmte Informationen, die verwaltet und als Einheit zwischen Benutzern und System ausgetauscht werden kann." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Document" + } + ], + "sourceOfDefinition": "[ISO 15519-1:2010]" + } + } + ] + }, + { + "idShort": "DocumentIdValue", + "modelType": "ConceptDescription", + "category": "CONSTANT", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "die eigentliche Identifikationsnummer" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassId", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassId", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige ID der Klasse in einer Klassifikation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassId" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Liste von sprachabhängigen Namen zur ClassId. " + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassName" + } + ] + } + } + ] + }, + { + "idShort": "DocumentClassificationSystem", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentClassification/ClassificationSystem", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Classification System" + }, + { + "language": "DE", + "text": "Klassifikationssystem" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eindeutige Kennung für ein Klassifikationssystem. Für Klassifikationen nach VDI 2770 muss \"VDI2770:2018\" verwenden werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentClassificationSystem" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "gebräuchliche Bezeichnung für Organisation" + }, + { + "language": "EN", + "text": "organization name" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Die gebräuchliche Bezeichnung für die Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationName" + } + ] + } + } + ] + }, + { + "idShort": "OrganizationOfficialName", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Organization/OrganizationOfficialName", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "offizieller Name der Organisation" + }, + { + "language": "EN", + "text": "official name of the organization" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Der offizielle Namen der Organisation." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "OrganizationOfficialName" + } + ] + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [ + { + "type": "ConceptDescription", + "value": "0173-1#02-AAO677#002" + } + ] + } + ] + }, + { + "idShort": "DocumentVersion", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Version des Dokuments" + } + ], + "definition": [ + { + "language": "DE", + "text": "Zu jedem Dokument muss eine Menge von mindestens einer Dokumentenversion existieren. Es können auch mehrere Dokumentenversionen ausgeliefert werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersion" + } + ] + } + } + ] + }, + { + "idShort": "Language", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersion/Language", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Language" + }, + { + "language": "DE", + "text": "Sprache" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Eine Liste der im Dokument verwendeten Sprachen." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Language" + } + ] + } + } + ] + }, + { + "idShort": "Title", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/Description/Title", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Title" + }, + { + "language": "DE", + "text": "Titel" + } + ], + "dataType": "STRING_TRANSLATABLE", + "definition": [ + { + "language": "DE", + "text": "Sprachabhängiger Titel des Dokuments." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Title" + } + ] + } + } + ] + }, + { + "idShort": "Date", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/LifeCycleStatus/SetDate", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "DATE", + "definition": [ + { + "language": "DE", + "text": "Datum und Uhrzeit, an dem der Status festgelegt wurde. Es muss das Datumsformat „YYYY-MM-dd“ verwendet werden (Y = Jahr, M = Monat, d = Tag, siehe ISO 8601)." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "SetDate" + } + ] + } + } + ] + }, + { + "idShort": "DocumentVersionIdValue", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/DocumentVersionId/Val", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "www.admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Verschiedene Versionen eines Dokuments müssen eindeutig identifizierbar sein. Die DocumentVersionId stellt eine innerhalb einer Domäne eindeutige Versionsidentifikationsnummer dar." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DocumentVersionId" + } + ] + } + } + ] + }, + { + "idShort": "DigitalFile", + "modelType": "ConceptDescription", + "id": "www.vdi2770.com/blatt1/Entwurf/Okt18/cd/StoredDocumentRepresentation/DigitalFile", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "FILE", + "definition": [ + { + "language": "DE", + "text": "Eine Datei, die die DocumentVersion repräsentiert. Neben der obligatorischen PDF/A Datei können weitere Dateien angegeben werden." + } + ], + "shortName": [ + { + "language": "EN?", + "text": "DigitalFile" + } + ] + } + } + ] + }, + { + "idShort": "MaxRotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAA120#008", + "administration": { + "version": "", + "revision": "2" + }, + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "de", + "text": "max. Drehzahl" + }, + { + "language": "en", + "text": "Max. rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "de", + "text": "Höchste zulässige Drehzahl, mit welcher der Motor oder die Speiseinheit betrieben werden darf" + }, + { + "language": "en", + "text": "Greatest permissible rotation speed with which the motor or feeding unit may be operated" + } + ], + "shortName": [], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ], + "isCaseOf": [ + { + "type": "ModelReference", + "keys": [] + } + ] + }, + { + "idShort": "MaxTorque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE098#004", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ModelReference", + "keys": [] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "Max. torque" + } + ], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Greatest permissible mechanical torque which the motor can pass on at the drive shaft" + }, + { + "language": "DE", + "text": "Größtes mechanisch zulässiges Drehmoment, welches der Motor an der Abtriebswelle abgeben kann" + } + ], + "shortName": [], + "unit": "Nm", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA212#003" + } + ] + } + } + } + ] + }, + { + "idShort": "RotationSpeed", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D895", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Aktuelle Drehzahl" + }, + { + "language": "EN", + "text": "Actual rotation speed" + } + ], + "dataType": "INTEGER_MEASURE", + "definition": [ + { + "language": "Atkuelle Drehzahl, mit welcher der Motor oder die Speiseinheit betri", + "text": "eben wird" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "RotationSpeed" + } + ], + "unit": "1/min", + "unitId": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "0173-1#05-AAA650#002" + } + ] + } + } + } + ] + }, + { + "idShort": "Torque", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "http://customer.com/cd//1/1/18EBD56F6B43D896", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [], + "dataType": "REAL_MEASURE", + "definition": [ + { + "language": "EN", + "text": "Actual mechanical torque which the motor passes on at the drive shaft" + }, + { + "language": "DE", + "text": "Atkuelles Drehmoment, welches der Motor an der Abtriebswelle abgibt" + } + ], + "shortName": [ + { + "language": "EN?", + "text": "Torque" + } + ], + "unit": "Nm", + "unitId": { + "type": "ModelReference", + "keys": [] + } + } + } + ] + }, + { + "idShort": "CoolingType", + "modelType": "ConceptDescription", + "category": "PROPERTY", + "id": "0173-1#02-BAE122#006", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "DE", + "text": "Art der Kühlung" + }, + { + "language": "EN", + "text": "Cooling type" + } + ], + "dataType": "STRING", + "definition": [ + { + "language": "DE", + "text": "Zusammenfassung verschiedener Kühlarten, um für Suchmerkmale zu einer begrenzten Auswahl zu kommen" + }, + { + "language": "EN", + "text": "Summary of various types of cooling, for use as search criteria that limit a selection" + } + ], + "shortName": [] + } + } + ] + }, + { + "idShort": "BAB657", + "modelType": "ConceptDescription", + "category": "VALUE", + "id": "0173-1#07-BAB657#003", + "embeddedDataSpecifications": [ + { + "dataSpecification": { + "type": "ExternalReference", + "keys": [ + { + "type": "GlobalReference", + "value": "http://admin-shell.io/DataSpecificationTemplates/DataSpecificationIEC61360" + } + ] + }, + "dataSpecificationContent": { + "modelType": "DataSpecificationIEC61360", + "preferredName": [ + { + "language": "EN", + "text": "open circuit, external cooling" + }, + { + "language": "DE", + "text": "offener Kreis, Fremdkühlung " + } + ], + "dataType": "STRING", + "definition": [], + "shortName": [] + } + } + ] + } + ] +}; + +export const aasEnvironment: aas.Environment = data; \ No newline at end of file diff --git a/projects/common/src/test/assets/samples.ts b/projects/common/src/test/assets/samples.ts new file mode 100644 index 00000000..e1e75312 --- /dev/null +++ b/projects/common/src/test/assets/samples.ts @@ -0,0 +1,19 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import * as aas from "../../lib/aas.js"; +import { selectElement } from "../../lib/document.js"; +import { aasEnvironment } from "./aas-environment.js"; + +export const testSubmodel: aas.Submodel = selectElement(aasEnvironment, 'TechnicalData')!; + +export const testProperty: aas.Property = selectElement(aasEnvironment, 'TechnicalData', 'MaxRotationSpeed')!; + +export const testSubmodelElementCollection: aas.SubmodelElementCollection = selectElement( + aasEnvironment, + 'Documentation', 'OperatingManual')!; \ No newline at end of file diff --git a/projects/common/src/test/authentication.spec.ts b/projects/common/src/test/authentication.spec.ts new file mode 100644 index 00000000..3f190025 --- /dev/null +++ b/projects/common/src/test/authentication.spec.ts @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { describe, it, expect } from '@jest/globals' +import { getUserNameFromEMail, isUserAuthorized } from "../lib/authentication.js"; + +describe('authentication', function () { + describe('getUserNameFromEMail', function () { + it('gets John Doe from john.doe@email.com', function () { + expect(getUserNameFromEMail('john.doe@email.com')).toEqual('John Doe'); + }); + + it('gets John Doe from john-doe@email.com', function () { + expect(getUserNameFromEMail('john-doe@email.com')).toEqual('John Doe'); + }); + + it('gets Johndoe from johndoe@email.com', function () { + expect(getUserNameFromEMail('johndoe@email.com')).toEqual('Johndoe'); + }); + + it('gets "" from empty e-mail', function () { + expect(getUserNameFromEMail('')).toEqual(''); + }); + }); + + describe('isUserAuthorized', function () { + it('true for actual: guest, expected: guest', function () { + expect(isUserAuthorized('guest', 'guest')).toBeTruthy(); + }); + + it('false for actual: guest, expected: editor', function () { + expect(isUserAuthorized('guest', 'editor')).toBeFalsy(); + }); + + it('false for actual: guest, expected: admin', function () { + expect(isUserAuthorized('guest', 'admin')).toBeFalsy(); + }); + + it('true for actual: editor, expected: guest', function () { + expect(isUserAuthorized('editor', 'guest')).toBeTruthy(); + }); + + it('true for actual: editor, expected: editor', function () { + expect(isUserAuthorized('editor', 'editor')).toBeTruthy(); + }); + + it('false for actual: editor, expected: admin', function () { + expect(isUserAuthorized('editor', 'admin')).toBeFalsy(); + }); + + it('true for actual: admin, expected: guest', function () { + expect(isUserAuthorized('admin', 'guest')).toBeTruthy(); + }); + + it('true for actual: admin, expected: editor', function () { + expect(isUserAuthorized('admin', 'editor')).toBeTruthy(); + }); + + it('true for actual: admin, expected: admin', function () { + expect(isUserAuthorized('admin', 'admin')).toBeTruthy(); + }); + }); +}); \ No newline at end of file diff --git a/projects/common/src/test/convert.spec.ts b/projects/common/src/test/convert.spec.ts new file mode 100644 index 00000000..f17c0ca8 --- /dev/null +++ b/projects/common/src/test/convert.spec.ts @@ -0,0 +1,396 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { describe, it, expect } from '@jest/globals' +import { LangString } from '../lib/aas.js'; +import { + changeType, + determineType, + convertFromString, + getLocaleValue, + getDefaultValue, + convertToString, + isBooleanType, + parseDate, + toLocale, + toInvariant, + parseNumber, + toBoolean +} from '../lib/convert.js'; + +describe('Convert', function () { + describe('convertFromString', function () { + it('converts "true", "false" to xs:boolean', function () { + expect(convertFromString('false', 'xs:boolean')).toBeFalsy(); + expect(convertFromString('true', 'xs:boolean')).toBeTruthy(); + }); + + it('to number', function () { + expect(convertFromString('-128', 'xs:byte')).toEqual(-128); + expect(convertFromString('0xff', 'xs:byte')).toEqual(-1); + expect(convertFromString('-1', 'xs:unsignedByte')).toBeUndefined(); + expect(convertFromString('0xff', 'xs:unsignedByte')).toEqual(255); + }); + + it('localized to number', function () { + expect(convertFromString('1.234', 'xs:double', 'en-us')).toEqual(1.234); + expect(convertFromString('1,234', 'xs:double', 'de-de')).toEqual(1.234); + }); + + it('returns undefined when try to convert "abc" to int', function () { + expect(convertFromString('abc', 'xs:int')).toBeUndefined(); + }); + + it('returns undefined when try to convert null to int', function () { + expect(convertFromString(null, 'xs:int')).toBeUndefined(); + }); + + it('returns undefined when try to convert undefined to int', function () { + expect(convertFromString(undefined, 'xs:int')).toBeUndefined(); + }); + }); + + describe('convertToString', function () { + it('converts "Hello World!" to "Hello World!"', function () { + expect(convertToString('Hello World!')).toEqual('Hello World!'); + }); + + it('converts true to "true"', function () { + expect(convertToString(true)).toEqual('true'); + }); + + it('converts false to "false"', function () { + expect(convertToString(false)).toEqual('false'); + }); + + it('converts 42 to "42"', function () { + expect(convertToString(42)).toEqual('42'); + }); + + it('converts 42n to "42"', function () { + expect(convertToString(42n)).toEqual('42'); + }); + + it('converts 42.123 to "42,123" (de-de)', function () { + expect(convertToString(42.123, 'de-de')).toEqual('42,123'); + }); + + it('converts 42.123 to "42.123" (en-us)', function () { + expect(convertToString(42.123, 'en-us')).toEqual('42.123'); + }); + + it('converts new Date(123456) to "1.1.1970, 01:02:03" (de-de)', function () { + expect(convertToString(new Date('1/1/1970, 1:02:03 AM'), 'de-de')).toEqual('1.1.1970, 01:02:03'); + }); + + it('converts new Date(123456) to "1/1/1970, 1:02:03 AM" (en-us)', function () { + expect(convertToString(new Date('1/1/1970, 1:02:03 AM'), 'en-us')).toEqual('1/1/1970, 1:02:03 AM'); + }); + + it ('converts an array', function() { + expect(convertToString([1, 2])).toEqual('[1, 2]'); + }); + + it('converts an object', function() { + expect(convertToString({ text: 'Hello world!', number: 42 })).toEqual('{ text: Hello world!, number: 42 }'); + }); + }); + + describe('changeType', function () { + it('leaves number as number', function () { + expect(changeType(1.23, 'xs:double')).toEqual(1.23); + }); + + it('leaves boolean as boolean', function () { + expect(changeType(true, 'xs:boolean')).toEqual(true); + }); + + it('leaves string as string', function () { + expect(changeType('Hello World!', 'xs:string')).toEqual('Hello World!'); + }); + + it('leaves Date as Date', function () { + const date = new Date(); + expect(changeType(date, 'xs:dateTime')).toEqual(date.getTime()); + }); + + it('converts string to boolean', function () { + expect(changeType('true', 'xs:boolean')).toEqual(true); + expect(changeType('false', 'xs:boolean')).toEqual(false); + expect(changeType('', 'xs:boolean')).toEqual(false); + expect(changeType('0', 'xs:boolean')).toEqual(false); + expect(changeType('Hello World!', 'xs:boolean')).toEqual(true); + }); + + it('converts number to boolean', function () { + expect(changeType(0.0, 'xs:boolean')).toEqual(false); + expect(changeType(1.0, 'xs:boolean')).toEqual(true); + expect(changeType(-1, 'xs:boolean')).toEqual(true); + }); + + it('converts string to double', function () { + expect(changeType('1.0', 'xs:double')).toEqual(1.0); + }); + + it('converts de-de string to double', function () { + expect(changeType('1,123', 'xs:double', 'de-de')).toEqual(1.123); + }); + + it('converts boolean to double', function () { + expect(changeType(true, 'xs:double')).toEqual(1.0); + expect(changeType(false, 'xs:double')).toEqual(0.0); + }); + }); + + describe('determineType', function () { + it('recognize as boolean', function () { + expect(determineType('true')).toEqual('xs:boolean'); + expect(determineType('false')).toEqual('xs:boolean'); + expect(determineType('TRUE')).toEqual('xs:boolean'); + expect(determineType('FALSE')).toEqual('xs:boolean'); + }); + + it('recognizes "1.23" as double', function () { + expect(determineType('1.23')).toEqual('xs:double'); + }); + + it('recognizes "42" as int', function () { + expect(determineType('42')).toEqual('xs:int'); + }); + + it('recognizes as dateTime', function () { + expect(determineType(new Date().toString())).toEqual('xs:dateTime'); + }); + + it('recognizes "Hello World!" as string', function () { + expect(determineType('Hello World!')).toEqual('xs:string'); + expect(determineType('')).toEqual('xs:string'); + }); + + it('recognizes as undefined', function () { + expect(determineType(null)).toBeUndefined; + expect(determineType(undefined)).toBeUndefined; + }); + + it('returns 42 as int', function () { + expect(determineType(42)).toEqual('xs:int'); + }); + + it('returns 42.123 as double', function () { + expect(determineType(42.123)).toEqual('xs:double'); + }); + + it('returns true as boolean', function () { + expect(determineType(true)).toEqual('xs:boolean'); + }); + + it('returns 281474976710656n as long', function () { + expect(determineType(281474976710656n)).toEqual('xs:long'); + }); + + it('returns new Date() as dateTime', function () { + expect(determineType(new Date())).toEqual('xs:dateTime'); + }); + }); + + describe('getLocaleValue', function () { + let localizable: LangString[]; + + beforeEach(() => { + localizable = [ + { + language: 'en-us', + text: 'Hello World!' + }, + { + language: 'de-de', + text: 'Hallo Deutschland!' + }, + { + language: 'de-LU', + text: 'Hallo Luxembourg!' + }, + { + language: 'de', + text: 'Hallo Welt!' + } + ]; + }); + + it('gets "Hello World!" for en-us', function () { + expect(getLocaleValue(localizable, 'en-us')).toEqual('Hello World!'); + }); + + it('gets "Hallo Welt!" for de-de', function () { + expect(getLocaleValue(localizable, 'de-de')).toEqual('Hallo Deutschland!') + }); + + it('gets "Hallo Welt!" for de', function () { + expect(getLocaleValue(localizable, 'de')).toEqual('Hallo Welt!') + }); + + it('gets "Hallo Welt!" for de-ch', function () { + expect(getLocaleValue(localizable, 'de-lu')).toEqual('Hallo Luxembourg!') + }); + + it('gets first entry for unknown language', function () { + expect(getLocaleValue(localizable, 'fr-fr')).toEqual('Hello World!'); + }); + }); + + describe('getDefaultValue', function () { + it('returns "false" for boolean data types', function () { + expect(getDefaultValue('xs:boolean')).toBeFalsy(); + }); + + it('returns "0" for number data types', function () { + expect(getDefaultValue('xs:byte')).toEqual(0); + expect(getDefaultValue('xs:decimal')).toEqual(0); + expect(getDefaultValue('xs:double')).toEqual(0); + expect(getDefaultValue('xs:float')).toEqual(0); + expect(getDefaultValue('xs:int')).toEqual(0); + expect(getDefaultValue('xs:integer')).toEqual(0); + expect(getDefaultValue('xs:short')).toEqual(0); + expect(getDefaultValue('xs:unsignedByte')).toEqual(0); + expect(getDefaultValue('xs:unsignedInt')).toEqual(0); + expect(getDefaultValue('xs:unsignedShort')).toEqual(0); + }); + + it('returns "0n" for bigint data types', function () { + expect(getDefaultValue('xs:long')).toEqual(0n); + expect(getDefaultValue('xs:unsignedLong')).toEqual(0n); + }); + + it(`returns "${new Date(0)}" for time date data types`, function () { + expect(getDefaultValue('xs:date')).toEqual(new Date(0).getTime()); + expect(getDefaultValue('xs:dateTime')).toEqual(new Date(0).getTime()); + expect(getDefaultValue('xs:time')).toEqual(new Date(0).getTime()); + }); + + it('returns "" for string data types', function () { + expect(getDefaultValue('xs:string')).toEqual(''); + }); + }); + + describe('isBooleanType', function () { + it('indicates that "xs:int" is not a boolean', function () { + expect(isBooleanType('xs:int')).toBeFalsy(); + }); + + it('indicates that "xs:boolean" is a boolean', function () { + expect(isBooleanType('xs:boolean')).toBeTruthy(); + }); + }); + + describe('parseNumber', function () { + it('parses invariant 1,234.567', function () { + expect(parseNumber('1,234.567')).toEqual(1234.567); + }); + + it('parses invariant 1234.567', function () { + expect(parseNumber('1234.567')).toEqual(1234.567); + }); + + it('parses "en" 1,234.567', function () { + expect(parseNumber('1,234.567', 'en')).toEqual(1234.567); + }); + + it('parses "de" 1.234,567', function () { + expect(parseNumber('1.234,567', 'de')).toEqual(1234.567); + }); + }); + + describe('parseDate', function () { + it('converts en-us date "02/27/2023"', function () { + expect(parseDate('02/27/2023', 'en-us')).toEqual(new Date(2023, 1, 27)); + }); + + it('converts en-us date and time "02/27/2023, 1:14 PM"', function () { + expect(parseDate('02/27/2023, 1:14 PM', 'en-us')).toEqual(new Date(2023, 1, 27, 13, 14)); + }); + + it('converts de-de date "27.02.2023"', function () { + expect(parseDate('27.02.2023', 'de-de')).toEqual(new Date(2023, 1, 27)); + }); + + it('converts de-de date and time "27.02.2023, 13:14"', function () { + expect(parseDate('27.02.2023, 13:14', 'de-de')).toEqual(new Date(2023, 1, 27, 13, 14)); + }); + + it('converts date "11/2020"', function () { + expect(parseDate('11/2020')).toEqual(new Date(2020, 10)); + }); + + it('converts date "new Date(2023, 1, 27, 13, 14, 15, 16)"', function () { + const date = new Date(2023, 1, 27, 13, 14, 15).toString(); + expect(parseDate(date)).toEqual(new Date(2023, 1, 27, 13, 14, 15)); + }); + }); + + describe('toLocale', function () { + it('converts 1234.56 to "de" 1.234,56', function () { + expect(toLocale('1234.56', 'xs:double', 'de')).toEqual('1.234,56'); + }); + + it('converts 1234.56 to "en" 1,234.56', function () { + expect(toLocale('1234.56', 'xs:double', 'en')).toEqual('1,234.56'); + }); + + it('converts double undefined to undefined', function () { + expect(toLocale(undefined, 'xs:double', 'en')).toBeUndefined; + }); + + it('converts double "invalid" to undefined', function () { + expect(toLocale(undefined, 'xs:double', 'en')).toBeUndefined; + }); + }); + + describe('toInvariant', function () { + it('converts "de" 1.234,56 to 1234.56', function () { + expect(toInvariant('1.234,56', 'xs:double', 'de')).toEqual('1234.56'); + }); + + it('converts "en" 1,234.56 to 1234.56', function () { + expect(toInvariant('1,234.56', 'xs:double', 'en')).toEqual('1234.56'); + }); + + it('converts double undefined to undefined', function () { + expect(toInvariant(undefined, 'xs:double', 'en')).toBeUndefined; + }); + + it('converts double "invalid" to undefined', function () { + expect(toInvariant(undefined, 'xs:double', 'en')).toBeUndefined; + }); + }); + + describe('toBoolean', function () { + it('converts undefined to false', function () { + expect(toBoolean(undefined)).toBeFalsy(); + }); + + it('converts null to false', function () { + expect(toBoolean(null)).toBeFalsy(); + }); + + it('converts 0 to false', function () { + expect(toBoolean(0)).toBeFalsy(); + }); + + it('converts 1 to true', function () { + expect(toBoolean(1)).toBeTruthy(); + }); + + it('converts "true" to true', function () { + expect(toBoolean('true')).toBeTruthy(); + }); + + it('converts "false" to false', function () { + expect(toBoolean('false')).toBeFalsy(); + }); + }); +}); \ No newline at end of file diff --git a/projects/common/src/test/document.spec.ts b/projects/common/src/test/document.spec.ts new file mode 100644 index 00000000..00a084cf --- /dev/null +++ b/projects/common/src/test/document.spec.ts @@ -0,0 +1,386 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { cloneDeep } from 'lodash-es'; +import { describe, it, expect } from '@jest/globals' +import { AASDocument } from '../lib/types.js'; +import * as doc from '../lib/document.js'; +import * as aas from '../lib/aas.js'; +import { testProperty, testSubmodel, testSubmodelElementCollection } from './assets/samples.js'; +import { aasEnvironment } from './assets/aas-environment.js'; + +describe('Document', function () { + describe('equalDocument', function () { + let a: AASDocument; + let b: AASDocument; + + beforeEach(function () { + a = { + id: 'http://customer.com/aas/a', + container: 'C:/Git/aasportal/common/test/assets/?type=AasxDirectory', + endpoint: { type: 'file', address: 'a.json' }, + idShort: 'A', + readonly: true, + timeStamp: 42 + }; + + b = { + id: 'http://customer.com/aas/b', + container: 'C:/Git/aasportal/common/test/assets/?type=AasxDirectory', + endpoint: { type: 'file', address: 'b.json' }, + idShort: 'B', + readonly: true, + timeStamp: 42 + }; + }); + + it('compares equal document', function () { + expect(doc.equalDocument(a, a)).toBeTruthy(); + }); + + it('compares same documents', function () { + const aa = cloneDeep(a); + expect(doc.equalDocument(a, aa)).toBeTruthy(); + }); + + it('compares different documents', function () { + expect(doc.equalDocument(a, b)).toBeFalsy(); + }); + }); + + describe('getChildren', function () { + it('returns the submodel elements of a Submodel', function () { + expect(doc.getChildren(testSubmodel).length).toEqual(testSubmodel.submodelElements!.length); + }); + + it('return the submodel elements of a SubmodelElementCollection', function () { + expect(doc.getChildren(testSubmodelElementCollection).length) + .toEqual(testSubmodelElementCollection.value!.length); + }); + + it('returns an empty array of a Property', function () { + expect(doc.getChildren(testProperty).length).toEqual(0); + }); + + it('returns the submodels of an AssetAdministrationShell', function () { + expect(doc.getChildren(aasEnvironment.assetAdministrationShells[0], aasEnvironment)) + .toEqual(aasEnvironment.submodels!); + }); + }); + + describe('resolveReference', function () { + let env: aas.Environment; + + beforeEach(async function () { + env = aasEnvironment; + }); + + it('resolves a reference ', function () { + const reference: aas.Reference = { + type: 'ModelReference', + keys: [{ + type: 'Submodel', + value: 'http://i40.customer.com/type/1/1/1A7B62B529F19152', + }, { + type: 'SubmodelElementCollection', + value: 'OperatingManual', + }, { + type: 'File', + value: 'DigitalFile_PDF', + } + ] + }; + + expect(doc.resolveReference(env, reference)).toBeDefined(); + }); + + it('returns undefined for an invalid reference', function () { + const reference: aas.Reference = { + type: 'ModelReference', + keys: [{ + type: 'Submodel', + value: 'http://i40.customer.com/type/1/1/1A7B62B529F19152' + }, { + type: 'SubmodelElementCollection', + value: 'OperatingManual' + }, { + type: 'File', + value: 'unknown' + } + ] + }; + + expect(doc.resolveReference(env, reference)).toBeUndefined(); + }); + }); + + describe('getIEC61360Content', function () { + let env: aas.Environment; + let property: aas.Property; + + beforeEach(async function () { + env = aasEnvironment; + property = doc.selectElement(env, 'Documentation', 'OperatingManual', 'DocumentClassificationSystem')!; + }); + + it('', function () { + expect(doc.getIEC61360Content(env, property)).toBeDefined(); + }); + }); + + describe('selectElement', function () { + let env: aas.Environment; + + beforeEach(async function () { + env = aasEnvironment; + }); + + it('selects a Submodel', function () { + expect(doc.selectElement(env, 'TechnicalData')).toBeDefined(); + }); + + it('selects a Property in a Submodel', function () { + expect(doc.selectElement(env, 'TechnicalData', 'MaxTorque')).toBeDefined(); + }); + + it('return undefined for an invalid path.', function () { + expect(doc.selectElement(env, 'TechnicalData', 'Unknown')).toBeUndefined(); + }); + + it('return undefined for an empty path.', function () { + expect(doc.selectElement(env)).toBeUndefined(); + }); + + it('selects "Documentation/OperatingManual/DocumentId"', function () { + expect(doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')).toBeDefined(); + }); + }); + + describe('getParent', function () { + let child: aas.Referable; + let parent: aas.Referable; + + beforeEach(function () { + parent = doc.selectElement(aasEnvironment, 'TechnicalData')!; + child = doc.selectElement(aasEnvironment, 'TechnicalData', 'MaxTorque')!; + }); + + it('gets the parent of a child', function () { + expect(doc.getParent(aasEnvironment, child)).toEqual(parent); + }); + + it('returns "undefined" for an identifiable', function () { + expect(doc.getParent(aasEnvironment, parent)).toBeUndefined(); + }); + }); + + describe('selectReferable', function () { + let env: aas.Environment; + + beforeEach(function () { + env = aasEnvironment; + }); + + it('selects an AAS', function () { + const reference: aas.Reference = { + type: 'ModelReference', + keys: [ + { + type: "AssetAdministrationShell", + value: "http://customer.com/aas/9175_7013_7091_9168" + } + ] + }; + + expect(doc.selectReferable(env, reference)).toEqual(env.assetAdministrationShells[0]); + }); + + it('selects the "Documentation" submodel', function () { + const reference: aas.Reference = { + type: 'ModelReference', + keys: [ + { + type: "Submodel", + value: "http://i40.customer.com/type/1/1/1A7B62B529F19152" + } + ] + }; + + const submodel: aas.Submodel = doc.selectElement(env, 'Documentation')!; + expect(doc.selectReferable(env, reference)).toEqual(submodel); + }); + + it('selects the "DocumentId" property', function () { + const property: aas.Property = doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')!; + const reference: aas.Reference = { + type: 'ModelReference', + keys: [ + { + type: "Submodel", + value: "http://i40.customer.com/type/1/1/1A7B62B529F19152" + }, + { + type: "SubmodelElementCollection", + value: "OperatingManual" + }, + { + type: "Property", + value: "DocumentId" + } + ] + }; + + expect(doc.selectReferable(env, reference)).toEqual(property); + }); + }); + + describe('getParent', function () { + let env: aas.Environment; + + beforeEach(function () { + env = aasEnvironment; + }); + + it('returns "OperatingManual" as parent of "DocumentId"', function () { + const collection: aas.SubmodelElementCollection = doc.selectElement(env, 'Documentation', 'OperatingManual')!; + const property: aas.Property = doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')!; + expect(doc.getParent(env, property)).toEqual(collection); + }); + + it('returns "undefined" while "Documentation" has no parent', function () { + const submodel: aas.Submodel = doc.selectElement(env, 'Documentation')!; + expect(doc.getParent(env, submodel)).toBeUndefined(); + }); + }); + + describe('isDescendent', function () { + let env: aas.Environment; + + beforeEach(function () { + env = aasEnvironment; + }); + + it('indicates that "DocumentId" is a descendant of "OperatingManual"', function () { + const collection: aas.SubmodelElementCollection = doc.selectElement(env, 'Documentation', 'OperatingManual')!; + const property: aas.Property = doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')!; + expect(doc.isDescendant(env, collection, property)).toBeTruthy(); + }); + + it('indicates that "DocumentId" is a descendant of "Documentation"', function () { + const submodel: aas.Submodel = doc.selectElement(env, 'Documentation')!; + const property: aas.Property = doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')!; + expect(doc.isDescendant(env, submodel, property)).toBeTruthy(); + }); + + it('indicates that "MaxTorque" is not a descendant of "Documentation"', function () { + const submodel: aas.Submodel = doc.selectElement(env, 'Documentation')!; + const property: aas.Property = doc.selectElement(env, 'TechnicalData', 'MaxTorque')!; + expect(doc.isDescendant(env, submodel, property)).toBeFalsy(); + }); + }); + + describe('normalize', function () { + let env: aas.Environment; + + beforeEach(function () { + env = aasEnvironment; + }); + + it('bla', function () { + const collection: aas.SubmodelElementCollection = doc.selectElement(env, 'Documentation', 'OperatingManual')!; + const property: aas.Property = doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')!; + expect(doc.normalize(env, [collection, property])).toEqual([collection]); + }); + }); + + describe('selectSubmodel', function () { + let env: aas.Environment; + + beforeEach(function () { + env = aasEnvironment; + }); + + it('return the submodel to which "DocumentId" belongs.', function () { + const property: aas.Property = doc.selectElement(env, 'Documentation', 'OperatingManual.DocumentId')!; + const submodel: aas.Submodel = doc.selectElement(env, 'Documentation')!; + expect(doc.selectSubmodel(env, property)).toEqual(submodel); + }); + }); + + describe('diff', function () { + let env: aas.Environment; + + beforeEach(function () { + env = aasEnvironment; + }); + + it('determines no diffs if source and target equal', function () { + const target = env; + expect(doc.diff(env, target)).toEqual([]); + }); + + it('determines no diffs if target is a shallow copy of source', function () { + const target = { ...env }; + expect(doc.diff(env, target)).toEqual([]); + }); + + it('determines no diffs if target is a deep clone of source', function () { + const target = { ...env }; + expect(doc.diff(env, target)).toEqual([]); + }); + + it('detects a new submodel in source', function () { + const target = { ...env, submodels: env.submodels!.slice(1) }; + expect(doc.diff(env, target)).toEqual([{ + type: 'inserted', + sourceIndex: 0, + sourceElement: env.submodels![0] + }]); + }); + + it('detects a deleted submodel in source', function () { + const target = cloneDeep(env); + const source = { ...env, submodels: env.submodels!.slice(1) }; + expect(doc.diff(source, target)).toEqual([{ + type: 'deleted', + destinationIndex: 0, + destinationElement: target.submodels![0] + }]); + }); + + it('detects a changed property value', function () { + const target = env; + const source = cloneDeep(env); + const property: aas.Property = doc.selectElement(source, 'TechnicalData', 'MaxTorque')!; + property.value = '42'; + expect(doc.diff(source, target)).toEqual([{ + type: 'changed', + destinationParent: doc.selectElement(target, 'TechnicalData'), + destinationElement: doc.selectElement(target, 'TechnicalData', 'MaxTorque'), + destinationIndex: 1, + sourceParent: doc.selectElement(source, 'TechnicalData'), + sourceElement: doc.selectElement(source, 'TechnicalData', 'MaxTorque'), + sourceIndex: 1 + }]); + }); + }); + + describe('getAbsolutePath', function () { + it('gets the absolute path of "MaxTorque"', function () { + const property: aas.Property = doc.selectElement(aasEnvironment, 'TechnicalData', 'MaxTorque')!; + expect(doc.getAbsolutePath(property)).toEqual(['http.//i40.customer.com/type/1/1/7A7104BDAB57E184', 'MaxTorque']); + }); + }); + + describe('getIdShortPath', function () { + it('gets the idShort path of "DocumentId"', function () { + const property: aas.Property = doc.selectElement(aasEnvironment, 'Documentation', 'OperatingManual.DocumentId')!; + expect(doc.getIdShortPath(property)).toEqual('OperatingManual.DocumentId'); + }); + }); +}); \ No newline at end of file diff --git a/projects/common/src/test/index.spec.ts b/projects/common/src/test/index.spec.ts new file mode 100644 index 00000000..808c1351 --- /dev/null +++ b/projects/common/src/test/index.spec.ts @@ -0,0 +1,269 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { describe, it, expect } from '@jest/globals' +import { createSpyObj } from './utils.js'; +import { + aas, + equalUrls, + isAssetAdministrationShell, + isBlob, + isMultiLanguageProperty, + isProperty, + isReferenceElement, + isSubmodel, + isSubmodelElement, + isUrlSafeBase64, + isValidEMail, + isValidPassword, + stringFormat +} from '../lib/index.js'; + +describe('index', function () { + describe('isSubmodelElement', function () { + it('indicates that "Submodel" is not a SubmodelElement', function () { + const submodel = createSpyObj({}, { modelType: 'Submodel' }); + expect(isSubmodelElement(submodel)).toBeFalsy(); + }); + + it('indicates that "Property" is a SubmodelElement', function () { + const property = createSpyObj({}, { modelType: 'Property' }); + expect(isSubmodelElement(property)).toBeTruthy(); + }); + + it('indicates that "ReferenceElement" is a SubmodelElement', function () { + const referenceElement = createSpyObj({}, { modelType: 'ReferenceElement' }); + expect(isSubmodelElement(referenceElement)).toBeTruthy(); + }); + + it('indicates that "null" is not a SubmodelElement', function () { + expect(isSubmodelElement(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a SubmodelElement', function () { + expect(isSubmodelElement(undefined)).toBeFalsy(); + }); + + it('indicates that "{}" is not a SubmodelElement', function () { + expect(isSubmodelElement({})).toBeFalsy(); + }); + + }); + + describe('isAssetAdministrationShell', function () { + it('identifies an AssetAdministrationShell', function () { + const shell = createSpyObj({}, { modelType: 'AssetAdministrationShell' }); + expect(isAssetAdministrationShell(shell)).toBeTruthy(); + }); + + it('indicates that "null" is not a AssetAdministrationShell', function () { + expect(isAssetAdministrationShell(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a AssetAdministrationShell', function () { + expect(isAssetAdministrationShell(undefined)).toBeFalsy(); + }); + }); + + describe('isProperty', function () { + it('identifies a Property', function () { + const property = createSpyObj({}, { modelType: 'Property' }); + expect(isProperty(property)).toBeTruthy(); + }); + + it('indicates that "null" is not a Property', function () { + expect(isProperty(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a Property', function () { + expect(isProperty(undefined)).toBeFalsy(); + }); + }); + + describe('isBlob', function () { + it('identifies a Blob', function () { + const property = createSpyObj({}, { modelType: 'Blob' }); + expect(isBlob(property)).toBeTruthy(); + }); + + it('indicates that "null" is not a Blob', function () { + expect(isBlob(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a Blob', function () { + expect(isBlob(undefined)).toBeFalsy(); + }); + }); + + describe('isReferenceElement', function () { + it('identifies a ReferenceElement', function () { + const referenceElement = createSpyObj({}, { modelType: 'ReferenceElement' }); + expect(isReferenceElement(referenceElement)).toBeTruthy(); + }); + + it('indicates that "null" is not a ReferenceElement', function () { + expect(isReferenceElement(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a ReferenceElement', function () { + expect(isReferenceElement(undefined)).toBeFalsy(); + }); + }); + + describe('isSubmodel', function () { + it('identifies a Submodel', function () { + const submodel = createSpyObj({}, { modelType: 'Submodel' }); + expect(isSubmodel(submodel)).toBeTruthy(); + }); + + it('indicates that "null" is not a Submodel', function () { + expect(isSubmodel(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a Submodel', function () { + expect(isSubmodel(undefined)).toBeFalsy(); + }); + }); + + describe('isMultiLanguageProperty', function () { + it('identifies a MultiLanguageProperty', function () { + const multiLanguageProperty = createSpyObj({}, { modelType: 'MultiLanguageProperty' }); + expect(isMultiLanguageProperty(multiLanguageProperty)).toBeTruthy(); + }); + + it('indicates that "null" is not a MultiLanguageProperty', function () { + expect(isMultiLanguageProperty(null)).toBeFalsy(); + }); + + it('indicates that "undefined" is not a MultiLanguageProperty', function () { + expect(isMultiLanguageProperty(undefined)).toBeFalsy(); + }); + }); + + describe('equalUrls', function () { + it('returns true for same URLs', function () { + expect(equalUrls('https://www.fraunhofer.de/', 'https://www.fraunhofer.de/')).toBeTruthy(); + }); + + it('returns true for equal URLs', function () { + const url = 'https://www.fraunhofer.de/'; + expect(equalUrls(url, url)).toBeTruthy(); + }); + + it('returns true for same URLs, one missing leading "/"', function () { + expect(equalUrls('https://www.fraunhofer.de', 'https://www.fraunhofer.de/')).toBeTruthy(); + }); + + it('returns true for same URLs, different character case', function () { + expect(equalUrls('https://www.fraunhofer.de/', 'https://WWW.Fraunhofer.DE/')).toBeTruthy(); + }); + + it('returns false for different URLs', function () { + expect(equalUrls('https://www.fraunhofer.de/', 'http://www.fraunhofer.de/')).toBeFalsy(); + }); + + it('returns false if one URL is empty.', function () { + expect(equalUrls('', 'http://www.fraunhofer.de/')).toBeFalsy(); + }); + + it('returns false if one URL is invalid.', function () { + expect(equalUrls('invalid', 'http://www.fraunhofer.de/')).toBeFalsy(); + }); + + it('returns true for same file system path', function () { + expect(equalUrls('C:\\Git\\aasportal\\data\\samples', 'C:\\Git\\aasportal\\data\\samples')).toBeTruthy(); + }); + + it('returns true for different file system path', function () { + expect(equalUrls('C:\\Git\\aasportal\\data\\samples', 'C:\\Git\\aasportal\\data\\other')).toBeFalsy(); + }); + }); + + describe("Is valid e-mail", function () { + it("recognize valid e-mail format", function () { + expect(isValidEMail("webaas@iosb-ina.fraunhofer.de")).toBeTruthy(); + }); + + it("recognize invalid e-mail format", function () { + expect(isValidEMail("invalid")).toBeFalsy(); + }); + }); + + describe("Is valid password", function () { + it("valid password", function () { + expect(isValidPassword("aZ0-+_$%!§?#*~.,;:")).toBeTruthy(); + }); + + it("at least 8 characters", function () { + expect(isValidPassword("1234567")).toBeFalsy(); + }); + + + it("more then 20 characters", function () { + expect(isValidPassword("123456789012345678901")).toBeFalsy(); + }); + + it("invalid characters", function () { + expect(isValidPassword("1234567\\/ ")).toBeFalsy(); + }); + }); + + + describe("stringFormat", function () { + it("returns a string with no format items", function () { + expect(stringFormat("Hello World!")).toEqual("Hello World!"); + }); + + it("string format item", function () { + expect(stringFormat("Hello {0}!", "World")).toEqual("Hello World!"); + }); + + it("two string format items", function () { + expect(stringFormat("{1} {0}!", "World", "Hello")).toEqual("Hello World!"); + }); + + it("twice string format item", function () { + expect(stringFormat("Hello {0}, {0}!", "World")).toEqual("Hello World, World!"); + }); + + it("number format item", function () { + expect(stringFormat("PI is {0}", Math.PI)).toEqual("PI is " + Math.PI.toString()); + }); + + it("boolean format item", function () { + expect(stringFormat("True is {0} and false is {1}.", true, false)) + .toEqual("True is true and false is false."); + }); + + it("formats item with toString method", function () { + expect(stringFormat('Hello {0}', { toString: () => 'World!' })).toEqual('Hello World!'); + }); + + it("undefined format item", function () { + expect(stringFormat("{0}", undefined)).toEqual(""); + }); + + it("null format item", function () { + expect(stringFormat("{0}", null)).toEqual(""); + }); + + it("invalid format item", function () { + expect(stringFormat("{1}", "Invalid")).toEqual(""); + }); + }); + + describe('isUrlSafeBase64', function () { + it('indicates that "https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237" is not url-safe-base64 encoded', function () { + expect(isUrlSafeBase64('https://iosb-ina.fraunhofer.de/ids/aas/5174_7001_0122_9237')).toBeFalsy(); + }); + + it('indicates that "aHR0cHM6Ly9pb3NiLWluYS5mcmF1bmhvZmVyLmRlL2lkcy9hYXMvNTE3NF83MDAxXzAxMjJfOTIzNw" is url-safe-base64 encoded', function () { + expect(isUrlSafeBase64('aHR0cHM6Ly9pb3NiLWluYS5mcmF1bmhvZmVyLmRlL2lkcy9hYXMvNTE3NF83MDAxXzAxMjJfOTIzNw')).toBeTruthy(); + }); + }); +}); \ No newline at end of file diff --git a/projects/common/src/test/keyed-list.spec.ts b/projects/common/src/test/keyed-list.spec.ts new file mode 100644 index 00000000..b79ea2a2 --- /dev/null +++ b/projects/common/src/test/keyed-list.spec.ts @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { describe, it, expect } from '@jest/globals' +import { KeyedList } from '../lib/keyed-list.js'; + +interface KeyValue { + key: string; + value: number; +} + +describe('KeyedList', function () { + let instance: KeyedList; + + beforeEach(function () { + instance = new KeyedList((value) => value.key, [ + { key: 'a', value: 1 }, { key: 'b', value: 2 }, { key: 'c', value: 3 } + ]); + }); + + it('should create an instance', function () { + expect(instance).toBeTruthy(); + }); + + it('gets the length', function () { + expect(instance.length).toEqual(3); + }); + + it('returns the values', function () { + expect([...instance.values()]).toEqual([ + { key: 'a', value: 1 }, { key: 'b', value: 2 }, { key: 'c', value: 3 } + ]) + }); + + it('returns the keys', function () { + expect([...instance.keys()].sort()).toEqual(['a', 'b', 'c']); + }); + + it('gets a value by key', function () { + expect(instance.get('b')).toEqual({ key: 'b', value: 2 }); + }); + + it('gets a value by index', function () { + expect(instance.getValue(2)).toEqual({ key: 'c', value: 3 }); + }); + + it('allows adding a new value', function () { + instance.set({ key: 'd', value: 4 }); + expect(instance.has('d')).toBeTruthy(); + }); + + it('allows replace an existing value', function () { + instance.set({ key: 'c', value: 42 }); + expect(instance.get('c')).toEqual({ key: 'c', value: 42 }); + expect(instance.length).toEqual(3); + }); + + it('indicates whether a key exist in the list', function () { + expect(instance.has('x')).toBeFalsy(); + }); + + it('allows deleting a value', function () { + expect(instance.delete('a')).toBeTruthy(); + }); + + it('indicates that deleting a non existing value fails', function () { + expect(instance.delete('y')).toBeFalsy(); + }); + + it('clears the list', function () { + instance.clear(); + expect(instance.length).toEqual(0); + }); +}); \ No newline at end of file diff --git a/projects/common/src/test/multi-key-map.spec.ts b/projects/common/src/test/multi-key-map.spec.ts new file mode 100644 index 00000000..15e4e3c5 --- /dev/null +++ b/projects/common/src/test/multi-key-map.spec.ts @@ -0,0 +1,94 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { describe, it, expect } from '@jest/globals' +import { MultiKeyMap } from '../lib/multi-key-map.js'; + +describe('MultiKeyMap', function () { + let map: MultiKeyMap; + + beforeEach(function () { + map = new MultiKeyMap(); + map.set(42, 'Hello World!'); + map.set(123, 'The quick brown fox jumps over the lazy dog.'); + }); + + it('should create', function () { + expect(map).toBeTruthy(); + }); + + it('allows adding a new key-value-pair', function () { + let size = map.size; + map.set(1, 'A'); + expect(map.hasValue(1)).toBeTruthy(); + expect(map.hasKey('A')).toBeTruthy(); + expect(map.size - size).toEqual(1); + }); + + it('gets a value by key', function () { + expect(map.getValue(42)).toEqual('Hello World!'); + }); + + it('gets a key by value', function () { + expect(map.getKey('Hello World!')).toEqual(42); + }); + + it('get the number of entries in the map', function () { + expect(map.size).toEqual(2); + }); + + it('deletes a value by key', function () { + let size = map.size; + expect(map.deleteValue(123)).toBeTruthy(); + expect(size - map.size).toEqual(1); + expect(map.hasValue(123)).toBeFalsy(); + expect(map.hasKey('The quick brown fox jumps over the lazy dog.')).toBeFalsy(); + }); + + it('deletes a value by key', function () { + let size = map.size; + expect(map.deleteValue(123)).toBeTruthy(); + expect(size - map.size).toEqual(1); + expect(map.hasValue(123)).toBeFalsy(); + expect(map.hasKey('The quick brown fox jumps over the lazy dog.')).toBeFalsy(); + }); + + it('clears a map', function () { + map.clear(); + expect(map.size).toEqual(0); + }); + + it('indicates whether a value exists for key', function () { + expect(map.hasValue(42)).toBeTruthy(); + expect(map.hasValue(-1)).toBeFalsy(); + }); + + it('indicates whether a key exists for value', function () { + expect(map.hasKey('Hello World!')).toBeTruthy(); + expect(map.hasKey('unknown')).toBeFalsy(); + }); + + it('overwrites an existing key-value-pair', function () { + map.set(42, 'B'); + expect(map.getValue(42)).toEqual('B'); + expect(map.getKey('B')).toEqual(42); + expect(map.getKey('Hello World!')).toBeUndefined(); + }); + + it('throw an error if a value already exists', function () { + expect(() => map.set(321, 'Hello World!')).toThrowError(); + }); + + it('returns all keys', function () { + expect([...map.keys()]).toEqual([42, 123]); + }); + + it('returns all values', function () { + expect([...map.values()]).toEqual(['Hello World!', 'The quick brown fox jumps over the lazy dog.']); + }); +}); \ No newline at end of file diff --git a/projects/common/src/test/utils.ts b/projects/common/src/test/utils.ts new file mode 100644 index 00000000..55aa401d --- /dev/null +++ b/projects/common/src/test/utils.ts @@ -0,0 +1,53 @@ +/****************************************************************************** + * + * Copyright (c) 2019-2023 Fraunhofer IOSB-INA Lemgo, + * eine rechtlich nicht selbstaendige Einrichtung der Fraunhofer-Gesellschaft + * zur Foerderung der angewandten Forschung e.V. + * + *****************************************************************************/ + +import { expect, jest } from '@jest/globals' + +type Func = (...args: any[]) => any; + +export type SpyObjMethodNames = T extends undefined + ? ReadonlyArray | { [methodName: string]: any } + : ReadonlyArray | { [P in keyof T]?: T[P] extends Func ? ReturnType : any }; + +export type SpyObjPropertyNames = T extends undefined + ? ReadonlyArray | { [propertyName: string]: any } + : ReadonlyArray | { [P in keyof T]?: T[P] }; + +export function createSpyObj(methodNames: SpyObjMethodNames, propertyNames?: SpyObjPropertyNames): jest.Mocked { + let obj: any = {}; + + if (Array.isArray(methodNames)) { + for (let i = 0; i < methodNames.length; i++) { + obj[methodNames[i] as string] = jest.fn(); + } + } else { + for (const methodName in methodNames) { + obj[methodName] = jest.fn(); + } + } + + if (propertyNames) { + if (Array.isArray(propertyNames)) { + for (const propertyName of propertyNames) { + obj[propertyName] = undefined; + } + } else { + for (const propertyName in propertyNames) { + obj[propertyName] = propertyNames[propertyName]; + } + } + } + + return obj as jest.Mocked; +} + +export type DoneFn = (...args: any[]) => void; + +export function fail(message?: string) { + expect(false).toBe(true); +} \ No newline at end of file diff --git a/projects/common/tsconfig.json b/projects/common/tsconfig.json new file mode 100644 index 00000000..5095a358 --- /dev/null +++ b/projects/common/tsconfig.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "compileOnSave": false, + "compilerOptions": { + "outDir": "./build", + "module": "ES2022", + "target": "ES2022", + "moduleResolution": "nodenext", + "strict": true, + "noImplicitAny": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "sourceMap": true, + "alwaysStrict": true, + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true, + "useUnknownInCatchVariables": false, + "downlevelIteration": true, + "removeComments": true, + "useDefineForClassFields": false, + "experimentalDecorators": true, + "lib": [ + "ES2022" + ] + } +} \ No newline at end of file diff --git a/projects/common/tsconfig.lib.json b/projects/common/tsconfig.lib.json new file mode 100644 index 00000000..2377680b --- /dev/null +++ b/projects/common/tsconfig.lib.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist/lib", + "declaration": true, + "declarationMap": true, + "declarationDir": "./dist/types" + }, + "include": [ + "./src/lib/**/*.ts" + ] +} \ No newline at end of file