diff --git a/.github/workflows/auto-pr-to-release.yml b/.github/workflows/auto-pr-to-release.yml new file mode 100644 index 000000000..cdc8eceee --- /dev/null +++ b/.github/workflows/auto-pr-to-release.yml @@ -0,0 +1,261 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# OpenCRVS is also distributed under the terms of the Civil Registration +# & Healthcare Disclaimer located at http://opencrvs.org/license. +# +# Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. + +name: Auto PR to Release Branch + +on: + pull_request: + types: [closed] + workflow_dispatch: + inputs: + pr_number: + description: 'PR number to process' + required: true + default: '' + dry_run: + description: 'Dry run' + required: false + default: false + type: boolean + +jobs: + resolve-releases: + if: ${{ github.event_name == 'pull_request' && github.event.pull_request.merged == true || github.event_name == 'workflow_dispatch' }} + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.resolve-applicable-versions.outputs.matrix }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Get PR details from workflow dispatch + if: ${{ github.event_name == 'workflow_dispatch' }} + id: get_pr_details_dispatch + run: | + PR_NUMBER=${{ github.event.inputs.pr_number }} + PR_DATA=$(curl -s -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/opencrvs/opencrvs-countryconfig/pulls/$PR_NUMBER) + echo "MILESTONE=$(printf '%s' $PR_DATA | jq -r '.milestone.title')" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + + - name: Get PR details from event + if: ${{ github.event_name == 'pull_request' }} + id: get_pr_details_event + run: | + echo "MILESTONE=${{ github.event.pull_request.milestone.title }}" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + + - name: Check for milestone and if release branch exists + continue-on-error: true + id: resolve-applicable-versions + run: | + if [ -z "${{ env.MILESTONE }}" ] || [ "${{ env.MILESTONE }}" = "null" ]; then + echo "No milestone set. Exiting." + exit 1 + fi + + filter_versions() { + local input_version=$1 + + # List remote branches, extract versions, and sort them semantically + versions=$(git ls-remote --heads origin 'release-*' | awk -F'release-' '{print $2}' | sort -V) + + # Filter out versions less than the input version + filtered_versions=$(echo "$versions" | awk -v input="$input_version" ' + function compare_versions(v1, v2) { + split(v1, a, /[.v]/); + split(v2, b, /[.v]/); + for (i = 2; i <= 4; i++) { + if (a[i] < b[i]) return -1; + if (a[i] > b[i]) return 1; + } + return 0; + } + { + if (compare_versions($0, input) >= 0) { + print $0 + } + }') + + # Keep only the highest patch version for each minor version + echo "$filtered_versions" | awk -F. ' + { + minor = $1 "." $2; + patches[minor] = $0; + } + END { + for (minor in patches) { + print patches[minor]; + } + }' | sort -V + } + + versions=$(filter_versions "${{ env.MILESTONE }}") + json_array=$(echo "$versions" | jq -R -s -c 'split("\n") | map(select(. != ""))') + echo "matrix=$json_array" >> $GITHUB_OUTPUT + + create-pr: + needs: resolve-releases + runs-on: ubuntu-22.04 + if: ${{ always() && needs.resolve-releases.result == 'success' }} + + strategy: + fail-fast: false + matrix: + version: ${{fromJson(needs.resolve-releases.outputs.matrix)}} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Get PR details from workflow dispatch + if: ${{ github.event_name == 'workflow_dispatch' }} + id: get_pr_details_dispatch + run: | + PR_NUMBER=${{ github.event.inputs.pr_number }} + PR_DATA=$(curl -s -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/opencrvs/opencrvs-countryconfig/pulls/$PR_NUMBER) + # printf escapes the newlines in the JSON, so we can use jq to parse output such as: + # "body": "![image](https://github.com/user-attachments/assets/8eee5bcf-7692-490f-a19f-576623e09961)\r\n", + echo "PR_ID=$(printf '%s' $PR_DATA | jq -r '.number')" >> $GITHUB_ENV + echo "PR_AUTHOR=$(printf '%s' $PR_DATA | jq -r '.user.login')" >> $GITHUB_ENV + echo "PR_MERGER=$(printf '%s' $PR_DATA | jq -r '.merged_by.login')" >> $GITHUB_ENV + echo "BASE_BRANCH=$(printf '%s' $PR_DATA | jq -r '.base.ref')" >> $GITHUB_ENV + echo "HEAD_BRANCH=$(printf '%s' $PR_DATA | jq -r '.head.ref')" >> $GITHUB_ENV + echo "PR_TITLE=$(printf '%s' $PR_DATA | jq -r '.title')" >> $GITHUB_ENV + echo "BASE_SHA=$(printf '%s' $PR_DATA | jq -r '.base.sha')" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + + - name: Get PR details from event + if: ${{ github.event_name == 'pull_request' }} + id: get_pr_details_event + run: | + PR_NUMBER=${{ github.event.pull_request.number }} + echo "PR_ID=${{ github.event.pull_request.number }}" >> $GITHUB_ENV + echo "PR_AUTHOR=${{ github.event.pull_request.user.login }}" >> $GITHUB_ENV + echo "BASE_BRANCH=${{ github.event.pull_request.base.ref }}" >> $GITHUB_ENV + echo "HEAD_BRANCH=${{ github.event.pull_request.head.ref }}" >> $GITHUB_ENV + echo "PR_TITLE=${{ github.event.pull_request.title }}" >> $GITHUB_ENV + + LATEST_COMMIT_SHA=$(gh pr view $PR_NUMBER --json commits --jq '.commits[-1].oid') + FIRST_COMMIT_SHA=$(gh pr view $PR_NUMBER --json commits --jq '.commits[0].oid') + echo "LATEST_COMMIT_SHA=${LATEST_COMMIT_SHA}" >> $GITHUB_ENV + echo "FIRST_COMMIT_SHA=${FIRST_COMMIT_SHA}" >> $GITHUB_ENV + + PR_DETAILS=$(gh pr view $PR_NUMBER --json mergedBy) + MERGED_BY_LOGIN=$(echo "$PR_DETAILS" | jq -r '.mergedBy.login') + echo "PR_MERGER=$MERGED_BY_LOGIN" >> $GITHUB_ENV + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + + - name: Create and push the new branch for the PR + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + run: | + SEMANTIC_PR_TITLE="${{ env.PR_TITLE }}" + RELEASE_BRANCH="release-${{ matrix.version }}" + MILESTONE="${{ matrix.version }}" + + # Check for semantic prefix + if [[ $SEMANTIC_PR_TITLE =~ ^(feat|fix|docs|style|refactor|perf|test|chore|build|ci|revert|wip|merge)\: ]]; then + SEMANTIC_PR_TITLE="${BASH_REMATCH[1]}(${MILESTONE}): ${SEMANTIC_PR_TITLE#*: }" + else + SEMANTIC_PR_TITLE="🍒 Merge changes from PR #${{ env.PR_ID }} to $RELEASE_BRANCH" + fi + + PR_BODY="Automated PR to merge changes from develop to $RELEASE_BRANCH" + + # Configure git + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git config advice.mergeConflict false + + # Fetch and checkout the release branch + git fetch --all --unshallow + git checkout $RELEASE_BRANCH + + # Create a new branch for the PR + NEW_BRANCH="auto-pr-$RELEASE_BRANCH-${{ env.PR_ID }}-$RANDOM" + git checkout -b $NEW_BRANCH + + echo "First commit: ${{ env.FIRST_COMMIT_SHA }}" + echo "Latest commit: ${{ env.LATEST_COMMIT_SHA }}" + # NOTE: git cherry-pick range needs ~ to include the FIRST_COMMIT_SHA (https://stackoverflow.com/questions/1994463/how-to-cherry-pick-a-range-of-commits-and-merge-them-into-another-branch) + COMMIT_RANGE="${{ env.FIRST_COMMIT_SHA }}~..${{ env.LATEST_COMMIT_SHA }}" + + if [ "${{ env.FIRST_COMMIT_SHA }}" == "${{ env.LATEST_COMMIT_SHA }}" ]; then + COMMIT_RANGE=${{ env.FIRST_COMMIT_SHA }} + fi + + echo "Commit range: $COMMIT_RANGE" + + # Attempt to cherry-pick the commits from the original PR + CHERRY_PICK_OUTPUT=$(git cherry-pick $COMMIT_RANGE 2>&1) || { + git cherry-pick --abort || true + # If cherry-pick fails, create a placeholder commit + echo "Cherry-pick failed. Creating placeholder commit." + + GIT_LOG_ONELINE_OUTPUT=$(git log --oneline --no-decorate $COMMIT_RANGE) + + git reset --hard + git commit --allow-empty -m "Placeholder commit for PR #${{ env.PR_ID }}" + + # Add manual cherry-pick commands to the PR body + PR_BODY="${PR_BODY} + + **I failed to cherry-pick the changes automatically because of the following:** + + \`\`\` + $CHERRY_PICK_OUTPUT + \`\`\` + + **To continue manually you can use these commands:** + \`\`\` + git fetch origin $NEW_BRANCH:$NEW_BRANCH + git fetch origin ${{ env.HEAD_BRANCH }}:${{ env.HEAD_BRANCH }} + + git checkout $NEW_BRANCH + git reset --hard HEAD~1 # Remove placeholder commit + git cherry-pick $COMMIT_RANGE + \`\`\` + + + **Individual commits:** + \`\`\` + $GIT_LOG_ONELINE_OUTPUT + \`\`\` + " + } + + if [ "${{ github.event.inputs.dry_run }}" == "true" ]; then + echo "This is a dry run." + echo "Would have pushed the new branch $NEW_BRANCH" + echo "PR title: $SEMANTIC_PR_TITLE" + echo "PR body:" + echo "$PR_BODY" + exit 0 + fi + + # Push the new branch + git push origin $NEW_BRANCH + + # Create a pull request and assign the original PR author as the reviewer + AUTHOR=${{ env.PR_AUTHOR }} + + if [[ $AUTHOR == *renovate* ]]; then + if [ -z "${{ env.PR_MERGER }}" ]; then + AUTHOR="" + else + AUTHOR=${{ env.PR_MERGER }} + fi + fi + gh pr create --title "$SEMANTIC_PR_TITLE" --body "$PR_BODY" --head "$NEW_BRANCH" --base "$RELEASE_BRANCH" --assignee "$AUTHOR" --reviewer "$AUTHOR" diff --git a/.github/workflows/clear-environment.yml b/.github/workflows/clear-environment.yml index 25f360477..fea82bf7a 100644 --- a/.github/workflows/clear-environment.yml +++ b/.github/workflows/clear-environment.yml @@ -22,6 +22,8 @@ jobs: name: 'Reset data' environment: ${{ github.event.inputs.environment }} runs-on: ubuntu-22.04 + outputs: + outcome: ${{ steps.reset-data.outcome }} timeout-minutes: 60 steps: - name: Clone country config resource package @@ -45,6 +47,7 @@ jobs: known_hosts: ${{ env.KNOWN_HOSTS }} - name: Reset data + id: reset-data env: HOST: ${{ vars.DOMAIN }} ENV: ${{ vars.ENVIRONMENT_TYPE }} diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 93288c6e1..30f89c55d 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -14,7 +14,7 @@ on: core-image-tag: description: Core DockerHub image tag required: true - default: 'v1.5.0' + default: 'v1.6.0' countryconfig-image-tag: description: Your Country Config DockerHub image tag required: true diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4c3d837ec..6e6998379 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,7 +15,7 @@ on: core-image-tag: description: Core DockerHub image tag required: true - default: 'v1.5.0' + default: 'v1.6.0' countryconfig-image-tag: description: Your Country Config DockerHub image tag required: true diff --git a/.github/workflows/get-secret-from-environment.yml b/.github/workflows/get-secret-from-environment.yml index 79fe4c73a..d495fe5b1 100644 --- a/.github/workflows/get-secret-from-environment.yml +++ b/.github/workflows/get-secret-from-environment.yml @@ -43,6 +43,17 @@ jobs: exit 1 fi + - name: Verify GitHub token validity + id: verify-token + run: | + RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: Bearer ${{ secrets.gh_token }}" \ + "https://api.github.com/user") + if [ "$RESPONSE" -ne 200 ]; then + echo "Invalid or expired GitHub token." + exit 1 + fi + echo "GitHub token is valid." + - name: Check if environment exists id: check-env run: | diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml index 3ffcabf0c..d03dd8251 100644 --- a/.github/workflows/publish-release.yml +++ b/.github/workflows/publish-release.yml @@ -7,8 +7,9 @@ on: description: Branch to build from default: master required: true + release_version: - description: Release tag. It will be prepended by your repository name + description: Release tag. It will be prepended by your repository name (e.g. v1.5.3 or 20240501) required: true jobs: @@ -22,12 +23,8 @@ jobs: - name: Install jq run: sudo apt-get install jq -y - - name: Read version from package.json - id: get_version - run: echo "::set-output name=version::$(jq -r '.version' package.json)" - - name: Set TAG environment variable - run: echo "TAG=v${{ steps.get_version.outputs.version }}" >> $GITHUB_ENV + run: echo "TAG=${{ github.event.inputs.release_version }}" >> $GITHUB_ENV - uses: trstringer/manual-approval@v1 with: @@ -45,6 +42,7 @@ jobs: github_token: ${{ secrets.GITHUB_TOKEN }} tag_prefix: ${{ github.event.repository.name }}- custom_tag: ${{ env.TAG }} + release_branches: ${{ github.event.inputs.branch_name }} - name: Login to DockerHub uses: docker/login-action@v3 @@ -74,6 +72,7 @@ jobs: type: now from_branch: ${{ github.event.inputs.branch_name }} target_branch: master + message: Merge ${{ github.event.inputs.branch_name }} to master github_token: ${{ secrets.GITHUB_TOKEN }} - name: Merge master -> develop @@ -82,4 +81,5 @@ jobs: type: now from_branch: master target_branch: develop + message: Merge master back to develop github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..123b05279 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +18.20.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index d42b71364..fca42f0c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,90 @@ ## 1.6.0 (TBD) +### Breaking changes + +- **Notification Flags** The configuration of various notifications is now controlled from `countryconfig` instead of being handled in the UI, as notification settings are not something that should be changed on the fly. To simplify this process, we have moved the settings to the `application-config.ts` file. From now on, the notifications can be managed in the `notificationForRecord` object defined in the mentioned file. Any changes will take effect after a new deployment. + + **_Country implementors must define the `notificationForRecord` object in the `application-config.ts` file to enable the notifications they want. Not doing so will keep notifications disabled by default._** + +- **Gateways searchEvents API updated** `operationHistories` only returns `operationType` & `operatedOn` due to the other fields being unused in OpenCRVS +- **Config changes to review/preview and signatures** Core used to provide review/preview section by default which are now removed and need to be provided from countryconfig. The signature field definitions (e.g. informant signature, bride signature etc.) were hard coded in core which also have now been removed. The signatures can now be added through the review/preview sections defined in countryconfig just like any other field. You can use the following section definition as the default which is without any additional fields. We highly recommend checking out our reference country repository which has the signature fields in it's review/preview sections + +``` +{ + id: 'preview', + viewType: 'preview', + name: { + defaultMessage: 'Preview', + description: 'Form section name for Preview', + id: 'register.form.section.preview.name' + }, + title: { + defaultMessage: 'Preview', + description: 'Form section title for Preview', + id: 'register.form.section.preview.title' + }, + groups: [ + { + id: 'preview-view-group', + fields: [] + } + ] +} +``` + - Remove `splitView` option from DOCUMENT_UPLOADER_WITH_OPTION field - New required sections preview & review added. Signature field definitions are now part of these two sections same as normal form fields. +- Remove `inputFieldWidth` from Number type form field +- You can now configure the home screen application’s name and icons in your country configuration package as manifest.json and app icon files are moved from core to country config (check `src/client-static` folder) +- Updated `allowedFileFormats` in signature fields to use MIME types (`image/png`, `image/jpg`, `image/jpeg`, `image/svg`) instead of simple file extensions. If you are already using the `allowedFileFormats` field in your implementation, please ensure to update the format accordingly. +- Remove unnecessary UI dividers that add in various sections of the declaration forms(e.g the Death, Birth and Marriage forms) [#244](https://github.com/opencrvs/opencrvs-countryconfig/pull/244) + +### Bug fixes + +- Protect individual certificate endpoint with token +- Kibana disk space alerts now work regardless of your disk device names. Alerts listen devices mounted both to `/` and `/data` (encrypted data partition) +- "Publish release" pipeline now correctly uses the "Branch to build from" value as the branch to be tagged. Previously it tried tagging "master". "Release tag" is also now used as the release version as is instead of it being read from `package.json`. +- Environment creator script now requires countries to provide a Github token with no expiry date. This is to reduce effort in keeping the token up to date. +- Added the missing outputs for the clear environment workflow which was causing the seed data workflow to not run even if the reset option was checked when deploying + +### New features + +- The select options in DOCUMENT_UPLOADER_WITH_OPTION field can now be hidden using the new `optionCondition` property. It works similarly to the same property available in SELECT_WITH_OPTIONS field + +* **ElasticSearch reindexing** Allows reindexing ElasticSearch via a new search-service endpoint `reindex`. We're replacing the original `ocrvs` index with timestamped ones. This is done automatically when upgrading and migrating, but this is an important architectural change that should be noted. More details in [#7033](https://github.com/opencrvs/opencrvs-core/pull/7033). + +- Introduce a new certificate handlebar "preview" which can be used to conditionally render some svg element when previewing the certificate e.g. background image similar to security paper + +- **Notification flags**: Added notification flags for `BIRTH`, `DEATH`, and `MARRIAGE` events, including: -## 1.5.0 + - `sent-notification` + - `sent-notification-for-review` + - `sent-for-approval` + - `registered` + - `sent-for-updates` + +- **`/record-notification` API**: Endpoint to check enabled notifications for records. The API returns the `notificationForRecord` object for `BIRTH` and `DEATH` events, listing their respective flags. Route configuration includes description and tags for API documentation. + +### New content keys requiring translation + +``` +INSERT CSV ROWS IN ENGLISH ONLY +``` + +## Bug fixes + +- Github pipeline dedicated for reading secrets and variables from other environments now checks if GH_TOKEN is still valid before attempting other operations +- Remove unnecessary UI dividers that add in various sections of the declaration forms(e.g the Death, Birth and Marriage forms) [#244](https://github.com/opencrvs/opencrvs-countryconfig/pull/244) +- Update template transformer for fields `informantType` and `otherInformantType` that fixes the bug of unavailability of these template fields [#5952](https://github.com/opencrvs/opencrvs-countryconfig/pull/5952) + +## 1.5.2 (https://github.com/opencrvs/opencrvs-countryconfig/compare/v1.5.1...v1.5.2) + +## Bug fixes + +- Broken email alerts from low disk space are now fixed [293](https://github.com/opencrvs/opencrvs-countryconfig/pull/293) + +## 1.5.0 (https://github.com/opencrvs/opencrvs-countryconfig/compare/v1.4.1...v1.5.0) ### Breaking changes @@ -17,7 +97,13 @@ See https://github.com/opencrvs/opencrvs-farajaland/pull/1005 for details -- #### Infrastructure +### Infrastructure + +- Allow using staging to both period restore of production backup and also for backing up its own data to a different location using `backup_server_remote_target_directory` and `backup_server_remote_source_directory` ansible variables. This use case is mostly meant for OpenCRVS team internal use. + +- Automate SSH key exchange between application and backup server. For staging servers, automatically fetch production backup encryption key if periodic restore is enabled + +- Improved support for non-22 SSH port - Treat backup host identically to other hosts. To migrate: @@ -53,29 +139,6 @@ - Remove `splitView` option from DOCUMENT_UPLOADER_WITH_OPTION field [#114](https://github.com/opencrvs/opencrvs-countryconfig/pull/114) - Enable authentication for certificates endpoint [#188](https://github.com/opencrvs/opencrvs-countryconfig/pull/188) -- #### Infrastructure - -- Allow using staging to both period restore of production backup and also for backing up its own data to a different location using `backup_server_remote_target_directory` and `backup_server_remote_source_directory` ansible variables. This use case is mostly meant for OpenCRVS team internal use. - -- Automate SSH key exchange between application and backup server. For staging servers, automatically fetch production backup encryption key if periodic restore is enabled - -- Improved support for non-22 SSH port -- Added french translation of informant for print certificate flow, issue certificate flow & correction flow -- In the certificate, the 'Place of Certification' now accurately reflects the correct location. - -**Infrastructure** - -- Treat backup host identically to other hosts. To migrate: - - 1. Move all inventory files (qa.yml, production.yml...) from `infrastructure/server-setup` to `infrastructure/server-setup/inventory` - 2. Run environment creator for your backup server `yarn environment:init --environment=backup` - -- Allow using staging to both period restore of production backup and also for backing up its own data to a different location using `backup_server_remote_target_directory` and `backup_server_remote_source_directory` ansible variables. This use case is mostly meant for OpenCRVS team internal use. - -- Automate SSH key exchange between application and backup server. For staging servers, automatically fetch production backup encryption key if periodic restore is enabled - -- Improved support for non-22 SSH port - ## [1.4.1](https://github.com/opencrvs/opencrvs-countryconfig/compare/v1.4.0...v1.4.1) - Improved logging for emails being sent diff --git a/docker-compose.yml b/docker-compose.yml index 3274fbcca..f7025fcab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,10 +6,7 @@ # & Healthcare Disclaimer located at http://opencrvs.org/license. # # Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. -version: "3.3" - services: - countryconfig: image: ${DOCKERHUB_ACCOUNT}/${DOCKERHUB_REPO}:${COUNTRY_CONFIG_VERSION} build: . diff --git a/infrastructure/deployment/deploy.sh b/infrastructure/deployment/deploy.sh index 707755df2..ba3eda77d 100755 --- a/infrastructure/deployment/deploy.sh +++ b/infrastructure/deployment/deploy.sh @@ -224,6 +224,8 @@ get_docker_tags_from_compose_files() { IMAGE_TAG_LIST=$(cat $SPACE_SEPARATED_COMPOSE_FILE_LIST \ `# Select rows with the image tag` \ | grep image: \ + `# Ignore the baseimage file as its not used directly` \ + | grep -v ocrvs-base \ `# Only keep the image version` \ | sed "s/image://") @@ -384,6 +386,15 @@ echo echo "Waiting 2 mins for mongo to deploy before working with data. Please note it can take up to 10 minutes for the entire stack to deploy in some scenarios." echo +echo 'Setting up elastalert indices' + +while true; do + if configured_ssh "/opt/opencrvs/infrastructure/elasticsearch/setup-elastalert-indices.sh"; then + break + fi + sleep 5 +done + echo "Setting up Kibana config & alerts" while true; do diff --git a/infrastructure/docker-compose.deploy.yml b/infrastructure/docker-compose.deploy.yml index 4cc3a39bd..3af57d9e6 100644 --- a/infrastructure/docker-compose.deploy.yml +++ b/infrastructure/docker-compose.deploy.yml @@ -6,8 +6,6 @@ # & Healthcare Disclaimer located at http://opencrvs.org/license. # # Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. -version: '3.3' - services: # Configure reverse proxy for public endpoints # Note: these published port will override UFW rules as Docker manages it's own iptables @@ -62,7 +60,7 @@ services: - overlay_net filebeat: - image: docker.elastic.co/beats/filebeat:7.17.0 + image: docker.elastic.co/beats/filebeat:8.14.3 user: root networks: - overlay_net @@ -87,7 +85,7 @@ services: - 'traefik.enable=false' metricbeat: - image: docker.elastic.co/beats/metricbeat:7.17.13 + image: docker.elastic.co/beats/metricbeat:8.14.3 user: root cap_add: - SYS_PTRACE @@ -130,7 +128,7 @@ services: [ 'curl', '-u', - 'elastic:${ELASTICSEARCH_SUPERUSER_PASSWORD}', + 'kibana_system:${KIBANA_SYSTEM_PASSWORD}', '-X', 'POST', 'http://kibana:5601/api/saved_objects/_import?overwrite=true', @@ -158,7 +156,7 @@ services: gelf-address: 'udp://127.0.0.1:12201' tag: 'setup-kibana-config' kibana: - image: docker.elastic.co/kibana/kibana:7.17.0 + image: docker.elastic.co/kibana/kibana:8.14.3 restart: always deploy: labels: @@ -175,8 +173,8 @@ services: networks: - overlay_net environment: - - ELASTICSEARCH_USERNAME=elastic - - ELASTICSEARCH_PASSWORD=${ELASTICSEARCH_SUPERUSER_PASSWORD} + - ELASTICSEARCH_USERNAME=kibana_system + - ELASTICSEARCH_PASSWORD=${KIBANA_SYSTEM_PASSWORD} configs: - source: kibana.{{ts}} target: /usr/share/kibana/config/kibana.yml @@ -284,7 +282,6 @@ services: - path.repo=/data/backups/elasticsearch - cluster.name=docker-cluster - network.host=0.0.0.0 - - discovery.zen.minimum_master_nodes=1 - discovery.type=single-node - xpack.security.enabled=true - xpack.security.authc.api_key.enabled=true @@ -367,6 +364,7 @@ services: - APM_ELASTIC_PASSWORD=${ROTATING_APM_ELASTIC_PASSWORD} - SEARCH_ELASTIC_USERNAME=search-user - SEARCH_ELASTIC_PASSWORD=${ROTATING_SEARCH_ELASTIC_PASSWORD} + - KIBANA_SYSTEM_PASSWORD=${KIBANA_SYSTEM_PASSWORD} - KIBANA_USERNAME=${KIBANA_USERNAME} - KIBANA_PASSWORD=${KIBANA_PASSWORD} volumes: @@ -386,7 +384,7 @@ services: gelf-address: 'udp://127.0.0.1:12201' tag: 'setup-elasticsearch-users' elastalert: - image: jertel/elastalert2:2.3.0 + image: jertel/elastalert2:2.19.0 restart: unless-stopped environment: - ES_USERNAME=elastic @@ -410,7 +408,7 @@ services: tag: 'elastalert' logstash: - image: logstash:7.17.0 + image: logstash:8.14.3 command: logstash -f /etc/logstash/logstash.conf --verbose ports: - '12201:12201' @@ -433,7 +431,7 @@ services: - 'traefik.enable=false' replicas: 1 apm-server: - image: docker.elastic.co/apm/apm-server:7.15.2 + image: docker.elastic.co/apm/apm-server:7.17.22 cap_add: ['CHOWN', 'DAC_OVERRIDE', 'SETGID', 'SETUID'] cap_drop: ['ALL'] restart: always @@ -589,6 +587,9 @@ services: - APN_SERVICE_URL=http://apm-server:8200 - COUNTRY_CONFIG_URL=https://countryconfig.{{hostname}} - LOGIN_URL=https://login.{{hostname}} + # This needs to be the internal swarm url + # as containers cannot connect to the web + - GATEWAY_URL=http://gateway:7070 - CLIENT_APP_URL=https://register.{{hostname}} - NOTIFICATION_TRANSPORT=${NOTIFICATION_TRANSPORT} - ALERT_EMAIL=${ALERT_EMAIL:-} diff --git a/infrastructure/docker-compose.development-deploy.yml b/infrastructure/docker-compose.development-deploy.yml index b60f37cab..170a229b0 100644 --- a/infrastructure/docker-compose.development-deploy.yml +++ b/infrastructure/docker-compose.development-deploy.yml @@ -1,5 +1,3 @@ -version: '3.3' - services: notification: environment: diff --git a/infrastructure/docker-compose.production-deploy.yml b/infrastructure/docker-compose.production-deploy.yml index b568d488b..dbeae2105 100644 --- a/infrastructure/docker-compose.production-deploy.yml +++ b/infrastructure/docker-compose.production-deploy.yml @@ -1,5 +1,3 @@ -version: '3.3' - # # Production deployments of OpenCRVS should never be exposed to the internet. # Instead, they should be deployed on a private network and exposed to the internet via a VPN. diff --git a/infrastructure/docker-compose.qa-deploy.yml b/infrastructure/docker-compose.qa-deploy.yml index f01395d40..63c6f5518 100644 --- a/infrastructure/docker-compose.qa-deploy.yml +++ b/infrastructure/docker-compose.qa-deploy.yml @@ -1,5 +1,3 @@ -version: '3.3' - services: traefik: networks: diff --git a/infrastructure/docker-compose.staging-deploy.yml b/infrastructure/docker-compose.staging-deploy.yml index 3b7a25cc0..54b6395b7 100644 --- a/infrastructure/docker-compose.staging-deploy.yml +++ b/infrastructure/docker-compose.staging-deploy.yml @@ -1,5 +1,3 @@ -version: '3.3' - # # Production deployments of OpenCRVS should never be exposed to the internet. # Instead, they should be deployed on a private network and exposed to the internet via a VPN. diff --git a/infrastructure/elasticsearch/roles/search_user.json b/infrastructure/elasticsearch/roles/search_user.json index b7be198b5..da60cdeb8 100644 --- a/infrastructure/elasticsearch/roles/search_user.json +++ b/infrastructure/elasticsearch/roles/search_user.json @@ -1,8 +1,17 @@ { + "cluster": ["manage"], "indices": [ { - "names": ["ocrvs"], - "privileges": ["write", "create", "create_index", "delete", "delete_index", "read"] + "names": ["ocrvs", "ocrvs-*"], + "privileges": [ + "write", + "create", + "create_index", + "delete", + "delete_index", + "read", + "manage" + ] } ] } diff --git a/infrastructure/elasticsearch/setup-elastalert-indices.sh b/infrastructure/elasticsearch/setup-elastalert-indices.sh new file mode 100755 index 000000000..d36fd8d10 --- /dev/null +++ b/infrastructure/elasticsearch/setup-elastalert-indices.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# +# OpenCRVS is also distributed under the terms of the Civil Registration +# & Healthcare Disclaimer located at http://opencrvs.org/license. +# +# Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. + +# Upgrading from 7 to 8 requires deleting elastalert indices. https://elastalert2.readthedocs.io/en/latest/recipes/faq.html#does-elastalert-2-support-elasticsearch-8 + +set -e + +docker_command="docker run --rm --network=opencrvs_overlay_net curlimages/curl" + +echo 'Waiting for availability of Elasticsearch' +ping_status_code=$($docker_command --connect-timeout 60 -u elastic:$ELASTICSEARCH_SUPERUSER_PASSWORD -o /dev/null -w '%{http_code}' "http://elasticsearch:9200") + +if [ "$ping_status_code" -ne 200 ]; then + echo "Elasticsearch is not ready. API returned status code: $ping_status_code" + exit 1 +fi + + + +echo 'Scaling down Elastalert' + +docker service scale opencrvs_elastalert=0 + +echo 'Deleting Elastalert indices' +indices='elastalert_status,elastalert_status_error,elastalert_status_past,elastalert_status_silence,elastalert_status_status' + +delete_status_code=$($docker_command --connect-timeout 60 -u elastic:$ELASTICSEARCH_SUPERUSER_PASSWORD -o /dev/null -w '%{http_code}' "http://elasticsearch:9200/${indices}?ignore_unavailable=true" -X DELETE) + +if [ "$delete_status_code" -ne 200 ]; then + echo "Could not delete indices. API returned status code: $delete_status_code" + exit 1 +fi + +echo 'Scaling up Elastalert' +docker service scale opencrvs_elastalert=1 + diff --git a/infrastructure/elasticsearch/setup-helpers.sh b/infrastructure/elasticsearch/setup-helpers.sh index c6a25e874..1b3380f0f 100755 --- a/infrastructure/elasticsearch/setup-helpers.sh +++ b/infrastructure/elasticsearch/setup-helpers.sh @@ -230,36 +230,3 @@ function ensure_settings { return $result } - - -function create_elastic_index { - local index_name=$1 - local elasticsearch_host="${ELASTICSEARCH_HOST:-elasticsearch}" - - local -a args=( '-s' '-D-' '-m15' '-w' '%{http_code}' - "http://${elasticsearch_host}:9200/${index_name}" - '-X' 'PUT' - '-H' 'Content-Type: application/json' - ) - - if [[ -n "${ELASTIC_PASSWORD:-}" ]]; then - args+=( '-u' "elastic:${ELASTIC_PASSWORD}" ) - fi - - local -i result=1 - local output - - output="$(curl "${args[@]}")" - - echo "${output}" - - if [[ "${output: -3}" -eq 200 || $output == *"resource_already_exists"* ]]; then - result=0 - fi - - if ((result)); then - echo -e "\n${output::-3}\n" - fi - - return $result -} diff --git a/infrastructure/elasticsearch/setup-settings.sh b/infrastructure/elasticsearch/setup-settings.sh index eea61f90a..260e13a31 100644 --- a/infrastructure/elasticsearch/setup-settings.sh +++ b/infrastructure/elasticsearch/setup-settings.sh @@ -19,8 +19,5 @@ echo "-------- $(date) --------" log 'Waiting for availability of Elasticsearch' wait_for_elasticsearch -log "Creating index for Elasticsearch. Index: ocrvs" -create_elastic_index "ocrvs" - log "Updating replicas for Elasticsearch" ensure_settings "{\"index\":{\"number_of_replicas\":0}}" diff --git a/infrastructure/elasticsearch/setup-users.sh b/infrastructure/elasticsearch/setup-users.sh index 366090da1..30d2f5923 100755 --- a/infrastructure/elasticsearch/setup-users.sh +++ b/infrastructure/elasticsearch/setup-users.sh @@ -24,6 +24,7 @@ users_passwords=( [$SEARCH_ELASTIC_USERNAME]="${SEARCH_ELASTIC_PASSWORD:-}" [beats_system]="${METRICBEAT_ELASTIC_PASSWORD:-}" [apm_system]="${APM_ELASTIC_PASSWORD:-}" + [kibana_system]="${KIBANA_SYSTEM_PASSWORD:-}" [$KIBANA_USERNAME]="${KIBANA_PASSWORD:-}" ) diff --git a/infrastructure/environments/setup-environment.ts b/infrastructure/environments/setup-environment.ts index 83a0642bf..aa5d3dd41 100644 --- a/infrastructure/environments/setup-environment.ts +++ b/infrastructure/environments/setup-environment.ts @@ -653,6 +653,13 @@ const derivedVariables = [ type: 'disabled', scope: 'ENVIRONMENT' }, + { + name: 'KIBANA_SYSTEM_PASSWORD', + valueLabel: 'KIBANA_SYSTEM_PASSWORD', + valueType: 'SECRET', + type: 'disabled', + scope: 'ENVIRONMENT' + }, { name: 'MINIO_ROOT_USER', valueLabel: 'MINIO_ROOT_USER', @@ -1103,6 +1110,23 @@ const SPECIAL_NON_APPLICATION_ENVIRONMENTS = ['jump', 'backup'] ), scope: 'ENVIRONMENT' as const }, + { + name: 'KIBANA_SYSTEM_PASSWORD', + type: 'SECRET' as const, + didExist: findExistingValue( + 'KIBANA_SYSTEM_PASSWORD', + 'SECRET', + 'ENVIRONMENT', + existingValues + ), + value: findExistingOrDefine( + 'KIBANA_SYSTEM_PASSWORD', + 'SECRET', + 'ENVIRONMENT', + generateLongPassword() + ), + scope: 'ENVIRONMENT' as const + }, { name: 'MINIO_ROOT_USER', type: 'SECRET' as const, diff --git a/infrastructure/monitoring/beats/metricbeat.yml b/infrastructure/monitoring/beats/metricbeat.yml index cb4875457..78bd940a7 100644 --- a/infrastructure/monitoring/beats/metricbeat.yml +++ b/infrastructure/monitoring/beats/metricbeat.yml @@ -85,7 +85,7 @@ setup.kibana: password: ${KIBANA_PASSWORD} #============================== Xpack Monitoring =============================== -xpack.monitoring: +monitoring: enabled: true elasticsearch: username: ${BEATS_USERNAME} diff --git a/infrastructure/monitoring/elastalert/rules/alert.yaml b/infrastructure/monitoring/elastalert/rules/alert.yaml index d5bfbcb50..a7064c695 100644 --- a/infrastructure/monitoring/elastalert/rules/alert.yaml +++ b/infrastructure/monitoring/elastalert/rules/alert.yaml @@ -26,13 +26,13 @@ filter: should: - term: rule.name.keyword: - value: 'Available disk space in data partition' + value: 'Available disk space in root file system' - term: rule.name.keyword: value: 'CPU under heavy load' - term: rule.name.keyword: - value: 'Low on available disk space' + value: 'Low on available disk space in data partition' minimum_should_match: 1 alert: post2 diff --git a/infrastructure/monitoring/filebeat/filebeat.yml b/infrastructure/monitoring/filebeat/filebeat.yml index d2ac41bcb..8f75ec4b9 100644 --- a/infrastructure/monitoring/filebeat/filebeat.yml +++ b/infrastructure/monitoring/filebeat/filebeat.yml @@ -60,7 +60,7 @@ setup.kibana: password: ${ELASTICSEARCH_PASSWORD} #============================== Xpack Monitoring =============================== -xpack.monitoring: +monitoring: enabled: true elasticsearch: diff --git a/infrastructure/monitoring/kibana/config.ndjson b/infrastructure/monitoring/kibana/config.ndjson index a8f47219d..f79787241 100644 --- a/infrastructure/monitoring/kibana/config.ndjson +++ b/infrastructure/monitoring/kibana/config.ndjson @@ -1,10 +1,10 @@ -{"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"metrics.inventory_threshold.fired","params":{"documents":["{\"@timestamp\":\"2023-11-17T13:17:52.791Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"metrics.alert.inventory.threshold","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2023-11-17T12:01:46.420Z","createdBy":"elastic","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Available disk space in data partition","notifyWhen":"onActionGroupChange","params":{"criteria":[{"comparator":"<","customMetric":{"aggregation":"min","field":"system.filesystem.available","id":"alert-custom-metric","type":"custom"},"metric":"custom","threshold":[170000000000],"timeSize":1,"timeUnit":"h","warningComparator":"<","warningThreshold":[220000000000]}],"filterQuery":"{\"bool\":{\"should\":[{\"match_phrase\":{\"system.filesystem.device_name\":\"/dev/vda\"}}],\"minimum_should_match\":1}}","filterQueryText":"system.filesystem.device_name : \"/dev/vda\"","nodeType":"host","sourceId":"default"},"schedule":{"interval":"1h"},"scheduledTaskId":null,"tags":["infra","opencrvs-builtin"],"throttle":null,"updatedAt":"2024-02-07T02:27:29.567Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"14778650-8541-11ee-9002-2f37fdc4e5d5","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294424438,232754],"type":"alert","updated_at":"2024-02-07T08:27:04.438Z","version":"WzQ5NTQzMSwxOV0="} +{"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"metrics.inventory_threshold.fired","params":{"documents":["{\"@timestamp\":\"2024-08-06T07:57:35.644Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"metrics.alert.inventory.threshold","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2023-11-17T12:01:46.420Z","createdBy":"elastic","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-08-06T08:02:44.568Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.18"},"muteAll":false,"mutedInstanceIds":[],"name":"Available disk space in root file system","notifyWhen":"onActionGroupChange","params":{"alertOnNoData":true,"criteria":[{"comparator":">=","customMetric":{"aggregation":"max","field":"system.filesystem.used.pct","id":"alert-custom-metric","type":"custom"},"metric":"custom","threshold":[0.7],"timeSize":1,"timeUnit":"h","warningComparator":">=","warningThreshold":[0.5]}],"filterQuery":"{\"bool\":{\"should\":[{\"match_phrase\":{\"system.filesystem.mount_point\":\"/hostfs\"}}],\"minimum_should_match\":1}}","filterQueryText":"system.filesystem.mount_point : \"/hostfs\"","nodeType":"host","sourceId":"default"},"schedule":{"interval":"1h"},"scheduledTaskId":null,"tags":["infra","opencrvs-builtin"],"throttle":null,"updatedAt":"2024-08-06T08:01:56.542Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.18","id":"14778650-8541-11ee-9002-2f37fdc4e5d5","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1722931316554,643],"type":"alert","updated_at":"2024-08-06T08:01:56.554Z","version":"WzM5MywxXQ=="} {"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"threshold_met","params":{"documents":["{\"@timestamp\":\"2022-04-18T07:05:33.819Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"apm.error_rate","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2022-06-01T11:30:27.033Z","createdBy":"opencrvs-admin","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Error in service","notifyWhen":"onActionGroupChange","params":{"environment":"ENVIRONMENT_ALL","threshold":1,"windowSize":1,"windowUnit":"m"},"schedule":{"interval":"1m"},"scheduledTaskId":null,"tags":[],"throttle":null,"updatedAt":"2024-02-05T03:00:20.633Z","updatedBy":"opencrvs-admin"},"coreMigrationVersion":"7.17.0","id":"3b6722e0-e19e-11ec-ba8e-51649755648d","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707273006619,214975],"type":"alert","updated_at":"2024-02-07T02:30:06.619Z","version":"WzQ5MjAzNCwxOV0="} {"attributes":{"buildNum":46534,"defaultIndex":"metricbeat-*"},"coreMigrationVersion":"7.17.0","id":"7.17.0","migrationVersion":{"config":"7.13.0"},"references":[],"sort":[1707273006619,216009],"type":"config","updated_at":"2024-02-07T02:30:06.619Z","version":"WzQ5MjQyOCwxOV0="} {"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"logs.threshold.fired","params":{"documents":["{\"@timestamp\":\"2023-11-22T08:25:47.329Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"logs.alert.document.count","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2023-11-22T08:32:38.272Z","createdBy":"elastic","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Error in backup logs","notifyWhen":"onActionGroupChange","params":{"count":{"comparator":"more than or equals","value":1},"criteria":[{"comparator":"matches","field":"message","value":"error"},{"comparator":"equals","field":"log.file.path","value":"/var/log/opencrvs-backup.log"}],"timeSize":1,"timeUnit":"h"},"schedule":{"interval":"1h"},"scheduledTaskId":null,"tags":[],"throttle":null,"updatedAt":"2024-02-07T02:27:22.558Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"b166fcb0-8911-11ee-8111-2f3be9e93efc","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294436464,232766],"type":"alert","updated_at":"2024-02-07T08:27:16.464Z","version":"WzQ5NTQzNCwxOV0="} -{"attributes":{"anomalyThreshold":50,"description":"","fields":{"container":"container.id","host":"host.name","message":["message","@message"],"pod":"kubernetes.pod.uid","tiebreaker":"_doc","timestamp":"@timestamp"},"inventoryDefaultView":"0","logColumns":[{"timestampColumn":{"id":"5e7f964a-be8a-40d8-88d2-fbcfbdca0e2f"}},{"fieldColumn":{"field":"event.dataset","id":" eb9777a8-fcd3-420e-ba7d-172fff6da7a2"}},{"messageColumn":{"id":"b645d6da-824b-4723-9a2a-e8cece1645c0"}}],"logIndices":{"indexName":"logs-*,filebeat-*,kibana_sample_data_logs*,logstash*","type":"index_name"},"metricAlias":"metrics-*,metricbeat-*","metricsExplorerDefaultView":"0","name":"Default"},"coreMigrationVersion":"7.17.0","id":"default","migrationVersion":{"infrastructure-ui-source":"7.16.2"},"references":[],"sort":[1707273006619,217714],"type":"infrastructure-ui-source","updated_at":"2024-02-07T02:30:06.619Z","version":"WzQ5MzAyNywxOV0="} +{"attributes":{"anomalyThreshold":50,"description":"","fields":{"container":"container.id","host":"host.name","message":["message","@message"],"pod":"kubernetes.pod.uid","tiebreaker":"_doc","timestamp":"@timestamp"},"inventoryDefaultView":"0","logColumns":[{"timestampColumn":{"id":"5e7f964a-be8a-40d8-88d2-fbcfbdca0e2f"}},{"fieldColumn":{"field":"event.dataset","id":" eb9777a8-fcd3-420e-ba7d-172fff6da7a2"}},{"messageColumn":{"id":"b645d6da-824b-4723-9a2a-e8cece1645c0"}}],"logIndices":{"indexName":"logs-*,filebeat-*,kibana_sample_data_logs*,logstash*,ecs-logstash*","type":"index_name"},"metricAlias":"metrics-*,metricbeat-*","metricsExplorerDefaultView":"0","name":"Default"},"coreMigrationVersion":"7.17.0","id":"default","migrationVersion":{"infrastructure-ui-source":"7.16.2"},"references":[],"sort":[1707273006619,217714],"type":"infrastructure-ui-source","updated_at":"2024-02-07T02:30:06.619Z","version":"WzQ5MzAyNywxOV0="} {"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"query matched","params":{"documents":["{\"@timestamp\":\"2023-11-20T10:19:30.521Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":".es-query","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2023-11-20T09:12:19.237Z","createdBy":"elastic","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Successful SSH login","notifyWhen":"onActionGroupChange","params":{"esQuery":"{ \"query\": { \"bool\": { \"must\": [ \n { \"term\": { \"log.file.path\": \"/var/log/auth.log\" } },\n { \"term\": { \"event.outcome\": \"success\" }}\n ] } } }","index":["filebeat-*"],"size":100,"threshold":[1],"thresholdComparator":">=","timeField":"@timestamp","timeWindowSize":1,"timeWindowUnit":"m"},"schedule":{"interval":"1m"},"scheduledTaskId":null,"tags":[],"throttle":null,"updatedAt":"2024-02-07T02:27:19.537Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"e79aaa90-8784-11ee-b9ba-89bbe73df7ff","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294457367,232778],"type":"alert","updated_at":"2024-02-07T08:27:37.367Z","version":"WzQ5NTQ0MCwxOV0="} {"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"metrics.inventory_threshold.fired","params":{"documents":["{\"@timestamp\":\"2022-06-20T06:16:33.414Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"metrics.alert.inventory.threshold","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2022-05-31T10:10:47.084Z","createdBy":"opencrvs-admin","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"CPU under heavy load","notifyWhen":"onActionGroupChange","params":{"criteria":[{"comparator":">","customMetric":{"aggregation":"avg","field":"","id":"alert-custom-metric","type":"custom"},"metric":"cpu","threshold":[70],"timeSize":1,"timeUnit":"m"}],"nodeType":"host","sourceId":"default"},"schedule":{"interval":"1m"},"scheduledTaskId":null,"tags":["infra","opencrvs-builtin"],"throttle":null,"updatedAt":"2024-02-07T02:27:30.573Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"f022bee0-e0c9-11ec-99b8-dbfd54551fda","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294457362,232774],"type":"alert","updated_at":"2024-02-07T08:27:37.362Z","version":"WzQ5NTQzOCwxOV0="} -{"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"metrics.inventory_threshold.fired","params":{"documents":["{\"@timestamp\":\"2023-11-17T13:17:52.791Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"metrics.alert.inventory.threshold","apiKey":null,"apiKeyOwner":null,"consumer":"infrastructure","createdAt":"2022-05-31T10:10:47.080Z","createdBy":"opencrvs-admin","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Low on available disk space","notifyWhen":"onActionGroupChange","params":{"alertOnNoData":true,"criteria":[{"comparator":">","customMetric":{"aggregation":"max","field":"system.filesystem.used.pct","id":"alert-custom-metric","label":"","type":"custom"},"metric":"custom","threshold":[0.7],"timeSize":1,"timeUnit":"h","warningComparator":">","warningThreshold":[0.5]}],"filterQuery":"{\"bool\":{\"should\":[{\"match_phrase\":{\"system.filesystem.device_name\":\"/dev/mapper/cryptfs\"}}],\"minimum_should_match\":1}}","filterQueryText":"system.filesystem.device_name : \"/dev/mapper/cryptfs\"","nodeType":"host","sourceId":"default"},"schedule":{"interval":"1h"},"scheduledTaskId":null,"tags":["infra","opencrvs-builtin"],"throttle":null,"updatedAt":"2024-02-07T02:27:20.542Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"f023d050-e0c9-11ec-99b8-dbfd54551fda","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294448366,232768],"type":"alert","updated_at":"2024-02-07T08:27:28.366Z","version":"WzQ5NTQzNSwxOV0="} +{"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"metrics.inventory_threshold.fired","params":{"documents":["{\"@timestamp\":\"2023-11-17T13:17:52.791Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"]}}],"alertTypeId":"metrics.alert.inventory.threshold","apiKey":null,"apiKeyOwner":null,"consumer":"infrastructure","createdAt":"2022-05-31T10:10:47.080Z","createdBy":"opencrvs-admin","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Low on available disk space in data partition","notifyWhen":"onActionGroupChange","params":{"alertOnNoData":true,"criteria":[{"comparator":">=","customMetric":{"aggregation":"max","field":"system.filesystem.used.pct","id":"alert-custom-metric","label":"","type":"custom"},"metric":"custom","threshold":[0.7],"timeSize":1,"timeUnit":"h","warningComparator":">=","warningThreshold":[0.5]}],"filterQuery":"{\"bool\":{\"should\":[{\"match_phrase\":{\"system.filesystem.mount_point\":\"/hostfs/data\"}}],\"minimum_should_match\":1}}","filterQueryText":"system.filesystem.mount_point : \"/hostfs/data\"","nodeType":"host","sourceId":"default"},"schedule":{"interval":"1h"},"scheduledTaskId":null,"tags":["infra","opencrvs-builtin"],"throttle":null,"updatedAt":"2024-02-07T02:27:20.542Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"f023d050-e0c9-11ec-99b8-dbfd54551fda","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294448366,232768],"type":"alert","updated_at":"2024-02-07T08:27:28.366Z","version":"WzQ5NTQzNSwxOV0="} {"attributes":{"actions":[{"actionRef":"preconfigured:preconfigured-alert-history-es-index","actionTypeId":".index","group":"threshold_met","params":{"documents":["{\"@timestamp\":\"2023-06-15T07:57:35.954Z\",\"tags\":\"{{rule.tags}}\",\"rule\":{\"id\":\"{{rule.id}}\",\"name\":\"{{rule.name}}\",\"params\":{\"{{rule__type}}\":\"{{params}}\"},\"space\":\"{{rule.spaceId}}\",\"type\":\"{{rule.type}}\"},\"kibana\":{\"alert\":{\"id\":\"{{alert.id}}\",\"context\":{\"{{rule__type}}\":\"{{context}}\"},\"actionGroup\":\"{{alert.actionGroup}}\",\"actionGroupName\":\"{{alert.actionGroupName}}\"}},\"event\":{\"kind\":\"alert\"}}"],"indexOverride":"kibana-alert-history-services"}}],"alertTypeId":"apm.error_rate","apiKey":null,"apiKeyOwner":null,"consumer":"alerts","createdAt":"2022-05-31T10:10:47.069Z","createdBy":"opencrvs-admin","enabled":false,"executionStatus":{"error":null,"lastExecutionDate":"2024-02-07T08:28:08.400Z","status":"pending"},"legacyId":null,"meta":{"versionApiKeyLastmodified":"7.17.0"},"muteAll":false,"mutedInstanceIds":[],"name":"Error in service","notifyWhen":"onActionGroupChange","params":{"environment":"ENVIRONMENT_ALL","threshold":1,"windowSize":1,"windowUnit":"m"},"schedule":{"interval":"1m"},"scheduledTaskId":null,"tags":[],"throttle":null,"updatedAt":"2024-02-07T02:27:21.551Z","updatedBy":"elastic"},"coreMigrationVersion":"7.17.0","id":"f02b4a60-e0c9-11ec-99b8-dbfd54551fda","migrationVersion":{"alert":"7.16.0"},"references":[],"sort":[1707294457374,232780],"type":"alert","updated_at":"2024-02-07T08:27:37.374Z","version":"WzQ5NTQ0MSwxOV0="} {"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":9,"missingRefCount":0,"missingReferences":[]} \ No newline at end of file diff --git a/infrastructure/monitoring/kibana/kibana.yml b/infrastructure/monitoring/kibana/kibana.yml index 90404ecab..a97e87780 100644 --- a/infrastructure/monitoring/kibana/kibana.yml +++ b/infrastructure/monitoring/kibana/kibana.yml @@ -53,7 +53,6 @@ monitoring.ui.container.elasticsearch.enabled: true xpack.encryptedSavedObjects.encryptionKey: '{{KIBANA_ENCRYPTION_KEY}}' xpack.reporting.encryptionKey: '{{KIBANA_ENCRYPTION_KEY}}' xpack.actions.preconfiguredAlertHistoryEsIndex: true -xpack.infra.sources.default.logAlias: 'logs-*,filebeat-*,kibana_sample_data_logs*,logstash*' # If your Elasticsearch is protected with basic authentication, these settings provide # the username and password that the Kibana server uses to perform maintenance on the Kibana # index at startup. Your Kibana users still need to authenticate with Elasticsearch, which diff --git a/infrastructure/monitoring/kibana/setup-config.sh b/infrastructure/monitoring/kibana/setup-config.sh index a2f5cca78..b94cab21f 100755 --- a/infrastructure/monitoring/kibana/setup-config.sh +++ b/infrastructure/monitoring/kibana/setup-config.sh @@ -34,4 +34,4 @@ $docker_command --connect-timeout 60 -u elastic:$ELASTICSEARCH_SUPERUSER_PASSWOR $docker_command --connect-timeout 60 -u elastic:$ELASTICSEARCH_SUPERUSER_PASSWORD "$kibana_alerting_api_url" | docker run --rm -i --network=opencrvs_overlay_net ghcr.io/jqlang/jq -r '.data[].id' | while read -r id; do $docker_command --connect-timeout 60 -X POST -H 'kbn-xsrf: true' -u elastic:$ELASTICSEARCH_SUPERUSER_PASSWORD "http://kibana:5601/api/alerting/rule/$id/_disable" $docker_command --connect-timeout 60 -X POST -H 'kbn-xsrf: true' -u elastic:$ELASTICSEARCH_SUPERUSER_PASSWORD "http://kibana:5601/api/alerting/rule/$id/_enable" -done +done \ No newline at end of file diff --git a/infrastructure/monitoring/logstash/logstash.conf b/infrastructure/monitoring/logstash/logstash.conf index f71eb84da..dfc866217 100644 --- a/infrastructure/monitoring/logstash/logstash.conf +++ b/infrastructure/monitoring/logstash/logstash.conf @@ -9,7 +9,10 @@ filter { # Docker's GELF driver want's to write into a field named # container_id, but Kibana and other tools read from container.id by default rename => {"container_id" => "container.id"} + # As of V8, Elasticsearch JSON logs now comply with ECS. [host] becomes object + rename => {"[host]" => "[host][name]"} } + truncate { length_bytes => 12 fields => ["container.id"] diff --git a/infrastructure/run-migrations.sh b/infrastructure/run-migrations.sh index d68ee546b..fbe00d8b0 100755 --- a/infrastructure/run-migrations.sh +++ b/infrastructure/run-migrations.sh @@ -25,13 +25,5 @@ elasticsearch_host() { fi } -create_elastic_index () { - local index_name=$1 - echo "Creating ElasticSearch Index: ${index_name}" - docker run --rm --network=opencrvs_overlay_net appropriate/curl curl -XPUT "http://$(elasticsearch_host)/$index_name" -v -} - -create_elastic_index "ocrvs" - # run migration by restarting migration service docker service update --force --update-parallelism 1 --update-delay 30s opencrvs_migration diff --git a/infrastructure/server-setup/inventory/jump.yml b/infrastructure/server-setup/inventory/jump.yml index 639a9d8dd..50d96e16f 100644 --- a/infrastructure/server-setup/inventory/jump.yml +++ b/infrastructure/server-setup/inventory/jump.yml @@ -26,5 +26,5 @@ all: jump-host: hosts: - backup: # @todo set this to be the hostname of your backup server + your-jumpserver-hostname-here: # @todo set this to be the hostname of your jump server ansible_host: '55.55.55.55' diff --git a/package.json b/package.json index 5fedc0f03..6de9bf306 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@opencrvs/countryconfig", - "version": "1.5.0", + "version": "1.6.0", "description": "OpenCRVS country configuration for reference data", "os": [ "darwin", @@ -18,7 +18,7 @@ "scripts": { "dev": "yarn start", "precommit": "lint-staged", - "test": "echo 'no tests, yet'", + "test": "vitest", "test:compilation": "tsc --noEmit", "lint": "eslint -c .eslintrc.js", "start": "cross-env NODE_ENV=development NODE_OPTIONS=--dns-result-order=ipv4first nodemon --exec ts-node -r tsconfig-paths/register src/index.ts", @@ -34,8 +34,8 @@ "@graphql-codegen/add": "^3.1.1", "@graphql-codegen/cli": "^3.3.1", "@graphql-codegen/introspection": "^3.0.1", - "@graphql-codegen/typescript-operations": "^3.0.4", "@graphql-codegen/typescript": "^3.0.4", + "@graphql-codegen/typescript-operations": "^3.0.4", "@inquirer/editor": "^1.2.13", "@octokit/core": "4.2.1", "@types/google-libphonenumber": "^7.4.23", @@ -49,11 +49,12 @@ "@typescript-eslint/eslint-plugin": "^5.60.1", "@typescript-eslint/parser": "^5.60.1", "cypress-xpath": "^2.0.1", + "eslint": "^8.43.0", "eslint-config-prettier": "^8.8.0", "eslint-plugin-prettier": "^4.2.1", - "eslint": "^8.43.0", "husky": "1.0.0-rc.13", "inquirer": "^9.2.12", + "js-yaml": "^4.1.0", "kleur": "^4.1.5", "libsodium-wrappers": "^0.7.13", "lint-staged": "^7.1.0", @@ -61,7 +62,8 @@ "nodemon": "^2.0.22", "pino-pretty": "^11.0.0", "prettier": "^2.8.8", - "react-intl": "^6.4.3" + "react-intl": "^6.4.3", + "vitest": "^2.1.2" }, "dependencies": { "@faker-js/faker": "^6.0.0-alpha.5", @@ -76,8 +78,8 @@ "@types/hapi__hapi": "^20.0.0", "@types/jwt-decode": "^2.2.1", "@types/lodash": "^4.14.117", - "@types/node-fetch": "^2.6.2", "@types/node": "^10.12.5", + "@types/node-fetch": "^2.6.2", "@types/nodemailer": "^6.4.14", "app-module-path": "^2.2.0", "chalk": "^2.4.1", @@ -89,6 +91,8 @@ "dotenv": "^16.4.5", "esbuild": "^0.18.9", "google-libphonenumber": "^3.2.32", + "graphql": "^16.3.0", + "graphql-tag": "^2.12.6", "handlebars": "^4.7.7", "hapi-auth-jwt2": "10.4.0", "hapi-pino": "^9.0.0", @@ -124,4 +128,4 @@ "minimist": "^1.2.2", "acorn": "^6.4.1" } -} \ No newline at end of file +} diff --git a/postman/Event Notification.postman_collection.json b/postman/Event Notification.postman_collection.json index ab3408626..bbe519238 100644 --- a/postman/Event Notification.postman_collection.json +++ b/postman/Event Notification.postman_collection.json @@ -12,7 +12,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"meta\": {\n \"lastUpdated\": \"2022-08-14T14:43:47.000Z\"\n },\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"8f793c5a-3d53-4c9b-898b-1c04759716c6\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"final\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"birth-notification\"\n }\n ],\n \"text\": \"Birth Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"subject\": {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n },\n \"date\": \"2022-08-14T14:43:47.000Z\",\n \"author\": [],\n \"title\": \"Birth Notification\",\n \"section\": [\n {\n \"title\": \"Child details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"child-details\"\n }\n ],\n \"text\": \"Child details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n }\n ]\n },\n {\n \"title\": \"Birth encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"birth-encounter\"\n }\n ],\n \"text\": \"Birth encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n }\n ]\n },\n {\n \"title\": \"Mother's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"mother-details\"\n }\n ],\n \"text\": \"Mother's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n ]\n },\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\"\n }\n ]\n },\n {\n \"title\": \"Father's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"father-details\"\n }\n ],\n \"text\": \"Father's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:8546aaf3-8a60-4150-bc24-ab5579bc0fa2\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"intent\": \"unknown\",\n \"identifier\": [],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"BIRTH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\"\n },\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"MOTHER\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260759205190\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastLocation\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeLocationId}}\"\n }\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Tatke\"\n ],\n \"given\": [\n \"Harney\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"2022-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"use\": \"official\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n },\n \"value\": \"3624667568\"\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Mom\"\n ]\n }\n ],\n \"gender\": \"female\",\n \"telecom\": [\n {\n \"use\": \"mobile\",\n \"system\": \"phone\",\n \"value\": \"+260759205190\"\n }\n ],\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthInteger\": 2,\n \"maritalStatus\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/StructureDefinition/marital-status\",\n \"code\": \"M\"\n }\n ],\n \"text\": \"MARRIED\"\n },\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghanland\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/patient-occupation\",\n \"valueString\": \"Housewife\"\n },\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/educational-attainment\",\n \"valueString\": \"POST_SECONDARY_ISCED_4\"\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"MOTHER\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"use\": \"official\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n },\n \"value\": \"6848901132\"\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Dad\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"telecom\": [\n {\n \"use\": \"mobile\",\n \"system\": \"phone\",\n \"value\": \"+260759205190\"\n }\n ],\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthInteger\": 2,\n \"maritalStatus\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/StructureDefinition/marital-status\",\n \"code\": \"M\"\n }\n ],\n \"text\": \"MARRIED\"\n },\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Madgeland\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/patient-occupation\",\n \"valueString\": \"Businessman\"\n },\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"FAR\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/educational-attainment\",\n \"valueString\": \"POST_SECONDARY_ISCED_4\"\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:45c68568-2ca0-4932-9731-535dd4180fe0\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"procedure\",\n \"display\": \"Procedure\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"57722-1\",\n \"display\": \"Birth plurality of Pregnancy\"\n }\n ]\n },\n \"valueQuantity\": {\n \"value\": \"SINGLE\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d2d3d5b8-658e-4c29-9ec5-cb2431b4ddf3\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"3141-9\",\n \"display\": \"Body weight Measured\"\n }\n ]\n },\n \"valueQuantity\": {\n \"value\": 4,\n \"unit\": \"kg\",\n \"system\": \"http://unitsofmeasure.org\",\n \"code\": \"kg\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:706905cf-7e5d-4d9f-866a-a3795780a990\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"procedure\",\n \"display\": \"Procedure\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"73764-3\",\n \"display\": \"Birth attendant title\"\n }\n ]\n },\n \"valueString\": \"PHYSICIAN\"\n }\n }\n ]\n}", + "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"meta\": {\n \"lastUpdated\": \"2022-08-14T14:43:47.000Z\"\n },\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"8f793c5a-3d53-4c9b-898b-1c04759716c6\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"final\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"birth-notification\"\n }\n ],\n \"text\": \"Birth Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"subject\": {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n },\n \"date\": \"2022-08-14T14:43:47.000Z\",\n \"author\": [],\n \"title\": \"Birth Notification\",\n \"section\": [\n {\n \"title\": \"Child details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"child-details\"\n }\n ],\n \"text\": \"Child details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n }\n ]\n },\n {\n \"title\": \"Birth encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"birth-encounter\"\n }\n ],\n \"text\": \"Birth encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n }\n ]\n },\n {\n \"title\": \"Mother's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"mother-details\"\n }\n ],\n \"text\": \"Mother's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n ]\n },\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\"\n }\n ]\n },\n {\n \"title\": \"Father's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"father-details\"\n }\n ],\n \"text\": \"Father's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:8546aaf3-8a60-4150-bc24-ab5579bc0fa2\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"intent\": \"unknown\",\n \"identifier\": [],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"BIRTH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\"\n },\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"MOTHER\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260759205190\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Tatke\"\n ],\n \"given\": [\n \"Harney\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"2022-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"use\": \"official\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n },\n \"value\": \"3624667568\"\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Mom\"\n ]\n }\n ],\n \"gender\": \"female\",\n \"telecom\": [\n {\n \"use\": \"mobile\",\n \"system\": \"phone\",\n \"value\": \"+260759205190\"\n }\n ],\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthInteger\": 2,\n \"maritalStatus\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/StructureDefinition/marital-status\",\n \"code\": \"M\"\n }\n ],\n \"text\": \"MARRIED\"\n },\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghanland\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/patient-occupation\",\n \"valueString\": \"Housewife\"\n },\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/educational-attainment\",\n \"valueString\": \"POST_SECONDARY_ISCED_4\"\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"MOTHER\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"use\": \"official\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n },\n \"value\": \"6848901132\"\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Dad\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"telecom\": [\n {\n \"use\": \"mobile\",\n \"system\": \"phone\",\n \"value\": \"+260759205190\"\n }\n ],\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthInteger\": 2,\n \"maritalStatus\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/StructureDefinition/marital-status\",\n \"code\": \"M\"\n }\n ],\n \"text\": \"MARRIED\"\n },\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Madgeland\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/patient-occupation\",\n \"valueString\": \"Businessman\"\n },\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"FAR\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/educational-attainment\",\n \"valueString\": \"POST_SECONDARY_ISCED_4\"\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:45c68568-2ca0-4932-9731-535dd4180fe0\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"procedure\",\n \"display\": \"Procedure\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"57722-1\",\n \"display\": \"Birth plurality of Pregnancy\"\n }\n ]\n },\n \"valueQuantity\": {\n \"value\": \"SINGLE\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d2d3d5b8-658e-4c29-9ec5-cb2431b4ddf3\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"3141-9\",\n \"display\": \"Body weight Measured\"\n }\n ]\n },\n \"valueQuantity\": {\n \"value\": 4,\n \"unit\": \"kg\",\n \"system\": \"http://unitsofmeasure.org\",\n \"code\": \"kg\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:706905cf-7e5d-4d9f-866a-a3795780a990\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"procedure\",\n \"display\": \"Procedure\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"73764-3\",\n \"display\": \"Birth attendant title\"\n }\n ]\n },\n \"valueString\": \"PHYSICIAN\"\n }\n }\n ]\n}", "options": { "raw": { "language": "json" @@ -38,7 +38,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"meta\": {\n \"lastUpdated\": \"2022-08-14T14:43:47.000Z\"\n },\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"8f793c5a-3d53-4c9b-898b-1c04759716c6\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"final\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"birth-notification\"\n }\n ],\n \"text\": \"Birth Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"subject\": {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n },\n \"date\": \"2022-08-14T14:43:47.000Z\",\n \"title\": \"Birth Notification\",\n \"section\": [\n {\n \"title\": \"Child details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"child-details\"\n }\n ],\n \"text\": \"Child details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n }\n ]\n },\n {\n \"title\": \"Birth encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"birth-encounter\"\n }\n ],\n \"text\": \"Birth encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n }\n ]\n },\n {\n \"title\": \"Mother's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"mother-details\"\n }\n ],\n \"text\": \"Mother's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n ]\n },\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\"\n }\n ]\n },\n {\n \"title\": \"Father's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"father-details\"\n }\n ],\n \"text\": \"Father's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:8546aaf3-8a60-4150-bc24-ab5579bc0fa2\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"intent\": \"unknown\",\n \"identifier\": [],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"BIRTH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\"\n },\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"MOTHER\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260759205190\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastLocation\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeLocationId}}\"\n }\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Min\"\n ],\n \"given\": [\n \"Child\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"2022-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Mom\"\n ]\n }\n ],\n \"gender\": \"female\",\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"MOTHER\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Dad\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n }\n ]\n}", + "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"meta\": {\n \"lastUpdated\": \"2022-08-14T14:43:47.000Z\"\n },\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"8f793c5a-3d53-4c9b-898b-1c04759716c6\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"final\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"birth-notification\"\n }\n ],\n \"text\": \"Birth Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"subject\": {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n },\n \"date\": \"2022-08-14T14:43:47.000Z\",\n \"title\": \"Birth Notification\",\n \"section\": [\n {\n \"title\": \"Child details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"child-details\"\n }\n ],\n \"text\": \"Child details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\"\n }\n ]\n },\n {\n \"title\": \"Birth encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"birth-encounter\"\n }\n ],\n \"text\": \"Birth encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\"\n }\n ]\n },\n {\n \"title\": \"Mother's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"mother-details\"\n }\n ],\n \"text\": \"Mother's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n ]\n },\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\"\n }\n ]\n },\n {\n \"title\": \"Father's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"father-details\"\n }\n ],\n \"text\": \"Father's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:8546aaf3-8a60-4150-bc24-ab5579bc0fa2\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"intent\": \"unknown\",\n \"identifier\": [],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"BIRTH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:37dd8e55-69c0-493d-b1a0-b7462a1d806a\"\n },\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"MOTHER\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260759205190\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:760c393e-4dc3-4572-83f6-b70765963ef1\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Min\"\n ],\n \"given\": [\n \"Child\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"2022-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Mom\"\n ]\n }\n ],\n \"gender\": \"female\",\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:b74fbd0e-8536-4c11-833d-781e89a4b553\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"MOTHER\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:d9d3a8c8-6a47-47a1-be86-0493a4ec55a7\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:ad1e15bb-51da-449a-8a12-c7dae10728e4\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"family\": [\n \"Ratke\"\n ],\n \"given\": [\n \"Dad\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"2002-06-29\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:7cb1d9cc-ea4b-4046-bea0-38bdf3082f56\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n }\n ]\n}", "options": { "raw": { "language": "json" @@ -64,7 +64,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:56e7d617-1011-4ca1-863f-3b7262709329\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"56e7d617-1011-4ca1-863f-3b7262709329\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"preliminary\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"death-notification\"\n }\n ],\n \"text\": \"Death Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"title\": \"Death Notification\",\n \"section\": [\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:9ae636db-f7ad-47aa-9e8a-5bb651482084\"\n }\n ]\n },\n {\n \"title\": \"Deceased details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"deceased-details\"\n }\n ],\n \"text\": \"Deceased details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:5c192954-d798-402f-a539-31aada34d005\"\n }\n ]\n },\n {\n \"title\": \"Death encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"death-encounter\"\n }\n ],\n \"text\": \"Death encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:8de42635-6dac-4d59-96b4-943ceb40ad1e\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d3bdcf50-f6b9-40aa-a30b-d9515275becc\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"DEATH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:56e7d617-1011-4ca1-863f-3b7262709329\"\n },\n \"identifier\": [],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"SPOUSE\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260712345679\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastLocation\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeLocationId}}\"\n }\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:9ae636db-f7ad-47aa-9e8a-5bb651482084\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"SPOUSE\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:398afc2a-09c9-4b7b-bc45-2bef06501cf0\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:5c192954-d798-402f-a539-31aada34d005\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Salam\"\n ],\n \"family\": [\n \"Ahmed\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"1975-12-12\",\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"deceasedBoolean\": true,\n \"deceasedDateTime\": \"2021-11-12\",\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:398afc2a-09c9-4b7b-bc45-2bef06501cf0\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Anjum\"\n ],\n \"family\": [\n \"Begum\"\n ]\n }\n ],\n \"birthDate\": \"1985-12-12\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:8de42635-6dac-4d59-96b4-943ceb40ad1e\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:6a0bd2db-4fa4-4665-ad62-24821dd01f2a\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:8de42635-6dac-4d59-96b4-943ceb40ad1e\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"cause-of-death-established\",\n \"display\": \"Cause of death established\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/cause-of-death-established\",\n \"code\": \"false\"\n }\n ]\n }\n }\n }\n ],\n \"meta\": {\n \"lastUpdated\": \"2022-11-30T05:59:51.196Z\"\n }\n}", + "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:56e7d617-1011-4ca1-863f-3b7262709329\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"56e7d617-1011-4ca1-863f-3b7262709329\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"preliminary\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"death-notification\"\n }\n ],\n \"text\": \"Death Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"title\": \"Death Notification\",\n \"section\": [\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:9ae636db-f7ad-47aa-9e8a-5bb651482084\"\n }\n ]\n },\n {\n \"title\": \"Deceased details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"deceased-details\"\n }\n ],\n \"text\": \"Deceased details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:5c192954-d798-402f-a539-31aada34d005\"\n }\n ]\n },\n {\n \"title\": \"Death encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"death-encounter\"\n }\n ],\n \"text\": \"Death encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:8de42635-6dac-4d59-96b4-943ceb40ad1e\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:d3bdcf50-f6b9-40aa-a30b-d9515275becc\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"DEATH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:56e7d617-1011-4ca1-863f-3b7262709329\"\n },\n \"identifier\": [],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"SPOUSE\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260712345679\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:9ae636db-f7ad-47aa-9e8a-5bb651482084\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"SPOUSE\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:398afc2a-09c9-4b7b-bc45-2bef06501cf0\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:5c192954-d798-402f-a539-31aada34d005\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Salam\"\n ],\n \"family\": [\n \"Ahmed\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"1975-12-12\",\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"deceasedBoolean\": true,\n \"deceasedDateTime\": \"2021-11-12\",\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:398afc2a-09c9-4b7b-bc45-2bef06501cf0\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Anjum\"\n ],\n \"family\": [\n \"Begum\"\n ]\n }\n ],\n \"birthDate\": \"1985-12-12\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"\",\n \"\",\n \"\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:8de42635-6dac-4d59-96b4-943ceb40ad1e\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:6a0bd2db-4fa4-4665-ad62-24821dd01f2a\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:8de42635-6dac-4d59-96b4-943ceb40ad1e\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"cause-of-death-established\",\n \"display\": \"Cause of death established\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/cause-of-death-established\",\n \"code\": \"false\"\n }\n ]\n }\n }\n }\n ],\n \"meta\": {\n \"lastUpdated\": \"2022-11-30T05:59:51.196Z\"\n }\n}", "options": { "raw": { "language": "json" @@ -90,7 +90,7 @@ "header": [], "body": { "mode": "raw", - "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:7109f150-6262-4798-835e-55b3e4dd4cfb\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"7109f150-6262-4798-835e-55b3e4dd4cfb\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"preliminary\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"death-notification\"\n }\n ],\n \"text\": \"Death Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"title\": \"Death Notification\",\n \"section\": [\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:1363f62f-e34f-4c03-90f3-5fa1d40d0892\"\n }\n ]\n },\n {\n \"title\": \"Deceased details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"deceased-details\"\n }\n ],\n \"text\": \"Deceased details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:233b56c8-aa3d-4d32-9d42-7afe1200fc4f\"\n }\n ]\n },\n {\n \"title\": \"Death encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"death-encounter\"\n }\n ],\n \"text\": \"Death encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:cbce7430-3c63-457e-a6d8-ed3b35a97a64\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"DEATH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:7109f150-6262-4798-835e-55b3e4dd4cfb\"\n },\n \"identifier\": [],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"SPOUSE\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260712345679\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastLocation\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeLocationId}}\"\n }\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:1363f62f-e34f-4c03-90f3-5fa1d40d0892\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"SPOUSE\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:42061dc8-0d97-493a-94e4-e60d0f3fc070\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:233b56c8-aa3d-4d32-9d42-7afe1200fc4f\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"value\": \"1234123421\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n }\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Bashir\"\n ],\n \"family\": [\n \"Ahmed\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"1971-12-12\",\n \"maritalStatus\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/StructureDefinition/marital-status\",\n \"code\": \"M\"\n }\n ],\n \"text\": \"MARRIED\"\n },\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"deceasedBoolean\": true,\n \"deceasedDateTime\": \"2021-12-12\",\n \"multipleBirthBoolean\": false,\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:42061dc8-0d97-493a-94e4-e60d0f3fc070\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"value\": \"4321234257\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n }\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Selena\"\n ],\n \"family\": [\n \"Begum\"\n ]\n }\n ],\n \"birthDate\": \"1980-12-12\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:7b4fcd33-5b39-463a-bbd4-4ac2e41e5f99\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"uncertified-manner-of-death\",\n \"display\": \"Uncertified manner of death\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/manner-of-death\",\n \"code\": \"NATURAL_CAUSES\"\n }\n ]\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:89c0605f-8eb8-4f58-98ff-317efe64e91f\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"cause-of-death-method\",\n \"display\": \"Cause of death method\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/cause-of-death-method\",\n \"code\": \"PHYSICIAN\"\n }\n ]\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:6a0bd2db-4fa4-4665-ad62-24821dd01f2a\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"cause-of-death-established\",\n \"display\": \"Cause of death established\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/cause-of-death-established\",\n \"code\": \"true\"\n }\n ]\n }\n }\n }\n ],\n \"meta\": {\n \"lastUpdated\": \"2022-11-30T05:50:26.175Z\"\n }\n}", + "raw": "{\n \"resourceType\": \"Bundle\",\n \"type\": \"document\",\n \"entry\": [\n {\n \"fullUrl\": \"urn:uuid:7109f150-6262-4798-835e-55b3e4dd4cfb\",\n \"resource\": {\n \"identifier\": {\n \"system\": \"urn:ietf:rfc:3986\",\n \"value\": \"7109f150-6262-4798-835e-55b3e4dd4cfb\"\n },\n \"resourceType\": \"Composition\",\n \"status\": \"preliminary\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-types\",\n \"code\": \"death-notification\"\n }\n ],\n \"text\": \"Death Notification\"\n },\n \"class\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-classes\",\n \"code\": \"crvs-document\"\n }\n ],\n \"text\": \"CRVS Document\"\n },\n \"title\": \"Death Notification\",\n \"section\": [\n {\n \"title\": \"Informant's details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"informant-details\"\n }\n ],\n \"text\": \"Informant's details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:1363f62f-e34f-4c03-90f3-5fa1d40d0892\"\n }\n ]\n },\n {\n \"title\": \"Deceased details\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/doc-sections\",\n \"code\": \"deceased-details\"\n }\n ],\n \"text\": \"Deceased details\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:233b56c8-aa3d-4d32-9d42-7afe1200fc4f\"\n }\n ]\n },\n {\n \"title\": \"Death encounter\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/sections\",\n \"code\": \"death-encounter\"\n }\n ],\n \"text\": \"Death encounter\"\n },\n \"entry\": [\n {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:cbce7430-3c63-457e-a6d8-ed3b35a97a64\",\n \"resource\": {\n \"resourceType\": \"Task\",\n \"status\": \"draft\",\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/types\",\n \"code\": \"DEATH\"\n }\n ]\n },\n \"focus\": {\n \"reference\": \"urn:uuid:7109f150-6262-4798-835e-55b3e4dd4cfb\"\n },\n \"identifier\": [],\n \"extension\": [\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person\",\n \"valueString\": \"SPOUSE\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-phone-number\",\n \"valueString\": \"+260712345679\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/contact-person-email\",\n \"valueString\": \"axon@gmail.com\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/timeLoggedMS\",\n \"valueInteger\": 0\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/in-complete-fields\",\n \"valueString\": \"N/A\"\n },\n {\n \"url\": \"http://opencrvs.org/specs/extension/regLastOffice\",\n \"valueReference\": {\n \"reference\": \"Location/{{officeId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:1363f62f-e34f-4c03-90f3-5fa1d40d0892\",\n \"resource\": {\n \"resourceType\": \"RelatedPerson\",\n \"relationship\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/ValueSet/relatedperson-relationshiptype\",\n \"code\": \"SPOUSE\"\n }\n ]\n },\n \"patient\": {\n \"reference\": \"urn:uuid:42061dc8-0d97-493a-94e4-e60d0f3fc070\"\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:233b56c8-aa3d-4d32-9d42-7afe1200fc4f\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"value\": \"1234123421\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n }\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Bashir\"\n ],\n \"family\": [\n \"Ahmed\"\n ]\n }\n ],\n \"gender\": \"male\",\n \"birthDate\": \"1971-12-12\",\n \"maritalStatus\": {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/StructureDefinition/marital-status\",\n \"code\": \"M\"\n }\n ],\n \"text\": \"MARRIED\"\n },\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"deceasedBoolean\": true,\n \"deceasedDateTime\": \"2021-12-12\",\n \"multipleBirthBoolean\": false,\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:42061dc8-0d97-493a-94e4-e60d0f3fc070\",\n \"resource\": {\n \"resourceType\": \"Patient\",\n \"active\": true,\n \"identifier\": [\n {\n \"value\": \"4321234257\",\n \"type\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/identifier-type\",\n \"code\": \"NATIONAL_ID\"\n }\n ]\n }\n }\n ],\n \"name\": [\n {\n \"use\": \"en\",\n \"given\": [\n \"Selena\"\n ],\n \"family\": [\n \"Begum\"\n ]\n }\n ],\n \"birthDate\": \"1980-12-12\",\n \"deceasedBoolean\": false,\n \"multipleBirthBoolean\": false,\n \"address\": [\n {\n \"type\": \"PRIMARY_ADDRESS\",\n \"line\": [\n \"12\",\n \"Usual Street\",\n \"Usual Residental Area\",\n \"\",\n \"\",\n \"URBAN\"\n ],\n \"city\": \"Meghnan\",\n \"district\": \"{{districtId}}\",\n \"state\": \"{{stateId}}\",\n \"postalCode\": \"52275\",\n \"country\": \"{{countryCode}}\"\n }\n ],\n \"extension\": [\n {\n \"url\": \"http://hl7.org/fhir/StructureDefinition/patient-nationality\",\n \"extension\": [\n {\n \"url\": \"code\",\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"urn:iso:std:iso:3166\",\n \"code\": \"{{countryCode}}\"\n }\n ]\n }\n },\n {\n \"url\": \"period\",\n \"valuePeriod\": {\n \"start\": \"\",\n \"end\": \"\"\n }\n }\n ]\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\",\n \"resource\": {\n \"resourceType\": \"Encounter\",\n \"status\": \"finished\",\n \"location\": [\n {\n \"location\": {\n \"reference\": \"Location/{{facilityId}}\"\n }\n }\n ]\n }\n },\n {\n \"fullUrl\": \"urn:uuid:7b4fcd33-5b39-463a-bbd4-4ac2e41e5f99\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"uncertified-manner-of-death\",\n \"display\": \"Uncertified manner of death\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/manner-of-death\",\n \"code\": \"NATURAL_CAUSES\"\n }\n ]\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:89c0605f-8eb8-4f58-98ff-317efe64e91f\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"cause-of-death-method\",\n \"display\": \"Cause of death method\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/cause-of-death-method\",\n \"code\": \"PHYSICIAN\"\n }\n ]\n }\n }\n },\n {\n \"fullUrl\": \"urn:uuid:6a0bd2db-4fa4-4665-ad62-24821dd01f2a\",\n \"resource\": {\n \"resourceType\": \"Observation\",\n \"status\": \"final\",\n \"context\": {\n \"reference\": \"urn:uuid:e9e011f5-78dc-4e2f-8ce2-ea80e04a510f\"\n },\n \"category\": [\n {\n \"coding\": [\n {\n \"system\": \"http://hl7.org/fhir/observation-category\",\n \"code\": \"vital-signs\",\n \"display\": \"Vital Signs\"\n }\n ]\n }\n ],\n \"code\": {\n \"coding\": [\n {\n \"system\": \"http://loinc.org\",\n \"code\": \"cause-of-death-established\",\n \"display\": \"Cause of death established\"\n }\n ]\n },\n \"valueCodeableConcept\": {\n \"coding\": [\n {\n \"system\": \"http://opencrvs.org/specs/cause-of-death-established\",\n \"code\": \"true\"\n }\n ]\n }\n }\n }\n ],\n \"meta\": {\n \"lastUpdated\": \"2022-11-30T05:50:26.175Z\"\n }\n}", "options": { "raw": { "language": "json" @@ -141,10 +141,6 @@ } ], "variable": [ - { - "key": "officeLocationId", - "value": "c24c0b72-11b5-4c1a-bbb7-61112fa6f481" - }, { "key": "officeId", "value": "0be1dc9b-5c8b-4d20-a88c-08cafc71c99a" diff --git a/src/api/application/application-config-default.ts b/src/api/application/application-config.ts similarity index 66% rename from src/api/application/application-config-default.ts rename to src/api/application/application-config.ts index 9b2db665a..9ac529c54 100644 --- a/src/api/application/application-config-default.ts +++ b/src/api/application/application-config.ts @@ -1,6 +1,6 @@ import { countryLogo } from '@countryconfig/api/application/country-logo' -export const defaultApplicationConfig = { +export const applicationConfig = { APPLICATION_NAME: 'Farajaland CRS', BIRTH: { REGISTRATION_TARGET: 30, @@ -56,3 +56,34 @@ export const defaultApplicationConfig = { } export const COUNTRY_WIDE_CRUDE_DEATH_RATE = 10 + +type EventNotificationFlags = { + 'sent-notification'?: boolean + 'sent-notification-for-review'?: boolean + 'sent-for-approval'?: boolean + registered?: boolean + 'sent-for-updates'?: boolean +} + +type NotificationFlags = { + BIRTH?: EventNotificationFlags + DEATH?: EventNotificationFlags + MARRIAGE?: EventNotificationFlags +} + +export const notificationForRecord: NotificationFlags = { + BIRTH: { + 'sent-notification': true, + 'sent-notification-for-review': true, + 'sent-for-approval': true, + registered: true, + 'sent-for-updates': true + }, + DEATH: { + 'sent-notification': true, + 'sent-notification-for-review': true, + 'sent-for-approval': true, + registered: true, + 'sent-for-updates': true + } +} diff --git a/src/api/application/handler.ts b/src/api/application/handler.ts index 68e655f47..a7b028d30 100644 --- a/src/api/application/handler.ts +++ b/src/api/application/handler.ts @@ -10,7 +10,7 @@ */ import { Request, ResponseToolkit } from '@hapi/hapi' -import { defaultApplicationConfig as applicationConfig } from './application-config-default' +import { applicationConfig } from './application-config' export async function applicationConfigHandler(_: Request, h: ResponseToolkit) { const res = JSON.stringify(applicationConfig) diff --git a/src/api/certificates/handler.ts b/src/api/certificates/handler.ts new file mode 100644 index 000000000..658e04eb6 --- /dev/null +++ b/src/api/certificates/handler.ts @@ -0,0 +1,20 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * OpenCRVS is also distributed under the terms of the Civil Registration + * & Healthcare Disclaimer located at http://opencrvs.org/license. + * + * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. + */ + +import { Request, ResponseToolkit } from '@hapi/hapi' +import { readFileSync } from 'fs' + +export async function certificateHandler(request: Request, h: ResponseToolkit) { + const res = readFileSync( + `./src/api/certificates/source/Farajaland-${request.params.event}-certificate-v2.svg` + ).toString() + return h.response(res).code(200) +} diff --git a/src/data-seeding/certificates/source/Farajaland-birth-certificate-v2.svg b/src/api/certificates/source/Farajaland-birth-certificate-v2.svg similarity index 98% rename from src/data-seeding/certificates/source/Farajaland-birth-certificate-v2.svg rename to src/api/certificates/source/Farajaland-birth-certificate-v2.svg index 6d66223f4..7aa67b024 100644 --- a/src/data-seeding/certificates/source/Farajaland-birth-certificate-v2.svg +++ b/src/api/certificates/source/Farajaland-birth-certificate-v2.svg @@ -47,7 +47,6 @@ REPUBLIC OF FARAJALAND / REPUBLIQUE DE FARAJALAND CERTIFICATE OF BIRTH / ACTE DE NAISSANCE - 1. Child’s full name /
Nom complet de l'enfant @@ -129,9 +128,6 @@ - - - diff --git a/src/data-seeding/certificates/source/Farajaland-death-certificate-v2.svg b/src/api/certificates/source/Farajaland-death-certificate-v2.svg similarity index 98% rename from src/data-seeding/certificates/source/Farajaland-death-certificate-v2.svg rename to src/api/certificates/source/Farajaland-death-certificate-v2.svg index 5ed6a20cd..994b425a3 100644 --- a/src/data-seeding/certificates/source/Farajaland-death-certificate-v2.svg +++ b/src/api/certificates/source/Farajaland-death-certificate-v2.svg @@ -14,7 +14,6 @@ Registrar / L'Officier de l'État Civil {{registrar.name}} I certify that this certificate is a true copy of the civil registry and is issued by the mandated authority in pursuance of civil registration law / Je certifie que le présent certificat est une copie conforme du registre d'état civil et qu'il est délivré par l'autorité mandatée conformément à la loi sur l'état civil. - 1. Deceased full name /
Nom complet du défunt @@ -114,9 +113,6 @@ REPUBLIC OF FARAJALAND / REPUBLIQUE DE FARAJALAND CERTIFICATE OF DEATH / ACTE DE DEATH - - - diff --git a/src/api/certificates/source/Farajaland-marriage-certificate-v2.svg b/src/api/certificates/source/Farajaland-marriage-certificate-v2.svg new file mode 100644 index 000000000..7bd68e87b --- /dev/null +++ b/src/api/certificates/source/Farajaland-marriage-certificate-v2.svg @@ -0,0 +1,165 @@ + + + + + +{{#ifCond printInAdvance '!==' true}}{{/ifCond}} + +CAUTION : THERE ARE OFFENCES RELATING TO FALSIFYING OR ALTERING A CERTIFICATE AND USING OR POSSESSING A FALSE CERTIFICATE IS NOT PROOF OF IDENTITY / ATTENTION : IL EXISTE DES INFRACTIONS RELATIVES A LA FALSIFIATION OU À LA MODIFICATION D'UN CERTIFICAT ET A L'UTILISATION OU LA POSSESSION D'UN FAUX CERTIFICAT. UN CERTIFICAT N'EST PAS UNE PREUVE D'IDENTITE + + + + + + + + + + + + + + + + + +FARAJALAND + +{{certificateDate}} +Date of certification / Date de délivrance +{{location loggedInUser.officeId 'name'}}{{location loggedInUser.districtId 'name'}}, {{location loggedInUser.stateId 'name'}}, Farajaland +Place of certification / Lieu de certification + +Registrar / L'Officier de l'État Civil +{{registrar.name}} +I certify that this certificate is a true copy of the civil registry and is issued by the mandated authority in pursuance of civil registration law / Je certifie que le présent certificat est une copie conforme du registre d'état civil et qu'il est délivré par l'autorité mandatée conformément à la loi sur l'état civil. + +REPUBLIC OF FARAJALAND / REPUBLIQUE DE FARAJALAND +CERTIFICATE OF MARRIAGE / ACTE DE MARRIAGE + +1. +Groom’s full name /
Nom complet du marié + +{{groomFirstName}} {{groomFamilyName}} + + +2. +Bride’s full name /
Nom complet de la mariée + +{{brideFirstName}} {{brideFamilyName}} + + +3. + /
 +Date of marriageDate du mariage + +{{eventDate}} + + +4. + /
 +Place of marriageLieu de mariage + + + {{location districtPlaceofmarriageId 'name'}}{{internationalDistrictPlaceofmarriage}}, + {{location statePlaceofmarriageId 'name'}}{{internationalStatePlaceofmarriage}}, {{countryPlaceofmarriage}} + + + + +5. +Witnesses / Les témoins + +{{witnessOneFirstName}} {{witnessOneFamilyName}}
{{witnessTwoFirstName}} {{witnessTwoFamilyName}} + + + +6. +Lieu d'enregistrement + +Place of registration / + +{{location registrar.officeId 'name'}}
{{location registrar.districtId 'name'}}, {{location registrar.stateId 'name'}}, Farajaland + + +7. + +Date of registration / +Date d'enregistrement + +{{registrationDate}} + + +8. +/
 +Registered by Enregistré par + +{{registrar.name}} + + + +9. +Signatures of bride and groom / Signatures des mariés + +Groom / Marié + +Bride / Mariée + + + + +No. {{registrationNumber}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{{#ifCond printInAdvance '!==' true}}{{/ifCond}} + + + + diff --git a/src/data-seeding/certificates/source/test/UsingAddressHandlebars.svg b/src/api/certificates/source/test/UsingAddressHandlebars.svg similarity index 100% rename from src/data-seeding/certificates/source/test/UsingAddressHandlebars.svg rename to src/api/certificates/source/test/UsingAddressHandlebars.svg diff --git a/src/data-seeding/certificates/source/test/UsingSignatureHandlebars.svg b/src/api/certificates/source/test/UsingSignatureHandlebars.svg similarity index 100% rename from src/data-seeding/certificates/source/test/UsingSignatureHandlebars.svg rename to src/api/certificates/source/test/UsingSignatureHandlebars.svg diff --git a/src/api/record-notification/handler.ts b/src/api/record-notification/handler.ts new file mode 100644 index 000000000..a10916e07 --- /dev/null +++ b/src/api/record-notification/handler.ts @@ -0,0 +1,9 @@ +import * as Hapi from '@hapi/hapi' +import { notificationForRecord } from '../application/application-config' + +export function recordNotificationHandler( + request: Hapi.Request, + h: Hapi.ResponseToolkit +) { + return h.response(notificationForRecord) +} diff --git a/src/client-static/images/icons/icon-128x128.png b/src/client-static/images/icons/icon-128x128.png new file mode 100644 index 000000000..fbf19dc54 Binary files /dev/null and b/src/client-static/images/icons/icon-128x128.png differ diff --git a/src/client-static/images/icons/icon-144x144.png b/src/client-static/images/icons/icon-144x144.png new file mode 100644 index 000000000..bc3d73139 Binary files /dev/null and b/src/client-static/images/icons/icon-144x144.png differ diff --git a/src/client-static/images/icons/icon-152x152.png b/src/client-static/images/icons/icon-152x152.png new file mode 100644 index 000000000..4f27e38bd Binary files /dev/null and b/src/client-static/images/icons/icon-152x152.png differ diff --git a/src/client-static/images/icons/icon-196x196.png b/src/client-static/images/icons/icon-196x196.png new file mode 100644 index 000000000..a50401d70 Binary files /dev/null and b/src/client-static/images/icons/icon-196x196.png differ diff --git a/src/client-static/images/icons/icon-256x256.png b/src/client-static/images/icons/icon-256x256.png new file mode 100644 index 000000000..6282479ad Binary files /dev/null and b/src/client-static/images/icons/icon-256x256.png differ diff --git a/src/client-static/images/icons/icon-512x512.png b/src/client-static/images/icons/icon-512x512.png new file mode 100644 index 000000000..4625da3fc Binary files /dev/null and b/src/client-static/images/icons/icon-512x512.png differ diff --git a/src/client-static/images/icons/icon-72x72.png b/src/client-static/images/icons/icon-72x72.png new file mode 100644 index 000000000..4881f71e0 Binary files /dev/null and b/src/client-static/images/icons/icon-72x72.png differ diff --git a/src/client-static/images/logo-90x90.svg b/src/client-static/images/logo-90x90.svg new file mode 100644 index 000000000..7e24a831b --- /dev/null +++ b/src/client-static/images/logo-90x90.svg @@ -0,0 +1,22 @@ + + + + \ No newline at end of file diff --git a/src/client-static/manifest.json b/src/client-static/manifest.json new file mode 100644 index 000000000..195d48c73 --- /dev/null +++ b/src/client-static/manifest.json @@ -0,0 +1,47 @@ +{ + "name": "OpenCRVS", + "short_name": "OpenCRVS", + "theme_color": "#4c68c1", + "background_color": "#4c68c1", + "display": "standalone", + "scope": "/", + "start_url": "/", + "icons": [ + { + "src": "images/icons/icon-72x72.png", + "sizes": "72x72", + "type": "image/png" + }, + { + "src": "images/icons/icon-128x128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "images/icons/icon-144x144.png", + "sizes": "144x144", + "type": "image/png" + }, + { + "src": "images/icons/icon-152x152.png", + "sizes": "152x152", + "type": "image/png" + }, + { + "src": "images/icons/icon-196x196.png", + "sizes": "196x196", + "type": "image/png" + }, + { + "src": "images/icons/icon-256x256.png", + "sizes": "256x256", + "type": "image/png" + }, + { + "src": "images/icons/icon-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "permissions": ["unlimitedStorage"] +} diff --git a/src/constants.ts b/src/constants.ts index 0ff671d46..795d1cc3e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -10,6 +10,7 @@ */ export const TEST_SOURCE = `${process.cwd()}/src/tests/` export const DOMAIN = process.env.DOMAIN || '*' +export const GATEWAY_URL = process.env.GATEWAY_URL || 'http://localhost:7070' export const LOGIN_URL = process.env.LOGIN_URL || 'http://localhost:3020/' export const CLIENT_APP_URL = process.env.CLIENT_APP_URL || 'http://localhost:3000/' diff --git a/src/data-seeding/certificates/handler.ts b/src/data-seeding/certificates/handler.ts deleted file mode 100644 index 57ee2ed35..000000000 --- a/src/data-seeding/certificates/handler.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * OpenCRVS is also distributed under the terms of the Civil Registration - * & Healthcare Disclaimer located at http://opencrvs.org/license. - * - * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. - */ - -import { Request, ResponseToolkit } from '@hapi/hapi' -import { readFileSync } from 'fs' - -export async function certificateHandler(request: Request, h: ResponseToolkit) { - if (request.params.event) { - const res = readFileSync( - `./src/data-seeding/certificates/source/Farajaland-${request.params.event}-certificate-v2.svg` - ).toString() - return h.response(res).code(200) - } - - const Certificates = [ - { - event: 'birth', - fileName: 'Farajaland-birth-certificate-v2.svg', - svgCode: readFileSync( - './src/data-seeding/certificates/source/Farajaland-birth-certificate-v2.svg' - ).toString() - }, - { - event: 'death', - fileName: 'Farajaland-death-certificate-v2.svg', - svgCode: readFileSync( - './src/data-seeding/certificates/source/Farajaland-death-certificate-v2.svg' - ).toString() - }, - { - event: 'marriage', - fileName: 'Farajaland-marriage-certificate-v2.svg', - svgCode: readFileSync( - './src/data-seeding/certificates/source/Farajaland-marriage-certificate-v2.svg' - ).toString() - } - ] - const res = JSON.stringify(Certificates) - return h.response(res) -} diff --git a/src/data-seeding/certificates/source/Farajaland-marriage-certificate-v2.svg b/src/data-seeding/certificates/source/Farajaland-marriage-certificate-v2.svg deleted file mode 100644 index 3c0dca946..000000000 --- a/src/data-seeding/certificates/source/Farajaland-marriage-certificate-v2.svg +++ /dev/null @@ -1,172 +0,0 @@ - - - - - -{{#ifCond printInAdvance '!==' true}}{{/ifCond}} - -CAUTION : THERE ARE OFFENCES RELATING TO FALSIFYING OR ALTERING A CERTIFICATE AND USING OR POSSESSING A FALSE CERTIFICATE IS NOT PROOF OF IDENTITY / ATTENTION : IL EXISTE DES INFRACTIONS RELATIVES A LA FALSIFIATION OU À LA MODIFICATION D'UN CERTIFICAT ET A L'UTILISATION OU LA POSSESSION D'UN FAUX CERTIFICAT. UN CERTIFICAT N'EST PAS UNE PREUVE D'IDENTITE - - - - - - - - - - - - - - - - - -FARAJALAND - -{{certificateDate}} -Date of certification / Date de délivrance -{{location loggedInUser.officeId 'name'}}{{location loggedInUser.districtId 'name'}}, {{location loggedInUser.stateId 'name'}}, Farajaland -Place of certification / Lieu de certification - -Registrar / L'Officier de l'État Civil -{{registrar.name}} -I certify that this certificate is a true copy of the civil registry and is issued by the mandated authority in pursuance of civil registration law / Je certifie que le présent certificat est une copie conforme du registre d'état civil et qu'il est délivré par l'autorité mandatée conformément à la loi sur l'état civil. - -REPUBLIC OF FARAJALAND / REPUBLIQUE DE FARAJALAND -CERTIFICATE OF MARRIAGE / ACTE DE MARRIAGE - - -1. -Groom’s full name /
Nom complet du marié - -{{groomFirstName}} {{groomFamilyName}} - - -2. -Bride’s full name /
Nom complet de la mariée - -{{brideFirstName}} {{brideFamilyName}} - - -3. - /
 -Date of marriageDate du mariage - -{{eventDate}} - - -4. - /
 -Place of marriageLieu de mariage - - - {{location districtPlaceofmarriageId 'name'}}{{internationalDistrictPlaceofmarriage}}, - {{location statePlaceofmarriageId 'name'}}{{internationalStatePlaceofmarriage}}, {{countryPlaceofmarriage}} - - - - -5. -Witnesses / Les témoins - -{{witnessOneFirstName}} {{witnessOneFamilyName}}
{{witnessTwoFirstName}} {{witnessTwoFamilyName}} - - - -6. -Lieu d'enregistrement - -Place of registration / - -{{location registrar.officeId 'name'}}
{{location registrar.districtId 'name'}}, {{location registrar.stateId 'name'}}, Farajaland - - -7. - -Date of registration / -Date d'enregistrement - -{{registrationDate}} - - -8. -/
 -Registered by Enregistré par - -{{registrar.name}} - - - -9. -Signatures of bride and groom / Signatures des mariés - - -Groom / Marié - - -Bride / Mariée - - - - -No. {{registrationNumber}} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -{{#ifCond printInAdvance '!==' true}}{{/ifCond}} - - - - - diff --git a/src/data-seeding/employees/source/default-employees.csv b/src/data-seeding/employees/source/default-employees.csv index aa77561c8..1888c3a03 100644 --- a/src/data-seeding/employees/source/default-employees.csv +++ b/src/data-seeding/employees/source/default-employees.csv @@ -1,12 +1,12 @@ primaryOfficeId,givenNames,familyName,systemRole,role,mobile,username,email,password -CRVS_OFFICE_JWMRGwDBXK,Kalusha,Bwalya,FIELD_AGENT,Social Worker,0911111111,k.bwalya,kalushabwalya17@gmail.com,test -CRVS_OFFICE_JWMRGwDBXK,Felix,Katongo,REGISTRATION_AGENT,Registration Agent,0922222222,f.katongo,kalushabwalya17+@gmail.com,test -CRVS_OFFICE_JWMRGwDBXK,Kennedy,Mweene,LOCAL_REGISTRAR,Local Registrar,0933333333,k.mweene,kalushabwalya1.7@gmail.com,test -CRVS_OFFICE_JWMRGwDBXK,Emmanuel,Mayuka,LOCAL_SYSTEM_ADMIN,Local System Admin,0921681112,e.mayuka,kalushabwalya.17@gmail.com,test -CRVS_OFFICE_2OKicPQMNI,Jonathan,Campbell,NATIONAL_SYSTEM_ADMIN,National System Admin,0921111111,j.campbell,kalushabwaly.a17@gmail.com,test -CRVS_OFFICE_okQp4uKCz0,Patrick,Gondwe,FIELD_AGENT,Local Leader,0912121212,p.gondwe,kalushabwal.ya17@gmail.com,test -CRVS_OFFICE_okQp4uKCz0,Joshua,Mutale,REGISTRATION_AGENT,Registration Agent,0923232323,j.mutale,kalushabwa.lya17@gmail.com,test -CRVS_OFFICE_okQp4uKCz0,Derrick,Bulaya,LOCAL_REGISTRAR,Local Registrar,0934343434,d.bulaya,kalushabw.alya17@gmail.com,test -CRVS_OFFICE_okQp4uKCz0,Alex,Ngonga,LOCAL_SYSTEM_ADMIN,Local System Admin,0978787878,a.ngonga,kalushab.walya17@gmail.com,test -CRVS_OFFICE_2OKicPQMNI,Edgar,Kazembe,PERFORMANCE_MANAGEMENT,Performance Manager,0977777777,e.kazembe,kalusha.bwalya17@gmail.com,test -CRVS_OFFICE_2OKicPQMNI,Joseph,Musonda,NATIONAL_REGISTRAR,National Registrar,0915151515,j.musonda,kalush.abwalya17@gmail.com,test +CRVS_OFFICE_JWMRGwDBXK,Kalusha,Bwalya,FIELD_AGENT,Social Worker,+260911111111,k.bwalya,kalushabwalya17@gmail.com,test +CRVS_OFFICE_JWMRGwDBXK,Felix,Katongo,REGISTRATION_AGENT,Registration Agent,+260922222222,f.katongo,kalushabwalya17+@gmail.com,test +CRVS_OFFICE_JWMRGwDBXK,Kennedy,Mweene,LOCAL_REGISTRAR,Local Registrar,+260933333333,k.mweene,kalushabwalya1.7@gmail.com,test +CRVS_OFFICE_JWMRGwDBXK,Emmanuel,Mayuka,LOCAL_SYSTEM_ADMIN,Local System Admin,+260921681112,e.mayuka,kalushabwalya.17@gmail.com,test +CRVS_OFFICE_2OKicPQMNI,Jonathan,Campbell,NATIONAL_SYSTEM_ADMIN,National System Admin,+260921111111,j.campbell,kalushabwaly.a17@gmail.com,test +CRVS_OFFICE_okQp4uKCz0,Patrick,Gondwe,FIELD_AGENT,Local Leader,+260912121212,p.gondwe,kalushabwal.ya17@gmail.com,test +CRVS_OFFICE_okQp4uKCz0,Joshua,Mutale,REGISTRATION_AGENT,Registration Agent,+260923232323,j.mutale,kalushabwa.lya17@gmail.com,test +CRVS_OFFICE_okQp4uKCz0,Derrick,Bulaya,LOCAL_REGISTRAR,Local Registrar,+260934343434,d.bulaya,kalushabw.alya17@gmail.com,test +CRVS_OFFICE_okQp4uKCz0,Alex,Ngonga,LOCAL_SYSTEM_ADMIN,Local System Admin,+260978787878,a.ngonga,kalushab.walya17@gmail.com,test +CRVS_OFFICE_2OKicPQMNI,Edgar,Kazembe,PERFORMANCE_MANAGEMENT,Performance Manager,+260977777777,e.kazembe,kalusha.bwalya17@gmail.com,test +CRVS_OFFICE_2OKicPQMNI,Joseph,Musonda,NATIONAL_REGISTRAR,National Registrar,+260915151515,j.musonda,kalush.abwalya17@gmail.com,test diff --git a/src/form/addresses/address-fields.ts b/src/form/addresses/address-fields.ts index b37cc1e31..17ab505ae 100644 --- a/src/form/addresses/address-fields.ts +++ b/src/form/addresses/address-fields.ts @@ -72,11 +72,13 @@ export function getAddressLocationSelect({ location, useCase, fhirLineArrayPosition, - isLowestAdministrativeLevel + isLowestAdministrativeLevel, + initialValue }: { section: string location: string useCase: string + initialValue: string /** Position where the location gets mapped into within a fhir.Address line-array */ fhirLineArrayPosition?: number /** If the structure the smallest possible level. Allows saving fhir.Address.partOf */ @@ -97,7 +99,7 @@ export function getAddressLocationSelect({ ? useCase : `${useCase}Address`, required: true, - initialValue: '', + initialValue, validator: [], placeholder: { defaultMessage: 'Select', @@ -106,8 +108,7 @@ export function getAddressLocationSelect({ }, dynamicOptions: { resource: 'locations', - dependency: getDependency(location, useCase, section), - initialValue: 'agentDefault' + dependency: getDependency(location, useCase, section) }, conditionals: isUseCaseForPlaceOfEvent(useCase) ? getPlaceOfEventConditionals( @@ -132,7 +133,8 @@ export function getAddressLocationSelect({ // We recommend that you do not edit this function function getAdminLevelSelects( section: string, - useCase: string + useCase: string, + addressHierarchy: string[] ): SerializedFormField[] { switch (ADMIN_LEVELS) { case 1: @@ -141,71 +143,114 @@ function getAdminLevelSelects( section, location: 'state', useCase, - isLowestAdministrativeLevel: true + isLowestAdministrativeLevel: true, + initialValue: addressHierarchy[0] }) ] case 2: return [ - getAddressLocationSelect({ section, location: 'state', useCase }), + getAddressLocationSelect({ + section, + location: 'state', + useCase, + initialValue: addressHierarchy[0] + }), getAddressLocationSelect({ section, location: 'district', useCase, - isLowestAdministrativeLevel: true + isLowestAdministrativeLevel: true, + initialValue: addressHierarchy[1] }) ] case 3: return [ - getAddressLocationSelect({ section, location: 'state', useCase }), - getAddressLocationSelect({ section, location: 'district', useCase }), + getAddressLocationSelect({ + section, + location: 'state', + useCase, + initialValue: addressHierarchy[0] + }), + getAddressLocationSelect({ + section, + location: 'district', + useCase, + initialValue: addressHierarchy[1] + }), getAddressLocationSelect({ section, location: 'locationLevel3', useCase, fhirLineArrayPosition: 10, - isLowestAdministrativeLevel: true + isLowestAdministrativeLevel: true, + initialValue: addressHierarchy[2] }) ] case 4: return [ - getAddressLocationSelect({ section, location: 'state', useCase }), - getAddressLocationSelect({ section, location: 'district', useCase }), + getAddressLocationSelect({ + section, + location: 'state', + useCase, + initialValue: addressHierarchy[0] + }), + getAddressLocationSelect({ + section, + location: 'district', + useCase, + initialValue: addressHierarchy[1] + }), getAddressLocationSelect({ section, location: 'locationLevel3', useCase, - fhirLineArrayPosition: 10 + fhirLineArrayPosition: 10, + initialValue: addressHierarchy[2] }), getAddressLocationSelect({ section, location: 'locationLevel4', useCase, fhirLineArrayPosition: 11, - isLowestAdministrativeLevel: true + isLowestAdministrativeLevel: true, + initialValue: addressHierarchy[3] }) ] case 5: return [ - getAddressLocationSelect({ section, location: 'state', useCase }), - getAddressLocationSelect({ section, location: 'district', useCase }), + getAddressLocationSelect({ + section, + location: 'state', + useCase, + initialValue: addressHierarchy[0] + }), + getAddressLocationSelect({ + section, + location: 'district', + useCase, + initialValue: addressHierarchy[1] + }), getAddressLocationSelect({ section, location: 'locationLevel3', useCase, - fhirLineArrayPosition: 10 + fhirLineArrayPosition: 10, + initialValue: addressHierarchy[2] }), getAddressLocationSelect({ section, location: 'locationLevel4', useCase, - fhirLineArrayPosition: 11 + fhirLineArrayPosition: 11, + initialValue: addressHierarchy[3] }), getAddressLocationSelect({ section, location: 'locationLevel5', useCase, fhirLineArrayPosition: 12, - isLowestAdministrativeLevel: true + isLowestAdministrativeLevel: true, + initialValue: addressHierarchy[4] }) ] } @@ -239,7 +284,8 @@ function getPlaceOfEventFields(useCase: EventLocationAddressCases) { // ==================================== END WARNING ==================================== export function getAddressFields( section: string, - addressCase: EventLocationAddressCases | AddressCases + addressCase: EventLocationAddressCases | AddressCases, + addressHierarchy: string[] ): SerializedFormField[] { let useCase = addressCase as string let placeOfEventFields: SerializedFormField[] = [] @@ -287,7 +333,7 @@ export function getAddressFields( }) }, // Required // Select fields are added for each administrative location level from Humdata - ...getAdminLevelSelects(section, useCase), // Required + ...getAdminLevelSelects(section, useCase, addressHierarchy), // Required { name: `city${sentenceCase(useCase)}${sentenceCase(section)}`, type: 'TEXT', diff --git a/src/form/addresses/index.ts b/src/form/addresses/index.ts index 97bee6497..6576f0015 100644 --- a/src/form/addresses/index.ts +++ b/src/form/addresses/index.ts @@ -62,7 +62,7 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ { // INFORMANT ADDRESS FIELDS precedingFieldId: - 'birth.informant.informant-view-group.informant-nid-seperator', + 'birth.informant.informant-view-group.informantBirthRegistrationNumber', configurations: [ { config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, @@ -93,7 +93,8 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ }, { // MOTHER ADDRESS FIELDS - precedingFieldId: 'birth.mother.mother-view-group.mother-nid-seperator', + precedingFieldId: + 'birth.mother.mother-view-group.motherBirthRegistrationNumber', configurations: [ { config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, @@ -117,7 +118,8 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ }, { // FATHER ADDRESS FIELDS - precedingFieldId: 'birth.father.father-view-group.father-nid-seperator', + precedingFieldId: + 'birth.father.father-view-group.fatherBirthRegistrationNumber', configurations: [ { config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, @@ -266,7 +268,8 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ },*/ { // SPOUSE ADDRESS FIELDS - precedingFieldId: 'death.spouse.spouse-view-group.spouse-nid-seperator', + precedingFieldId: + 'death.spouse.spouse-view-group.spouseBirthRegistrationNumber', configurations: [ { config: AddressSubsections.PRIMARY_ADDRESS_SUBSECTION, @@ -301,7 +304,7 @@ export const defaultAddressConfiguration: IAddressConfiguration[] = [ { // PLACE OF MARRIAGE ADDRESS FIELDS precedingFieldId: - 'marriage.marriageEvent.marriage-event-details.place-of-marriage-seperator', + 'marriage.marriageEvent.marriage-event-details.placeOfMarriageTitle', configurations: [{ config: EventLocationAddressCases.PLACE_OF_MARRIAGE }] }, { diff --git a/src/form/birth/index.ts b/src/form/birth/index.ts index fb24a1bd6..3cbd0093c 100644 --- a/src/form/birth/index.ts +++ b/src/form/birth/index.ts @@ -69,7 +69,12 @@ import { exactDateOfBirthUnknownConditional, hideIfNidIntegrationEnabled } from '../common/default-validation-conditionals' -import { documentsSection, registrationSection } from './required-sections' +import { + documentsSection, + registrationSection, + previewSection, + reviewSection +} from './required-sections' import { certificateHandlebars } from './certificate-handlebars' import { getSectionMapping } from '@countryconfig/utils/mapping/section/birth/mapping-utils' import { getCommonSectionMapping } from '@countryconfig/utils/mapping/field-mapping-utils' @@ -269,13 +274,6 @@ export const birthForm: ISerializedForm = { hideIfNidIntegrationEnabled.concat(hideIfInformantMotherOrFather), true ), - // preceding field of address fields - divider('informant-nid-seperator', [ - { - action: 'hide', - expression: informantNotMotherOrFather - } - ]), // ADDRESS FIELDS WILL RENDER HERE divider('informant-address-seperator', [ { @@ -348,8 +346,6 @@ export const birthForm: ISerializedForm = { hideIfNidIntegrationEnabled.concat(detailsExist), true ), - // preceding field of address fields - divider('mother-nid-seperator', detailsExist), // ADDRESS FIELDS WILL RENDER HERE divider('mother-address-seperator', detailsExist), getMaritalStatus(certificateHandlebars.motherMaritalStatus, [ @@ -437,8 +433,6 @@ export const birthForm: ISerializedForm = { hideIfNidIntegrationEnabled.concat(detailsExist), true ), - // preceding field of address fields - divider('father-nid-seperator', detailsExist), // ADDRESS FIELDS WILL RENDER HERE divider('father-address-seperator', detailsExist), getMaritalStatus(certificateHandlebars.fatherMaritalStatus, [ @@ -460,6 +454,8 @@ export const birthForm: ISerializedForm = { ], mapping: getSectionMapping('father') }, - documentsSection // REQUIRED SECTION FOR DOCUMENT ATTACHMENTS + documentsSection, // REQUIRED SECTION FOR DOCUMENT ATTACHMENTS + previewSection, // REQUIRED SECTION TO PREVIEW DECLARATION BEFORE SUBMIT + reviewSection // REQUIRED SECTION TO REVIEW SUBMITTED DECLARATION ] } diff --git a/src/form/birth/optional-fields.ts b/src/form/birth/optional-fields.ts index dddd1a421..38df50af2 100644 --- a/src/form/birth/optional-fields.ts +++ b/src/form/birth/optional-fields.ts @@ -61,12 +61,8 @@ export const weightAtBirth: SerializedFormField = { parameters: [0, 6] } ], - postfix: 'Kg', - mapping: getFieldMapping( - 'weightAtBirth', - certificateHandlebars.weightAtBirth - ), - inputFieldWidth: '78px' + postfix: 'kilograms (kg)', + mapping: getFieldMapping('weightAtBirth', certificateHandlebars.weightAtBirth) } export const multipleBirth: SerializedFormField = { @@ -94,9 +90,5 @@ export const multipleBirth: SerializedFormField = { parameters: [2] } ], - mapping: getFieldMapping( - 'multipleBirth', - certificateHandlebars.multipleBirth - ), - inputFieldWidth: '64px' + mapping: getFieldMapping('multipleBirth', certificateHandlebars.multipleBirth) } diff --git a/src/form/birth/required-sections.ts b/src/form/birth/required-sections.ts index 771ff05ba..a968430b8 100644 --- a/src/form/birth/required-sections.ts +++ b/src/form/birth/required-sections.ts @@ -2,6 +2,7 @@ import { getSectionMapping } from '@countryconfig/utils/mapping/section/birth/ma import { formMessageDescriptors } from '../common/messages' import { ISerializedFormSection } from '../types/types' import { getFieldMapping } from '@countryconfig/utils/mapping/field-mapping-utils' +import { informantsSignature } from '../common/common-optional-fields' export const registrationSection = { id: 'registration', // A hidden 'registration' section must be included to store identifiers in a form draft that are used in certificates @@ -208,4 +209,30 @@ export const documentsSection = { ] } ] -} as ISerializedFormSection +} satisfies ISerializedFormSection + +export const previewSection = { + id: 'preview', + viewType: 'preview', + name: formMessageDescriptors.previewName, + title: formMessageDescriptors.previewTitle, + groups: [ + { + id: 'preview-view-group', + fields: [informantsSignature] + } + ] +} satisfies ISerializedFormSection + +export const reviewSection = { + id: 'review', + viewType: 'review', + name: formMessageDescriptors.reviewName, + title: formMessageDescriptors.reviewTitle, + groups: [ + { + id: 'review-view-group', + fields: [informantsSignature] + } + ] +} satisfies ISerializedFormSection diff --git a/src/form/common/common-optional-fields.ts b/src/form/common/common-optional-fields.ts index d37f8ff84..3d78ff4e2 100644 --- a/src/form/common/common-optional-fields.ts +++ b/src/form/common/common-optional-fields.ts @@ -66,7 +66,6 @@ export const getAgeOfIndividualInYears = ( validator: validators, conditionals, postfix: 'years', - inputFieldWidth: '78px', ...(certificateHandlebar && { mapping: getFieldMapping('ageOfIndividualInYears', certificateHandlebar) }) @@ -200,3 +199,25 @@ export const getEducation = ( options: educationalAttainmentOptions, mapping: getFieldMapping('educationalAttainment', certificateHandlebar) }) + +export const informantsSignature = { + name: 'informantSignature', + label: { + defaultMessage: 'Signature of informant', + description: 'Label for informants signature input', + id: 'review.inputs.informantsSignature' + }, + validator: [], + type: 'SIGNATURE', + allowedFileFormats: ['image/png', 'image/svg'], + mapping: { + mutation: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'informantsSignature'] + }, + query: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'informantsSignature'] + } + } +} satisfies SerializedFormField diff --git a/src/form/common/messages.ts b/src/form/common/messages.ts index 8ffafad8d..17c2684a3 100644 --- a/src/form/common/messages.ts +++ b/src/form/common/messages.ts @@ -326,6 +326,26 @@ export const formMessageDescriptors = { description: 'Label for form field: Nationality', id: 'form.field.label.nationality' }, + previewName: { + defaultMessage: 'Preview', + description: 'Form section name for Preview', + id: 'register.form.section.preview.name' + }, + previewTitle: { + defaultMessage: 'Preview', + description: 'Form section title for Preview', + id: 'register.form.section.preview.title' + }, + reviewName: { + defaultMessage: 'Review', + description: 'Form section name for Review', + id: 'review.form.section.review.name' + }, + reviewTitle: { + defaultMessage: 'Review', + description: 'Form section title for Review', + id: 'review.form.section.review.title' + }, placeOfBirthPreview: { defaultMessage: 'Place of delivery', description: 'Title for place of birth sub section', diff --git a/src/form/death/custom-fields.ts b/src/form/death/custom-fields.ts index 2b3add283..1d08e2e86 100644 --- a/src/form/death/custom-fields.ts +++ b/src/form/death/custom-fields.ts @@ -31,7 +31,6 @@ export function getNumberOfDependants(): SerializedFormField { initialValue: '', validator: [], mapping: getCustomFieldMapping(fieldId), - conditionals: [], - inputFieldWidth: '64px' + conditionals: [] } } diff --git a/src/form/death/index.ts b/src/form/death/index.ts index 454568e65..9883423cf 100644 --- a/src/form/death/index.ts +++ b/src/form/death/index.ts @@ -64,7 +64,12 @@ import { hideIfInformantSpouse, hideIfNidIntegrationEnabled } from '../common/default-validation-conditionals' -import { documentsSection, registrationSection } from './required-sections' +import { + documentsSection, + previewSection, + registrationSection, + reviewSection +} from './required-sections' import { deceasedNameInEnglish, informantNameInEnglish /*, @@ -359,8 +364,6 @@ export const deathForm = { ), getIDType('death', 'spouse', detailsExist, true), ...getIDNumberFields('spouse', detailsExist, true), - // preceding field of address fields - divider('spouse-nid-seperator', detailsExist), // ADDRESS FIELDS WILL RENDER HERE divider('spouse-address-separator') ], @@ -509,6 +512,8 @@ export const deathForm = { ], mapping: getSectionMapping('father') },*/ - documentsSection + documentsSection, + previewSection, + reviewSection ] } satisfies ISerializedForm diff --git a/src/form/death/required-sections.ts b/src/form/death/required-sections.ts index eeabd9930..5a7fbea52 100644 --- a/src/form/death/required-sections.ts +++ b/src/form/death/required-sections.ts @@ -2,6 +2,7 @@ import { getSectionMapping } from '@countryconfig/utils/mapping/section/death/ma import { formMessageDescriptors } from '../common/messages' import { ISerializedFormSection } from '../types/types' import { getFieldMapping } from '@countryconfig/utils/mapping/field-mapping-utils' +import { informantsSignature } from '../common/common-optional-fields' export const registrationSection = { id: 'registration', @@ -178,3 +179,29 @@ export const documentsSection = { } ] } satisfies ISerializedFormSection + +export const previewSection = { + id: 'preview', + viewType: 'preview', + name: formMessageDescriptors.previewName, + title: formMessageDescriptors.previewTitle, + groups: [ + { + id: 'preview-view-group', + fields: [informantsSignature] + } + ] +} satisfies ISerializedFormSection + +export const reviewSection = { + id: 'review', + viewType: 'review', + name: formMessageDescriptors.reviewName, + title: formMessageDescriptors.reviewTitle, + groups: [ + { + id: 'review-view-group', + fields: [informantsSignature] + } + ] +} satisfies ISerializedFormSection diff --git a/src/form/index.ts b/src/form/index.ts index 1dc89b8ab..51323c305 100644 --- a/src/form/index.ts +++ b/src/form/index.ts @@ -8,14 +8,19 @@ * * Copyright (C) The OpenCRVS Authors located at https://github.com/opencrvs/opencrvs-core/blob/master/AUTHORS. */ - +import { Request } from '@hapi/hapi' import { decorateFormsWithAddresses } from '../utils/address-utils' import { birthForm } from './birth' import { deathForm } from './death' import { marriageForm } from './marriage' import { IForms, Event } from './types/types' +import { fetchUserLocationHierarchy } from '@countryconfig/utils/users' -export async function formHandler(): Promise { +export async function formHandler(req: Request): Promise { + const addressHierarchy = await fetchUserLocationHierarchy( + req.headers.authorization, + req.auth.credentials.sub as string + ) // ====================== NOTE REGARDING MIGRATING FROM OPNCRVS v1.2 OR EARLIER ====================== // SIMPLY RETURN A JSON OF YOUR FULL FORM HERE, WITH THE ADDITION OF THE NEW MARRIAGE AND VERSION PROP @@ -51,8 +56,12 @@ export async function formHandler(): Promise { // THIS DECORATOR FUNCTION POPULATES ADDRESSES ACCORDING TO THE defaultAddressConfiguration in address-settings.ts // SO YOU ONLY NEED TO CONFIGURE ADDRESS FIELDS IN A SINGLE LOCATION FOR ALL DECORATED INSTANCES. - birth: decorateFormsWithAddresses(birthForm, Event.Birth), - death: decorateFormsWithAddresses(deathForm, Event.Death), - marriage: decorateFormsWithAddresses(marriageForm, Event.Marriage) + birth: decorateFormsWithAddresses(birthForm, Event.Birth, addressHierarchy), + death: decorateFormsWithAddresses(deathForm, Event.Death, addressHierarchy), + marriage: decorateFormsWithAddresses( + marriageForm, + Event.Marriage, + addressHierarchy + ) } } diff --git a/src/form/marriage/index.ts b/src/form/marriage/index.ts index 7fc51ef6f..1892e2dff 100644 --- a/src/form/marriage/index.ts +++ b/src/form/marriage/index.ts @@ -48,7 +48,12 @@ import { hideIfInformantBrideOrGroom, brideOrGroomBirthDateValidators } from '../common/default-validation-conditionals' -import { documentsSection, registrationSection } from './required-sections' +import { + documentsSection, + previewSection, + registrationSection, + reviewSection +} from './required-sections' import { brideNameInEnglish, groomNameInEnglish, @@ -259,8 +264,7 @@ export const marriageForm: ISerializedForm = { fields: [ getMarriageDate, // Required field getTypeOfMarriage, - placeOfMarriageSubsection, - divider('place-of-marriage-seperator') + placeOfMarriageSubsection // PLACE OF MARRIAGE FIELDS WILL RENDER HERE ] } @@ -320,6 +324,8 @@ export const marriageForm: ISerializedForm = { ], mapping: getCommonSectionMapping('informant') }, - documentsSection + documentsSection, + previewSection, + reviewSection ] } diff --git a/src/form/marriage/required-sections.ts b/src/form/marriage/required-sections.ts index 78123172b..358b1f58c 100644 --- a/src/form/marriage/required-sections.ts +++ b/src/form/marriage/required-sections.ts @@ -1,7 +1,11 @@ import { getSectionMapping } from '@countryconfig/utils/mapping/section/marriage/mapping-utils' import { getInformantConditionalForMarriageDocUpload } from '../common/default-validation-conditionals' import { formMessageDescriptors } from '../common/messages' -import { ISelectOption, ISerializedFormSection } from '../types/types' +import { + ISelectOption, + ISerializedFormSection, + SerializedFormField +} from '../types/types' import { getDocUploaderForMarriage } from './required-fields' export const registrationSection = { @@ -100,3 +104,127 @@ export const documentsSection = { } ] } as ISerializedFormSection + +/* + * In this reference configuration the signature + * fields for both the preview & review section are same + * but they can potentially be different e.g. it could be + * made such that the signatures are only required when + * registering a submitted declaration + */ +const signatureFields = [ + { + name: 'brideSignature', + label: { + defaultMessage: 'Signature of Bride', + description: "Label for bride's signature input", + id: 'review.inputs.brideSignature' + }, + required: true, + validator: [], + type: 'SIGNATURE', + allowedFileFormats: ['image/png'], + mapping: { + mutation: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'brideSignature'] + }, + query: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'brideSignature'] + } + } + }, + { + name: 'groomSignature', + label: { + defaultMessage: 'Signature of groom', + description: "Label for groom's signature input", + id: 'review.inputs.groomSignature' + }, + required: true, + validator: [], + type: 'SIGNATURE', + allowedFileFormats: ['image/png'], + mapping: { + mutation: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'groomSignature'] + }, + query: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'groomSignature'] + } + } + }, + { + name: 'witnessOneSignature', + label: { + defaultMessage: 'Signature of witnessOne', + description: "Label for witnessOne's signature input", + id: 'review.inputs.witnessOneSignature' + }, + required: true, + validator: [], + type: 'SIGNATURE', + allowedFileFormats: ['image/png'], + mapping: { + mutation: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'witnessOneSignature'] + }, + query: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'witnessOneSignature'] + } + } + }, + { + name: 'witnessTwoSignature', + label: { + defaultMessage: 'Signature of witnessTwo', + description: "Label for witnessTwo's signature input", + id: 'review.inputs.witnessTwoSignature' + }, + required: true, + validator: [], + type: 'SIGNATURE', + allowedFileFormats: ['image/png'], + mapping: { + mutation: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'witnessTwoSignature'] + }, + query: { + operation: 'fieldValueSectionExchangeTransformer', + parameters: ['registration', 'witnessTwoSignature'] + } + } + } +] satisfies SerializedFormField[] + +export const previewSection = { + id: 'preview', + viewType: 'preview', + name: formMessageDescriptors.previewName, + title: formMessageDescriptors.previewTitle, + groups: [ + { + id: 'preview-view-group', + fields: signatureFields + } + ] +} satisfies ISerializedFormSection + +export const reviewSection = { + id: 'review', + viewType: 'review', + name: formMessageDescriptors.reviewName, + title: formMessageDescriptors.reviewTitle, + groups: [ + { + id: 'review-view-group', + fields: signatureFields + } + ] +} satisfies ISerializedFormSection diff --git a/src/form/types/types.ts b/src/form/types/types.ts index a7fbbbc1e..338999849 100644 --- a/src/form/types/types.ts +++ b/src/form/types/types.ts @@ -141,6 +141,8 @@ export const TIME = 'TIME' export const NID_VERIFICATION_BUTTON = 'NID_VERIFICATION_BUTTON' export const DIVIDER = 'DIVIDER' export const HEADING3 = 'HEADING3' +export const SIGNATURE = 'SIGNATURE' + export enum RadioSize { LARGE = 'large', NORMAL = 'normal' @@ -346,7 +348,6 @@ export interface INumberFormField extends IFormFieldBase { type: typeof NUMBER step?: number max?: number - inputFieldWidth?: string inputWidth?: number } export interface IBigNumberFormField extends IFormFieldBase { @@ -412,6 +413,7 @@ export interface IImageUploaderWithOptionsFormField extends IFormFieldBase { export interface IDocumentUploaderWithOptionsFormField extends IFormFieldBase { type: typeof DOCUMENT_UPLOADER_WITH_OPTION options: ISelectOption[] + optionCondition?: string hideOnEmptyOption?: boolean compressImagesToSizeMB?: number maxSizeMB?: number @@ -482,6 +484,17 @@ export interface IHeading3Field extends IFormFieldBase { type: typeof HEADING3 } +export interface ISignatureFormField extends IFormFieldBase { + type: typeof SIGNATURE + maxSizeMb?: number + allowedFileFormats?: ( + | 'image/png' + | 'image/jpg' + | 'image/jpeg' + | 'image/svg' + )[] +} + export type IFormField = | ITextFormField | ITelFormField @@ -514,6 +527,7 @@ export type IFormField = | INidVerificationButton | IDividerField | IHeading3Field + | ISignatureFormField export interface SelectComponentOption { value: string @@ -529,7 +543,6 @@ export interface IDynamicOptions { jurisdictionType?: string resource?: string options?: { [key: string]: ISelectOption[] } - initialValue?: string } export type IFormFieldTemplateMapOperation = diff --git a/src/index.ts b/src/index.ts index c7ea2459b..c8ddb8f32 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ require('app-module-path').addPath(require('path').join(__dirname)) require('dotenv').config() import fetch from 'node-fetch' +import path from 'path' import * as Hapi from '@hapi/hapi' import * as Pino from 'hapi-pino' import * as JWT from 'hapi-auth-jwt2' @@ -48,18 +49,19 @@ import { ErrorContext } from 'hapi-auth-jwt2' import { mapGeojsonHandler } from '@countryconfig/api/dashboards/handler' import { formHandler } from '@countryconfig/form' import { locationsHandler } from './data-seeding/locations/handler' -import { certificateHandler } from './data-seeding/certificates/handler' +import { certificateHandler } from './api/certificates/handler' import { rolesHandler } from './data-seeding/roles/handler' import { usersHandler } from './data-seeding/employees/handler' import { applicationConfigHandler } from './api/application/handler' import { validatorsHandler } from './form/common/custom-validation-conditionals/validators-handler' import { conditionalsHandler } from './form/common/custom-validation-conditionals/conditionals-handler' -import { COUNTRY_WIDE_CRUDE_DEATH_RATE } from './api/application/application-config-default' +import { COUNTRY_WIDE_CRUDE_DEATH_RATE } from './api/application/application-config' import { handlebarsHandler } from './form/common/certificate/handlebars/handler' import { trackingIDHandler } from './api/tracking-id/handler' import { dashboardQueriesHandler } from './api/dashboards/handler' import { fontsHandler } from './api/fonts/handler' import { certificateConfigurationHandler } from './api/certificate-configuration/handler' +import { recordNotificationHandler } from './api/record-notification/handler' export interface ITokenPayload { sub: string @@ -237,18 +239,15 @@ export async function createServer() { server.auth.default('jwt') - if (process.env.NODE_ENV !== 'production') { - server.route({ - method: 'GET', - path: '/certificates/{event}.svg', - handler: certificateHandler, - options: { - auth: false, - tags: ['api', 'certificates'], - description: 'Returns only one certificate metadata' - } - }) - } + server.route({ + method: 'GET', + path: '/certificates/{event}.svg', + handler: certificateHandler, + options: { + tags: ['api', 'certificates'], + description: 'Returns only one certificate metadata' + } + }) // add ping route by default for health check server.route({ method: 'GET', @@ -489,16 +488,6 @@ export async function createServer() { } }) - server.route({ - method: 'GET', - path: '/certificates', - handler: certificateHandler, - options: { - tags: ['api', 'certificates'], - description: 'Returns certificate metadata' - } - }) - server.route({ method: 'GET', path: '/roles', @@ -529,6 +518,33 @@ export async function createServer() { } }) + server.route({ + method: 'GET', + path: '/static/{param*}', + handler: { + directory: { + path: path.join(__dirname, 'client-static'), + redirectToSlash: true, + index: false + } + }, + options: { + auth: false, + tags: ['api', 'static'], + description: 'Server static files for client' + } + }) + + server.route({ + method: 'GET', + path: '/record-notification', + handler: recordNotificationHandler, + options: { + tags: ['api'], + description: 'Checks for enabled notification for record' + } + }) + server.ext({ type: 'onRequest', method(request: Hapi.Request & { sentryScope?: any }, h) { diff --git a/src/translations/client.csv b/src/translations/client.csv index 525186ad2..06c51c816 100644 --- a/src/translations/client.csv +++ b/src/translations/client.csv @@ -156,134 +156,23 @@ changeEmail.validation.msg,Phone number validation message,Must be a valid email changePhone.validation.msg,Phone number validation message,Must be a valid 10 digit number that starts with 0,Doit être un numéro valide à {num} chiffres qui commence par {start}. config.advanced.search,This is used for the advanced search,Advanced Search,Recherche avancée config.advanced.search.instruction,This is used for the advanced search,Select the options to build an advanced search. A minimum of two search parameters is required.,Sélectionnez les options pour construire une recherche avancée. Un minimum de deux paramètres de recherche est requis. -config.application.applicationNameChangeNotification,Message for application name change notification,Name of application updated,Nom de l'application mise à jour -config.application.applicationNameLabel,Application name config label,Name of application,Nom de l'application -config.application.backgroundImageChangeNotification,Message for background image change notification,Background image updated,Mise à jour de l'image de fond -config.application.backgroundImageError,Error message for background image change,Unable to change image. Please try again.,Impossible de modifier l'image. Veuillez réessayer. -config.application.backgroundImageFileLimitError,Error message for large Background file,Background image file must be less than 2mb,Le fichier de l'image d'arrière-plan doit être inférieur à 2 Mo -config.application.birthDelayedDialogTitle,Delayed dialog title for brith,Delayed registration time period for birth registration,Délai d'enregistrement retardé pour l'enregistrement des naissances -config.application.birthDelayedFeeChangeNotification,Message for application birth delayed fee change notification,Birth delayed fee updated,Mise à jour de la pénalité de déclaration tardive des naissances -config.application.birthLateFeeChangeNotification,Message for application birth late fee change notification,Birth late fee updated,Mise à jour de la pénalité de déclaration tardive des naissances -config.application.birthLateRegTargetChangeNotification,Message for application birth late registration target change notification,Birth late registration target days updated,Mise à jour des jours cibles d'enregistrement tardif des naissances -config.application.birthLegallySpecifiedDialogTitle,Legally specified dialog title for brith,Legally specified time period for birth registration,Délai légal pour déclaration des naissances -config.application.birthOnTimeFeeChangeNotification,Message for application birth on time fee change notification,Birth on time fee updated,Mise à jour des frais de naissance à temps -config.application.birthRegTargetChangeNotification,Message for application birth registration target change notification,Birth registration target days updated,Mise à jour des jours cibles pour l'enregistrement des naissances config.application.birthTabTitle,The title for birth tab,Birth,Naissance config.application.birthTabTitleExport,The title for birth tab for VSExport,Births,Naissances -config.application.colourTabText,The title for colour tab text,Hex code,Code hexadécimal -config.application.colourTabTitle,The title for colour tab,Colour,Couleur -config.application.configChangeError,Error message for application config change,Unable to make change. Please try again,Impossible d'effectuer la modification. Veuillez réessayer -config.application.currencyChangeMessage,Message for application currency change modal,Select your currency for your CRVS system,Selectionnez la devise -config.application.currencyChangeNotification,Message for application currency change notification,Currency updated,Devise mise à jour -config.application.currencyLabel,Currency config label,Currency,Devise -config.application.deathDelayedFeeChangeNotification,Message for application death delayed fee change notification,Death delayed fee updated,Mise à jour de la pénalité de retard déclaration du décès -config.application.deathLegallySpecifiedDialogTitle,Legally specified dialog title for death,Legally specified time period for death registration,Délais légal de déclaration du décès -config.application.deathOnTimeFeeChangeNotification,Message for application death on time fee change notification,Death on time fee updated,Mise à jour des frais de déclaration de décès dans le délais legal -config.application.deathRegTargetChangeNotification,Message for application death registration target change notification,Death registration target days updated,Mise à jour des jours cibles de déclaration des décès config.application.deathTabTitle,The title for death tab,Death,Décès config.application.deathTabTitleExport,The title for death tab for VSExport,Deaths,Décès -config.application.delayedFeeDialogTitle,Delayed fee dialog title,Registration fees for delayed registrations,Frais pour les declarations tardives -config.application.delayedRegistrationLabel,Delayed registration config label,Delayed registration,Enregistrement retardé -config.application.delayedRegistrationValue,Delayed registration config value,After {lateTime} days,Après {lateTime} jours config.application.emptystate,Vital Statistics Export Empty State Text,The previous month's vital statistics data (based on vital event registrations occurring within that month) will become available for you to export as of the 1st of every month. Large CSV files cannot be opened in Excel and should therefore be opened in a statistical program such as {posit}.,Les données statistiques vitales du mois précédent (basées sur les enregistrements d'événements vitaux survenus au cours de ce mois) seront disponibles pour l'exportation à partir du 1er de chaque mois. Les grands fichiers CSV ne peuvent pas être ouverts dans Excel et doivent donc être ouverts dans un programme statistique tel que {posit}. -config.application.eventTargetInputLabel,The label for event target label,days,jours -config.application.example,Label for Example,Example,Exemple config.application.export,Download Export CSV,Export,Export -config.application.generalTabTitle,The title for general tab,General,Général -config.application.govermentLogoLabel,Government logo config label,Goverment logo,Logo du gouvernement -config.application.govtLogoChangeError,Error message for country logo change,Unable to change logo. Please try again.,Impossible de modifier le logo. Veuillez réessayer. -config.application.govtLogoChangeMessage,Message for government logo change modal,Upload a logo to be used on the login and declaration review screens,Téléchargez le logo du gouvernement qui sera utilisé sur le login et la décalcomanie du formulaire. Notez que le logo du certificat est téléchargé dans le cadre du modèle de certificat. -config.application.govtLogoChangeNotification,Message for government logo change notification,Government logo updated,Mise à jour du logo du gouvernement -config.application.govtLogoFileLimitError,Error message for large country logo file,Logo image file must be less than 2mb,Le fichier image du logo doit être inférieur à 2 Mo -config.application.imageTabTitle,The title for image tab,Image,Image -config.application.invalidExample,Label for Invalid example,Invalid,Invalide -config.application.lateFeeDialogTitle,Date fee dialog title,Registration fees for late registrations,Frais d'inscription pour les inscriptions tardives -config.application.lateRegistrationLabel,Late registration config label,Late registration,Déclaration tardive -config.application.lateRegistrationValue,Late registration config value,Between {onTime} days and {lateTime} days,Entre {onTime} jours et {lateTime} jours -config.application.legallySpecifiedLabel,Legally specified config label,Legally specified,Mention légale -config.application.legallySpecifiedValue,Legally specified config value,Within {onTime} days,Dans (ontime) jours -config.application.loginBackgroundLabel,Login Background config label,Login Background,Historique de la connexion -config.application.loginImageText,Login Image config label,Upload an image and set how you would like it to display in the background,Téléchargez une image et définissez comment vous souhaitez qu'elle s'affiche en arrière-plan. -config.application.marriageDelayedFeeChangeNotification,Message for application marriage delayed fee change notification,Marriage delayed fee updated,Mise à jour de la pénalité de retard déclaration du marriage -config.application.marriageLegallySpecifiedDialogTitle,Legally specified dialog title for marriage,Legally specified time period for marriage registration,Délais légal de déclaration du marriage -config.application.marriageOnTimeFeeChangeNotification,Message for application marriage on time fee change notification,Marriage on time fee updated,Mise à jour des frais de déclaration de marriage dans le délais legal -config.application.marriageRegTargetChangeNotification,Message for application marriage registration target change notification,Marriage registration target days updated,Mise à jour des jours cibles de déclaration des marriages -config.application.marriageTabTitle,The title for marriage tab,Marriage,Mariage -config.application.nameChangeMessage,Message for application name change modal,Choose a name for your CRVS system,Choisissez un nom pour votre système CRVS -config.application.nidPatternChangeError,Error message for invalid regular expression for NID number,Invalid regular expression for a National ID,Expression régulière invalide pour un identifiant national -config.application.nidPatternChangeMessage,Unique Identification Number (UIN) config message,Set the regex pattern for your national ID. For guidance please refer to www.regex101.com,Expression régulière invalide pour un identifiant national -config.application.nidPatternChangeNotification,Message for NID Pattern change modal,Unique Identification Number (UIN) regex pattern updated,Mise à jour du modèle regex pour le numéro d'identification unique (UIN) -config.application.nidPatternTitle,Unique Identification Number (UIN) config title,Unique Identification Number (UIN) e.g. National ID,"Numéro d'identification unique (UIN), par exemple la carte d'identité nationale." -config.application.onTimeFeeDialogTitle,On time fee dialog title,Registration fees within legally specified time,Droits d'inscription dans le délai légal -config.application.pattern,Label for Pattern,Pattern,Modèle -config.application.phoneNumberChangeError,Error message for invalid regular expression for phone number number,Invalid regular expression for a phone number,Expression régulière invalide pour un numéro de téléphone -config.application.phoneNumberChangeMessage,phone number config config message,Set the regex pattern for your country phone number. For guidance please refer to www.regex101.com,"Définissez le modèle regex pour le numéro de téléphone de votre pays. Pour obtenir des conseils, veuillez consulter le site www.regex101.com" -config.application.phoneNumberChangeNotification,Message for phone number Pattern change modal,Phone regex pattern updated,Mise à jour du modèle de regex téléphonique -config.application.phoneNumberExampleLabel,,example: {example},exemple: {example} -config.application.phoneNumberLabel,Phone number config label,Phone number,Numéro de téléphone -config.application.phoneNumberPatternLabel,,pattern: {pattern},motif: {pattern} -config.application.phoneNumberPatternTitle,Phone number config title,Phone number regex,Regex du numéro de téléphone -config.application.registrationFeesGroupTitle,The title for registration fee group,Registration fees,Droits d'inscription -config.application.registrationTimePeriodsGroupTitle,The title for registration time periods group,Registration time periods,Périodes d'enregistrement -config.application.settings,Link Text for Config Application Settings,Application,Application -config.application.testNumber,Label for test number,Test number,Numéro de test -config.application.updatingeMessage,Message for application config updated modal,Updating...,Mise à jour en cours -config.application.validExample,Label for valid example,Valid,Valable config.application.vitalStatistics,Vital Statistics Export,"Month-{month}-Farajaland-{event, select, birth{birth} death{death} other{birth}}-event-statistics.csv {fileSize}","Mois-{month}-Farajaland-{event, select, birth{birth} death{death} other{birth}}-événement-statistiques.csv {fileSize}" config.application.vsExportDownloadFailed,Vital Statistics Export Empty State Text,Sorry! Something went wrong,Désolé ! Quelque chose s'est mal passé config.application.vsexport,VS Export tab,Vital statistics,Statistiques vitales -config.application.withinLegallySpecifiedTimeLabel,Within legally specified time config label,Within legally specified time,Dans les délais prévus par la loi -config.birthDefaultTempDesc,Label for default birth certificate template,Default birth certificate template,Modèle d'acte de naissance par défaut -config.birthTemplate,Label for birth certificate template,Birth certificate,Certificat de naissance -config.birthUpdatedTempDesc,,Updated {birthLongDate},Mise à jour de {birthLongDate} config.certTemplate,Label for certificate templates,Certificate Template,Modèle de certificat -config.certificate.allowPrinting,To allow printing in advanced of issuance,Allow printing in advanced of issuance,Permettre l'impression à l'avance de l'émission -config.certificate.allowPrintingNotification,Message for allowing printing notification,Allow printing in advance of issuance updated,Permettre l'impression avant la mise à jour de l'émission -config.certificate.certificateUpdated,Certificate template change message on success,{eventName} certificate has been updated,Le certificat {eventName} a été mis à jour. -config.certificate.certificateUploading,Certificate template message when uploading SVG,Uploading and validating {eventName} certificate.,Téléchargement et validation du certificat {eventName}. -config.certificate.certificateValidationError,Certificate template error message on failed,Unable to read SVG. Please check,Impossible de lire le SVG. Veuillez vérifier config.certificate.options,Show options,Options,Options -config.certificate.printDescription,Allowing printing,Records printed off in advance of collections will be added to the ready to issue work-queue,Les documents imprimés avant les collectes seront ajoutés à la liste des documents prêts à être délivrés -config.certificate.template,Template for certificates,Template,Gabarit -config.certificate.uploadCertificateDialogCancel,Cancel new certificate template upload button,Cancel,Annuler -config.certificate.uploadCertificateDialogConfirm,Confirm new certificate template upload button,Upload,Télécharger -config.certificate.uploadCertificateDialogDescription,The description for the dialog when upload new certificate template,This will replace the current certificate template. We recommend downloading the existing certificate template as a reference.,Ceci remplacera le modèle de certificat actuel. Nous vous recommandons de télécharger le modèle de certificat existant comme référence. -config.certificate.uploadCertificateDialogTitle,Upload certificate template modal title,Upload new certificate?,Télécharger un nouveau certificat ? -config.certificateConfiguration,Link Text for Config Declaration Settings,Certificate configuration,Configuration du certificat -config.deathDefaultTempDesc,Label for default death certificate template,Default death certificate template,Modèle de certificat de décès par défaut -config.deathTemplate,Label for death certificate template,Death certificate,Acte de mariage -config.deathUpdatedTempDesc,,Updated {deathLongDate},Mise à jour de {deathLongDate} -config.downloadTemplate,Download action in certificate config action menu,Download,Télécharger config.emailAllUsers.modal.supportingCopy,Label for send email all users confirmation supporting copy,User will receive emails over the next 24 hours,L'utilisateur recevra des courriels au cours des prochaines 24 heures config.emailAllUsers.modal.title,Label for send email all users confirmation title,Send email to all users?,Envoyer un e-mail à tous les utilisateurs ? config.emailAllUsers.subtitle,Subtitle for email all users,This email will be sent to all users you are active. Emails will be sent over the next 24 hours. Only one email can be sent per day,Cet e-mail sera envoyé à tous les utilisateurs que vous activez. Les courriels seront envoyés au cours des prochaines 24 heures. Un seul courriel peut être envoyé par jour config.emailAllUsers.title,Title for email all users,Email all users,Envoyer un e-mail à tous les utilisateurs -config.eventUpdatedTempDesc,Label for updated birth certificate template,"Updated {lastModified, date, ::dd MMMM yyyy}","Mis à jour {lastModified, date, ::dd MMMM yyyy}" -config.form.settings.time,,Time input,Saisie de l'heure -config.form.tools.input.customSelectWithDynamicOptions,,Custom select with dynamic options,Sélection personnalisée avec options dynamiques -config.informantNotification.declarationSMS,Title for informant declarationSMS notification,Declaration sent for review,Déclaration envoyée pour examen -config.informantNotification.inProgressSMS,Title for informant inProgressSMS notification,Notification sent to Office,Notification envoyée au bureau -config.informantNotification.registrationSMS,Title for informant registrationSMS notification,Declaration registered,Déclaration enregistrée -config.informantNotification.rejectionSMS,Title for informant rejectionSMS notification,Declaration rejected,Déclaration rejetée -config.informantNotification.subtitle,Subtile for informant sms notification,Select the notifications to send to the informant to keep them informed of the progress to their declaration. Your system is configured to send {communicationType}.,Sélectionnez les notifications à envoyer à l'informateur pour le tenir informé de l'avancement de sa déclaration. Votre système est configuré pour envoyer {communicationType} -config.informantNotification.success,Notification for informant update success,Informant notifications updated,Mise à jour des notifications des informateurs -config.informantNotification.title,The title for Informant notifications,Informant notifications,Notifications d'informateurs -config.integrations,,Integrations,Intégrations -config.listDetails,Details for certificates templates list,To learn how to edit an SVG and upload a certificate to suite your country requirements please refer to this detailed guide. ,"Pour savoir comment modifier un SVG et télécharger un certificat en fonction des exigences de votre pays, veuillez consulter ce guide détaillé." -config.listDetailsQsn,Details question for certificates templates list,How to configure a certificate?,Comment configurer un certificat ? -config.listTitle,Title for certificates templates list,Certification,La certification -config.marriageDefaultTempDesc,Label for default marriage certificate template,Default marriage certificate template,Modèle de certificat de mariage par défaut -config.marriageTemplate,Label for marriage certificate template,Marriage certificate,Certificat de mariage -config.previewTemplate,,Preview,Prévisualiser -config.printTemplate,Print action in certificate config action menu,Print,Imprimer -config.uploadTemplate,Upload action in certificate config action menu,Upload,Télécharger config.userRoles.language,Language name,"{language, select, en {English} fr {French} other {{language}}}","{language, select, en {Anglais} fr {Français} other {{language}}}" -config.userRoles.role,ListViewSimplified header for role,ROLE,RÔLE config.userRoles.roleUpdateInstruction,Instruction for adding/updating role in role management modal,Add the roles to be assigned the system role of {systemRole},Ajoutez les rôles auxquels attribuer le rôle système de {systemRole} -config.userRoles.subtitle,Subtile for informant sms notification,Map user roles to each system role so that specific permissions and privileges are correctly assigned. To learn more about the different system roles see ... {link},"Associez les rôles d'utilisateur à chaque rôle système afin que les autorisations et les privilèges spécifiques soient correctement attribués. Pour en savoir plus sur les différents rôles système, voir ... {link}" -config.userRoles.systemRoleSuccessMsg,Label for System role updated success message,System role updated successfully,Rôle système mis à jour avec succès -config.userRoles.systemRoles,ListViewSimplified header for system roles,SYSTEM ROLES,RÔLES SYSTÈME -config.userRoles.title,The title for user roles,User roles,Rôles des utilisateurs conflicts.modal.assign.description,Description for modal when assign,Please note you will have sole access to this record. Please make any updates promptly otherwise unassign the record.,"Veuillez noter que vous aurez un accès exclusif à cet enregistrement. Veuillez effectuer rapidement les mises à jour éventuelles, sinon vous désassignez l'enregistrement." conflicts.modal.assign.title,Title for modal when assign,Assign record?,Attribuer un enregistrement ? conflicts.modal.assigned.description,Description for modal when record already assigned,{name} at {officeName} has sole editable access to this record,{name} à {officeName} a un accès unique et modifiable à cet enregistrement. @@ -1920,6 +1809,7 @@ search.locationNotFound,Label for location not found,Location Not Found,Emplacem search.noDeclarations,The text when there is no declaration to review,No declarations to review,Aucune déclaration à examiner search.noResultFor,The no result text,No results for ”{param}”,Aucun résultat pour “{param}” search.noResults,Text to display if the search return no results for the current filters,No result to display,Aucun résultat à afficher +search.placeholder,Placeholder text of search input,Name of query,Nom de la requête search.removeBbookmarkAdvancedSearchModalBody,Modal body for remove bookmark advacnced search,This advanced search bookmark will be removed from the side bar shortcut,Ce signet de recherche avancée sera supprimé du raccourci de la barre latérale search.removeBookmarkAdvancedSearchModalTitle,Modal title for remove bookmark advacnced search,Remove search query?,Supprimer la requête de recherche ? search.results,Results label at the top of the data table component,Results,Résultats diff --git a/src/utils/address-utils.ts b/src/utils/address-utils.ts index 3a49b6ecf..b3bfe57bd 100644 --- a/src/utils/address-utils.ts +++ b/src/utils/address-utils.ts @@ -988,23 +988,26 @@ export const getAddressSubsection = ( // You should never need to edit this function. If there is a bug here raise an issue in [Github](https://github.com/opencrvs/opencrvs-farajaland) function getAddressFieldsByConfiguration( configuration: AllowedAddressConfigurations, - section: string + section: string, + addressHierarchy: string[] ): SerializedFormField[] { switch (configuration.config) { case EventLocationAddressCases.PLACE_OF_BIRTH: case EventLocationAddressCases.PLACE_OF_DEATH: case EventLocationAddressCases.PLACE_OF_MARRIAGE: - return getAddressFields('', configuration.config) + return getAddressFields('', configuration.config, addressHierarchy) case AddressCases.PRIMARY_ADDRESS: return getAddress( section, AddressCases.PRIMARY_ADDRESS, + addressHierarchy, configuration.conditionalCase ) case AddressCases.SECONDARY_ADDRESS: return getAddress( section, AddressCases.SECONDARY_ADDRESS, + addressHierarchy, configuration.conditionalCase ) case AddressCopyConfigCases.PRIMARY_ADDRESS_SAME_AS_OTHER_PRIMARY: @@ -1043,7 +1046,8 @@ function getAddressFieldsByConfiguration( // You should never need to edit this function. If there is a bug here raise an issue in [Github](https://github.com/opencrvs/opencrvs-farajaland) export function decorateFormsWithAddresses( defaultEventForm: ISerializedForm, - event: string + event: string, + addressHierarchy: string[] ): ISerializedForm { const newForm = cloneDeep(defaultEventForm) defaultAddressConfiguration.forEach( @@ -1056,7 +1060,11 @@ export function decorateFormsWithAddresses( let previewGroups: IPreviewGroup[] = [] configurations.forEach((configuration) => { addressFields = addressFields.concat( - getAddressFieldsByConfiguration(configuration, sectionId) + getAddressFieldsByConfiguration( + configuration, + sectionId, + addressHierarchy + ) ) previewGroups = previewGroups.concat(getPreviewGroups(configuration)) }) @@ -1083,11 +1091,13 @@ export function decorateFormsWithAddresses( function getAddress( section: string, addressCase: AddressCases, + addressHierarchy: string[], conditionalCase?: string | Conditional[] ): SerializedFormField[] { const defaultFields: SerializedFormField[] = getAddressFields( section, - addressCase + addressCase, + addressHierarchy ) if (conditionalCase) { return addConditionalsToFields(defaultFields, conditionalCase) diff --git a/src/utils/mapping/field-mapping-utils.ts b/src/utils/mapping/field-mapping-utils.ts index a4a4451ae..25f9200e6 100644 --- a/src/utils/mapping/field-mapping-utils.ts +++ b/src/utils/mapping/field-mapping-utils.ts @@ -135,11 +135,17 @@ export function getFieldMapping( }, template: { fieldName: certificateHandlebar, - operation: 'selectTransformer' + operation: 'fieldValueTransformer', + parameters: ['relationship'] } } case 'otherInformantType': return { + template: { + fieldName: certificateHandlebar, + operation: 'fieldValueTransformer', + parameters: ['otherRelationship'] + }, mutation: { operation: 'fieldValueSectionExchangeTransformer', parameters: ['registration', 'otherInformantType'] diff --git a/src/utils/users.ts b/src/utils/users.ts new file mode 100644 index 000000000..415c77bb5 --- /dev/null +++ b/src/utils/users.ts @@ -0,0 +1,49 @@ +import { GATEWAY_URL } from '@countryconfig/constants' +import fetch from 'node-fetch' +import gql from 'graphql-tag' +import { print } from 'graphql/language/printer' +import { URL } from 'url' + +type GetUser = { + primaryOffice: { + hierarchy: Array<{ + id: string + }> + } +} +export async function fetchUserLocationHierarchy( + token: string, + userId: string +) { + const url = new URL('graphql', GATEWAY_URL) + const getUsersRes = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `${token}` + }, + body: JSON.stringify({ + operationName: 'fetchUser', + variables: { + userId: userId + }, + query: print(gql` + query fetchUser($userId: String!) { + getUser(userId: $userId) { + primaryOffice { + hierarchy { + id + } + } + } + } + `) + }) + }) + + const res = (await getUsersRes.json()) as { + data: { getUser: GetUser } + } + + return res.data.getUser.primaryOffice.hierarchy.map(({ id }) => id) +} diff --git a/tests/verify-elastalert-kibana-alerts-match.test.ts b/tests/verify-elastalert-kibana-alerts-match.test.ts new file mode 100644 index 000000000..4da5e82c5 --- /dev/null +++ b/tests/verify-elastalert-kibana-alerts-match.test.ts @@ -0,0 +1,54 @@ +import { readdirSync, readFileSync } from 'fs' +import yaml from 'js-yaml' +import { join } from 'path' +import { expect, it } from 'vitest' + +function findAllValuesByKey(obj: unknown, key: string): any[] { + const result: any[] = [] + + const recurse = (item: unknown) => { + if (Array.isArray(item)) { + for (const element of item) { + recurse(element) + } + } else if (typeof item === 'object' && item !== null) { + for (const k in item) { + if (k === key) { + result.push(item[k]) + } + recurse(item[k]) + } + } + } + + recurse(obj) + return result +} + +it('all tests defined in Kibana config are also defined in Elastalert config', () => { + const allAlertNames = readFileSync( + join(__dirname, '../infrastructure/monitoring/kibana', 'config.ndjson'), + 'utf8' + ) + .split('\n') + .map((str) => JSON.parse(str)) + .filter((item) => item.type === 'alert') + .map((item) => item.attributes.name) + .sort() + .filter((value, index, self) => self.indexOf(value) === index) + + const ruleNameFilters = readdirSync( + join(__dirname, '../infrastructure/monitoring/elastalert/rules') + ) + .map((file) => + join(__dirname, '../infrastructure/monitoring/elastalert/rules', file) + ) + .map((file) => readFileSync(file, 'utf8')) + .map((file) => yaml.load(file)) + .flatMap((rule) => findAllValuesByKey(rule, 'rule.name.keyword')) + .map((x) => x.value) + .sort() + .filter((value, index, self) => self.indexOf(value) === index) + + expect(ruleNameFilters).toEqual(allAlertNames) +}) diff --git a/yarn.lock b/yarn.lock index ec9ff6f2e..c5123f94d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -602,116 +602,231 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + "@esbuild/android-arm64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.9.tgz#9cad38830ea5fa714c196bb283c0958f49b64bfb" integrity sha512-G1rIBpSgjv0DEFmBYjljL85l4asf1dtQYwjoD02A5YG85JV3dsQSJL94vsEMWYMWkNd46hcvz3suURuY4dr+9g== +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + "@esbuild/android-arm@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.9.tgz#f0cfe4e981f901d290b32f3b3d322d867dc8b42f" integrity sha512-v1cr0l0RZOzIgLtTe8M1cRFFP0ICRdymPPa8HCPUpgZ+XasQrd5Mxyp9KlDqXLLyGmnZpzhufKEThLIihQL53A== +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + "@esbuild/android-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.9.tgz#d047bbe7f3e046650e46394132ca8553e4e4d4a6" integrity sha512-rPgcISGfoP7/Yk8+0eUf9R/KLCYGgqtojz/Uvj26wp7/EclwxoaOMArBnDChfuWF5YLdS16dDfqb4qwXS087lw== +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + "@esbuild/darwin-arm64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.9.tgz#22e2f880ef99f51e8f52a238170fa24d68f035e9" integrity sha512-vw9kWBT2EvDhLAVkI5c2KWFh+GMwgXrzR1QnIpZazA+tIacaelNLMMSTHEJisOeQqiMQhv8goTODFm9liS7wpw== +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + "@esbuild/darwin-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.9.tgz#e42d4b0a5315a6eab3591baa0d3be4fccfca0fb9" integrity sha512-tDbKKMUeS0PckRtIxdF3+NgkE19kTyLFmUQ0umgXDnBvcWC3/DqhZyu4P4Af3zBzOfWH5DAAmGW1hgy53Z706w== +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + "@esbuild/freebsd-arm64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.9.tgz#3ec3bb5a70edf0b890f11b8077c69ed297e0467e" integrity sha512-Anyk3qeTKJUcxiLE8VQ6y6frVuqFc71M5TEc2EzvXchoy6oWn5eZK+MpZBVnENVMSDA4wOjDKiFsPtVhnrhHHA== +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + "@esbuild/freebsd-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.9.tgz#87a33b75e4be4c7b3d2cf15aef0cd1e1b0d24043" integrity sha512-BsOYio/4p/6RWG+sDQXVYet8qQ0bB91rfO0YNk5s0HlqE9vEth3Yi1jFNi4v7bUA4vQDWWoybpA/9NTz1sM88A== +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + "@esbuild/linux-arm64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.9.tgz#0628d1559b6936aad8fa9b3df4eca6404d3a0669" integrity sha512-2fJtf4KKR301FrhRNY1KIgVid2nUrZV6fzx39E+JgT3jAw2NsZYUiphR31CyH4MloyoEwgQTnskwaQH+nT4bHA== +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + "@esbuild/linux-arm@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.9.tgz#4608fb5635e22a764310b2ff0a7bfafd2a29018b" integrity sha512-YotJBEt9swVrEBRBIXQzI03A4kDQSWk+mbGTTBreIRvWWWTXXqhNYZgqiwnEvtyQi9aqSipEzkRzAGNqs54EXw== +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + "@esbuild/linux-ia32@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.9.tgz#10f6d7001553c35f3b4cdda1cd0fa92b7bf14909" integrity sha512-pTTBAGi2lrduXo4vATnqCtFi9zRbyXOlcV+euznW5EoFyjAIR+JCQgFDeFCMo343E2EI2MgV7ZQctO8IWcsdsA== +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + "@esbuild/linux-loong64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.9.tgz#8d6283269b9e6afa9a4f5ad546e6a005395f873f" integrity sha512-hmsjvhwHrsCKPthXhhNjLE+QON8uQCE9P/OBktaYOD8UDfmz9+txm04uXhnkRH0fDEqStsDEedbX+8KPg1CwyA== +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + "@esbuild/linux-mips64el@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.9.tgz#cc734a77fa17118060dc45e9c5500626b5ba72e7" integrity sha512-Ymv4j25ie7mVEVlcThnOlRVvqDSsj22MJBH31QGMsyA0dUwReqCg9yNqRM2Dh8QHDRO2UrMhGmiL6BaTdBWlQw== +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + "@esbuild/linux-ppc64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.9.tgz#2f5ede177ba030070c17466c372d438690758297" integrity sha512-y2viEHwLpNfWP1eLa+vV+DWIbw/pQyv1Vf6qxSGJeBQmmu9T2hOagMiCr6zhDo89l+MUAXiShdKmqlKI6HdCkw== +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + "@esbuild/linux-riscv64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.9.tgz#b28f9ee395754ca65a261d0f724e52e8af4a1529" integrity sha512-na8WG8Z7z1EIUcJFuXKOawJEsq8luOur7LHK/ophO0+RSE8A9yxCsKYhaN9IxlR1UciAuHjo/7d5yiflABwUmA== +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + "@esbuild/linux-s390x@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.9.tgz#0f57a44ce133048218963b04075bb2956e4b2c3f" integrity sha512-XsnaI89KstE0jG4cMdzuJ8SKcKAod26had7U/4SzvuMrci0/XyEQXB1jikn6MB7LPGrd5rcLeYp3F7psUxhkWw== +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + "@esbuild/linux-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.9.tgz#6607e056fba189b2ac0f295492ce16344f995a64" integrity sha512-odEbmjtm3tLPtY43FRWOG+CLN7d4ooQpGjYVFVti5rLXLym26dORxnlbekNPXuQRuQKNMPczNNWE1jOc8yAyJQ== +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + "@esbuild/netbsd-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.9.tgz#0e67492dd5197bc6227234563465a66789ac5dde" integrity sha512-j/GgOjKNUPd54isC/RBYlS6CREbulnMWAJEIKTnPM0QnY0pEGfMHkFh73bsmZdovp/97zRty0NdePRk4dTP/cw== +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + "@esbuild/openbsd-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.9.tgz#03121aad11bbe3ef5e801f751cb4cef483efa147" integrity sha512-DN0Z9RGU/hlaMWSG9GaDLvlu0718u1HDGiF19wJ35fUznf9yJYgXDwZ5/cRQXUewHXJB0pD/VyQfRLDP3M4maw== +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + "@esbuild/sunos-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.9.tgz#9442369e234d7eb53d06fb385ad3a745af365790" integrity sha512-W/eHabLCXdki/8H3jmfE/ClDuh3bQQKpYfQHGQ7lQync9W72ZdVr2y1iWfEVTE7ZK/DQROo3GyfTkx5HPBZxmQ== +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + "@esbuild/win32-arm64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.9.tgz#6a233d4d0bafffad51253022952d97f22b0ad91a" integrity sha512-84FMz3Sh1hwGk/oWy6XGIW2bGVcsqvHLjjtbwd982XoTHOvQSthhrMef0J+4ShE1ZE7VeUXHIt2Mfer+myedYw== +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + "@esbuild/win32-ia32@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.9.tgz#f060d7609d70986324d486c71454d5be0a96f5e9" integrity sha512-/RsFTk0P13Nb+ixBVZfPdlLWKsP+he3ZLxOO/1eCsZZ2U7c/JxB053U7kURsyhhUPwiGzGVaAQAeyhGtYe8ehw== +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + "@esbuild/win32-x64@0.18.9": version "0.18.9" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.9.tgz#05686cd64032f1f46569dc19670c937381db2c86" integrity sha512-S+oBiO8UE1hmDJZlZJ6HZEdBBrxCGovwN66P9rle4DWVktM5fsMouYhpbtUf4WQLEy0HvcE2ZOQ2gIq8v0BkBw== +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1722,6 +1837,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" @@ -1885,6 +2005,86 @@ resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.4.tgz#a04d63f4d1bf5540a41b01a921c9a7fddc3bd1ca" integrity sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA== +"@rollup/rollup-android-arm-eabi@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz#1661ff5ea9beb362795304cb916049aba7ac9c54" + integrity sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA== + +"@rollup/rollup-android-arm64@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz#2ffaa91f1b55a0082b8a722525741aadcbd3971e" + integrity sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA== + +"@rollup/rollup-darwin-arm64@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz#627007221b24b8cc3063703eee0b9177edf49c1f" + integrity sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA== + +"@rollup/rollup-darwin-x64@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz#0605506142b9e796c370d59c5984ae95b9758724" + integrity sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ== + +"@rollup/rollup-linux-arm-gnueabihf@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz#62dfd196d4b10c0c2db833897164d2d319ee0cbb" + integrity sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA== + +"@rollup/rollup-linux-arm-musleabihf@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz#53ce72aeb982f1f34b58b380baafaf6a240fddb3" + integrity sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw== + +"@rollup/rollup-linux-arm64-gnu@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz#1632990f62a75c74f43e4b14ab3597d7ed416496" + integrity sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA== + +"@rollup/rollup-linux-arm64-musl@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz#8c03a996efb41e257b414b2e0560b7a21f2d9065" + integrity sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw== + +"@rollup/rollup-linux-powerpc64le-gnu@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz#5b98729628d5bcc8f7f37b58b04d6845f85c7b5d" + integrity sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw== + +"@rollup/rollup-linux-riscv64-gnu@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz#48e42e41f4cabf3573cfefcb448599c512e22983" + integrity sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg== + +"@rollup/rollup-linux-s390x-gnu@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz#e0b4f9a966872cb7d3e21b9e412a4b7efd7f0b58" + integrity sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g== + +"@rollup/rollup-linux-x64-gnu@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz#78144741993100f47bd3da72fce215e077ae036b" + integrity sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A== + +"@rollup/rollup-linux-x64-musl@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz#d9fe32971883cd1bd858336bd33a1c3ca6146127" + integrity sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ== + +"@rollup/rollup-win32-arm64-msvc@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz#71fa3ea369316db703a909c790743972e98afae5" + integrity sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ== + +"@rollup/rollup-win32-ia32-msvc@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz#653f5989a60658e17d7576a3996deb3902e342e2" + integrity sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ== + +"@rollup/rollup-win32-x64-msvc@4.24.0": + version "4.24.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz#0574d7e87b44ee8511d08cc7f914bcb802b70818" + integrity sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw== + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.1" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" @@ -2011,6 +2211,11 @@ dependencies: "@types/node" "*" +"@types/estree@1.0.6", "@types/estree@^1.0.0": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== + "@types/fhir@^0.0.30": version "0.0.30" resolved "https://registry.yarnpkg.com/@types/fhir/-/fhir-0.0.30.tgz#a0aec3b2d7dd2a7584474dac446ede5f9a4d7a13" @@ -2337,6 +2542,65 @@ "@typescript-eslint/types" "5.60.1" eslint-visitor-keys "^3.3.0" +"@vitest/expect@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.2.tgz#e92fa284b8472548f72cacfe896020c64af6bf78" + integrity sha512-FEgtlN8mIUSEAAnlvn7mP8vzaWhEaAEvhSXCqrsijM7K6QqjB11qoRZYEd4AKSCDz8p0/+yH5LzhZ47qt+EyPg== + dependencies: + "@vitest/spy" "2.1.2" + "@vitest/utils" "2.1.2" + chai "^5.1.1" + tinyrainbow "^1.2.0" + +"@vitest/mocker@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.2.tgz#08853a9d8d12afba284aebdf9b5ea26ddae5f20a" + integrity sha512-ExElkCGMS13JAJy+812fw1aCv2QO/LBK6CyO4WOPAzLTmve50gydOlWhgdBJPx2ztbADUq3JVI0C5U+bShaeEA== + dependencies: + "@vitest/spy" "^2.1.0-beta.1" + estree-walker "^3.0.3" + magic-string "^0.30.11" + +"@vitest/pretty-format@2.1.2", "@vitest/pretty-format@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.2.tgz#42882ea18c4cd40428e34f74bbac706a82465193" + integrity sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA== + dependencies: + tinyrainbow "^1.2.0" + +"@vitest/runner@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.2.tgz#14da1f5eac43fbd9a37d7cd72de102e8f785d727" + integrity sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw== + dependencies: + "@vitest/utils" "2.1.2" + pathe "^1.1.2" + +"@vitest/snapshot@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.2.tgz#e20bd794b33fdcd4bfe69138baac7bb890c4d51f" + integrity sha512-xtAeNsZ++aRIYIUsek7VHzry/9AcxeULlegBvsdLncLmNCR6tR8SRjn8BbDP4naxtccvzTqZ+L1ltZlRCfBZFA== + dependencies: + "@vitest/pretty-format" "2.1.2" + magic-string "^0.30.11" + pathe "^1.1.2" + +"@vitest/spy@2.1.2", "@vitest/spy@^2.1.0-beta.1": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.2.tgz#bccdeca597c8fc3777302889e8c98cec9264df44" + integrity sha512-GSUi5zoy+abNRJwmFhBDC0yRuVUn8WMlQscvnbbXdKLXX9dE59YbfwXxuJ/mth6eeqIzofU8BB5XDo/Ns/qK2A== + dependencies: + tinyspy "^3.0.0" + +"@vitest/utils@2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.2.tgz#222ac35ba02493173e40581256eb7a62520fcdba" + integrity sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ== + dependencies: + "@vitest/pretty-format" "2.1.2" + loupe "^3.1.1" + tinyrainbow "^1.2.0" + "@whatwg-node/events@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" @@ -2562,6 +2826,11 @@ asn1js@^3.0.1, asn1js@^3.0.5: pvutils "^1.1.3" tslib "^2.4.0" +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2760,6 +3029,11 @@ busboy@^1.6.0: dependencies: streamsearch "^1.1.0" +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -2835,6 +3109,17 @@ capital-case@^1.0.4: tslib "^2.0.3" upper-case-first "^2.0.2" +chai@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" + integrity sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + chalk@*: version "5.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.1.2.tgz#d957f370038b75ac572471e83be4c5ca9f8e8c45" @@ -2928,6 +3213,11 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + chokidar@^3.5.2: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -3311,6 +3601,13 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.6: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== + dependencies: + ms "^2.1.3" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -3326,6 +3623,11 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA== +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -3515,6 +3817,35 @@ esbuild@^0.18.9: "@esbuild/win32-ia32" "0.18.9" "@esbuild/win32-x64" "0.18.9" +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -3656,6 +3987,13 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -3993,6 +4331,11 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -4013,6 +4356,11 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-func-name@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" @@ -4140,7 +4488,7 @@ graphql-request@^6.0.0: "@graphql-typed-document-node/core" "^3.2.0" cross-fetch "^3.1.5" -graphql-tag@^2.11.0: +graphql-tag@^2.11.0, graphql-tag@^2.12.6: version "2.12.6" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.6.tgz#d441a569c1d2537ef10ca3d1633b48725329b5f1" integrity sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg== @@ -4157,6 +4505,11 @@ graphql-ws@^5.4.1: resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.11.2.tgz#d5e0acae8b4d4a4cf7be410a24135cfcefd7ddc0" integrity sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w== +graphql@^16.3.0: + version "16.8.1" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07" + integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw== + handlebars@*: version "4.7.8" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" @@ -5139,6 +5492,13 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +loupe@^3.1.0, loupe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.1.tgz#71d038d59007d890e3247c5db97c1ec5a92edc54" + integrity sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw== + dependencies: + get-func-name "^2.0.1" + lower-case-first@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lower-case-first/-/lower-case-first-2.0.2.tgz#64c2324a2250bf7c37c5901e76a5b5309301160b" @@ -5173,6 +5533,13 @@ lru_map@^0.3.3: resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" integrity sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ== +magic-string@^0.30.11: + version "0.30.11" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" + integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5298,7 +5665,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -5318,6 +5685,11 @@ nan@^2.18.0, nan@^2.19.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.19.0.tgz#bb58122ad55a6c5bc973303908d5b16cfdd5a8c0" integrity sha512-nO1xXxfh/RWNxfd/XPfbIfFk5vgLsAxUR9y5O0cHMJu/AW9U95JLXqthYHjEp+8gQ5p96K9jUp8nbVOxCdRbtw== +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -5773,11 +6145,26 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" + integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -5865,6 +6252,15 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg== +postcss@^8.4.43: + version "8.4.47" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.47.tgz#5bf6c9a010f3e724c503bf03ef7947dcb0fea365" + integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ== + dependencies: + nanoid "^3.3.7" + picocolors "^1.1.0" + source-map-js "^1.2.1" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -6175,6 +6571,31 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^4.20.0: + version "4.24.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.24.0.tgz#c14a3576f20622ea6a5c9cad7caca5e6e9555d05" + integrity sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg== + dependencies: + "@types/estree" "1.0.6" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.24.0" + "@rollup/rollup-android-arm64" "4.24.0" + "@rollup/rollup-darwin-arm64" "4.24.0" + "@rollup/rollup-darwin-x64" "4.24.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.24.0" + "@rollup/rollup-linux-arm-musleabihf" "4.24.0" + "@rollup/rollup-linux-arm64-gnu" "4.24.0" + "@rollup/rollup-linux-arm64-musl" "4.24.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.24.0" + "@rollup/rollup-linux-riscv64-gnu" "4.24.0" + "@rollup/rollup-linux-s390x-gnu" "4.24.0" + "@rollup/rollup-linux-x64-gnu" "4.24.0" + "@rollup/rollup-linux-x64-musl" "4.24.0" + "@rollup/rollup-win32-arm64-msvc" "4.24.0" + "@rollup/rollup-win32-ia32-msvc" "4.24.0" + "@rollup/rollup-win32-x64-msvc" "4.24.0" + fsevents "~2.3.2" + run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -6368,6 +6789,11 @@ short-uid@^0.1.0: resolved "https://registry.yarnpkg.com/short-uid/-/short-uid-0.1.0.tgz#069d94d044fc498afb0ea7bb22c5e634979434c8" integrity sha512-FcrUzrOPh7gZcJ9piR15qs3bTSOyZWzpPFeKYK37A4Mr20wKnwskWFdYRj+mk8AWSO1wsflM+HgyeNTbgBecPg== +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -6480,6 +6906,11 @@ sonic-boom@^4.0.1: dependencies: atomic-sleep "^1.0.0" +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -6567,6 +6998,11 @@ ssh2@^1.14.0: cpu-features "~0.0.9" nan "^2.18.0" +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + staged-git-files@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.1.tgz#37c2218ef0d6d26178b1310719309a16a59f8f7b" @@ -6580,6 +7016,11 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" +std-env@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== + stream-shift@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" @@ -6759,6 +7200,31 @@ through@^2.3.6, through@^2.3.8: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== +tinybench@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" + integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== + +tinyexec@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.0.tgz#ed60cfce19c17799d4a241e06b31b0ec2bee69e6" + integrity sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg== + +tinypool@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe" + integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA== + +tinyrainbow@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" + integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== + +tinyspy@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" + integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== + title-case@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/title-case/-/title-case-3.0.3.tgz#bc689b46f02e411f1d1e1d081f7c3deca0489982" @@ -7049,6 +7515,52 @@ value-or-promise@^1.0.12: resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c" integrity sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q== +vite-node@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.2.tgz#f5491a2b399959c9e2f3c4b70cb0cbaecf9be6d2" + integrity sha512-HPcGNN5g/7I2OtPjLqgOtCRu/qhVvBxTUD3qzitmL0SrG1cWFzxzhMDWussxSbrRYWqnKf8P2jiNhPMSN+ymsQ== + dependencies: + cac "^6.7.14" + debug "^4.3.6" + pathe "^1.1.2" + vite "^5.0.0" + +vite@^5.0.0: + version "5.4.8" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.8.tgz#af548ce1c211b2785478d3ba3e8da51e39a287e8" + integrity sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.43" + rollup "^4.20.0" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.2.tgz#f285fdde876749fddc0cb4d9748ae224443c1694" + integrity sha512-veNjLizOMkRrJ6xxb+pvxN6/QAWg95mzcRjtmkepXdN87FNfxAss9RKe2far/G9cQpipfgP2taqg0KiWsquj8A== + dependencies: + "@vitest/expect" "2.1.2" + "@vitest/mocker" "2.1.2" + "@vitest/pretty-format" "^2.1.2" + "@vitest/runner" "2.1.2" + "@vitest/snapshot" "2.1.2" + "@vitest/spy" "2.1.2" + "@vitest/utils" "2.1.2" + chai "^5.1.1" + debug "^4.3.6" + magic-string "^0.30.11" + pathe "^1.1.2" + std-env "^3.7.0" + tinybench "^2.9.0" + tinyexec "^0.3.0" + tinypool "^1.0.0" + tinyrainbow "^1.2.0" + vite "^5.0.0" + vite-node "2.1.2" + why-is-node-running "^2.3.0" + wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -7109,6 +7621,14 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + word-wrap@^1.2.3: version "1.2.4" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"