From 9866283390fbe91dd7a7cc9886c6017de399bbe3 Mon Sep 17 00:00:00 2001 From: Olaf Rode <olaf.rode@fokus.fraunhofer.de> Date: Tue, 25 Mar 2025 17:29:36 +0100 Subject: [PATCH] feat: adjusting repo structure to gematik requirements before moving content to public github project --- CODE_OF_CONDUCT.md | 75 ++++++++++++++++ README.md | 40 +++++++-- ReleaseNotes.md | 10 +++ SECURITY.md | 6 ++ curl/README.md | 58 ++++++++----- curl/download.sh | 86 +++++++++---------- images/Gematik_Logo_Flag_With_Background.png | Bin 0 -> 36991 bytes npm/README.md | 41 ++++++--- npm/create_npm_config.sh | 28 +++--- sushi-wrap/BfArM-Package-Test/sushi-wrap.sh | 80 ++++++++--------- sushi-wrap/README.md | 57 +++++++----- 11 files changed, 324 insertions(+), 157 deletions(-) create mode 100644 CODE_OF_CONDUCT.md create mode 100644 ReleaseNotes.md create mode 100644 SECURITY.md create mode 100644 images/Gematik_Logo_Flag_With_Background.png diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..6622047 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,75 @@ +## Code of Conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion, or sexual identity and +orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or +advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Calls for violence, vilification and advertising +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at OSPO@gematik.de. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ \ No newline at end of file diff --git a/README.md b/README.md index aa1e56f..8a759de 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,37 @@ -# bfarm-package-download +<img align="right" width="250" height="47" src="images/Gematik_Logo_Flag_With_Background.png"/> <br/> + +# zts-api-client-examples -Innerhalb des Repositories wird eine Reihe von Beispiel-Clients und -Konfigurationen bereitgestellt, die den automatiserten Download von FHIR-Packages aus der BfArM Package Registry (https://terminologien.bfram.de/packages/...) demonstrieren: +<details> + <summary>Table of Contents</summary> + <ol> + <li><a href="#about-the-project">About The Project</a></li> + <li><a href="#getting-started">Getting Started</a></li> + <li><a href="#license">License</a></li> + <li><a href="#contact">Contact</a></li> + </ol> +</details> -- **[curl](./curl/README.md)** - Beispiel-Skript für das automatisierte Downloaden von FHIR-Packages über curl. Der Client unterstützt verschiedene Anwendungsszenarien im Kontext des Content-Syndication (z.B. Download der als "latest" getaggten Paketversionen, Download aller Paketversionen) -- **[npm](./npm/README.md)** - Beispielkonfiguration/-anleitung für die Nutzung von npm zum Download von FHIR-Packages. -- **[sushi-wrap](./sushi-wrap/README.md)** - Beispiel-Skript für die Integration mit Sushi +## About The Project +This repository provides a series of example clients and configurations that demonstrate the automated download of FHIR packages from the BfArM Package Registry (https://terminologien.bfarm.de/packages): + +### Release Notes +See [ReleaseNotes.md](./ReleaseNotes.md) for all information regarding the (newest) releases. + +## Getting Started +The following example clients/configurations are currently provided: + +- **[curl](./curl/README.md)** — Example script for the automated download of FHIR packages using curl. The client supports various application scenarios in the context of content syndication (e.g., downloading package versions tagged as "latest", downloading all package versions). +- **[npm](./npm/README.md)** — Example configuration/instructions for using npm to download FHIR packages. +- **[sushi-wrap](./sushi-wrap/README.md)** — Example wrapper script to integrate an automated package download into Sushi workflows. + +For more in-depth documentation, please refer to the referenced README files of the individual tools. + +## License +See [LICENCE.md](./LICENCE.md) for all information regarding licencing. + +## Contact +We take open source license compliance very seriously. We are always striving to achieve compliance at all times and to improve our processes. +This software is currently being tested to ensure its technical quality and legal compliance. Your feedback is highly valued. +If you find any issues or have any suggestions or comments, or if you see any other ways in which we can improve, please reach out to: [https://terminologien.bfarm.de/kontakt.html](https://terminologien.bfarm.de/kontakt.html) + diff --git a/ReleaseNotes.md b/ReleaseNotes.md new file mode 100644 index 0000000..2f43f5c --- /dev/null +++ b/ReleaseNotes.md @@ -0,0 +1,10 @@ +<img align="right" width="250" height="47" src="images/Gematik_Logo_Flag_With_Background.png" /> +<br/> + +# Release Notes zts-api-client-examples + +## Release 1.0.0 (2025-03-25) + +### changed + +- initial release with examples for downloading terminology packages using curl, npm and sushi diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..367917e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,6 @@ +# Security Policy + +Since this software is not a productive version, please submit an issue or pull request for any bugs or vulnerabilities you find. + +In case of a responsible disclosure, please follow instructions +on https://www.gematik.de/datensicherheit#c1227. \ No newline at end of file diff --git a/curl/README.md b/curl/README.md index 94130bf..617fabc 100644 --- a/curl/README.md +++ b/curl/README.md @@ -1,35 +1,51 @@ -# curl-basiertes Download-Skript +<img align="right" width="250" height="47" src="../images/Gematik_Logo_Flag_With_Background.png"/> <br/> + +# curl-based Download Script -## Voraussetzung -Folgende Pakete werden zur Ausführung des Download-Skripts benötigt: +<details> + <summary>Table of Contents</summary> + <ol> + <li><a href="#about-the-project">About The Project</a></li> + <li><a href="#prerequisites">Prerequisites</a></li> + <li><a href="#preliminary-note">Preliminary Note</a></li> + <li><a href="#usage">Usage</a></li> + </ol> +</details> -- **curl** (command line tool and library for transferring data with URLs) - [Website](https://curl.se/) -- **jq** (leightweight and flexible command-line JSON processor) - [Website](https://jqlang.github.io/jq/) +## About The Project +Example script for the automated download of FHIR packages using curl. The client script supports various application scenarios in the context of content syndication (e.g., downloading package versions tagged as "latest", downloading all package versions). -## Vorbemerkung -Die vom ZTS angebotenen Inhalte unterliegen Downloadbedingungen, welche unter [https://terminologien.bfarm.de/download-conditions.html](https://terminologien.bfarm.de/download-conditions.html) eingesehen werden können. Bitte stellen Sie sicher, dass Sie die jeweils geltenden Bedingungen akzeptieren, bevor Sie das angebotenen Skript nutzen. Die Annahme der Bedingungen ist über den Kommandozeilenparameter ```-c``` zu bestätigen. +## Prerequisites +The following packages are required to run the download script: -## Kommandozeilenparameter -Folgende Kommandozeilenparameter werden durch das Tool unterstützt: +- **curl** (command-line tool and library for transferring data with URLs) - [Website](https://curl.se/) +- **jq** (lightweight and flexible command-line JSON processor) - [Website](https://jqlang.github.io/jq/) -- ```-c``` consent to download conditions - valid values: ```true```, ```false``` - default value: ```false``` -- ```-i``` packages to INCLUDE - valid values: ```ALL``` (for all available packages), ```{packagelist}``` (package names separated by ',') - e.g. ```bfarm.terminologien.icd10gm,bfarm.terminologien.ops``` - default: ```ALL``` -- ```-e``` packages to EXCLUDE from download - valid values: ```{packagelist}``` (package names separated by ',') - e.g. ```bfarm.terminologien.loinc,bfarm.terminologien.ucum``` - default: -- ```-l``` download only latest version of the package - valid values: ```true```, ```false``` - default: ```true``` -- ```-o``` output directory (location where downloaded packages will be stored) - e.g. ```./content``` - default: ```./packages``` +## Preliminary Note +The content offered by ZTS is subject to download conditions, which can be viewed at [https://terminologien.bfarm.de/download-conditions.html](https://terminologien.bfarm.de/download-conditions.html). Please ensure that you accept the applicable terms before using the provided script. Acceptance of the terms must be confirmed via the command-line parameter ```-c``` (see below). -## Beispiel-Nutzung -Das hier angebotene Skript ermöglicht die Umsetzung verschiedener Anwendungsfälle in Bezug auf den Download von Terminologiepaketen: +## Usage -**Download der jeweils aktuellen Version eines namentlich bekannten Pakets** +### Command-Line Parameters +The following command-line parameters are supported by the tool: + +- ```-c``` consent to download conditions — valid values: ```true```, ```false``` — default value: ```false``` +- ```-i``` packages to INCLUDE — valid values: ```ALL``` (for all available packages), ```{packagelist}``` (package names separated by ',') — e.g., ```bfarm.terminologien.icd10gm,bfarm.terminologien.ops``` — default: ```ALL``` +- ```-e``` packages to EXCLUDE from download — valid values: ```{packagelist}``` (package names separated by ',') — e.g. ```bfarm.terminologien.loinc,bfarm.terminologien.ucum``` — default: (none) +- ```-l``` download only the latest version of the package — valid values: ```true```, ```false``` — default: ```true``` +- ```-o``` output directory (location where downloaded packages will be stored) — e.g., ```./content``` — default: ```./packages``` + +### Example Usage +The provided script enables various use cases regarding the download of terminology packages: + +**Download the latest version of a specific named package** ```./download.sh -c [true|false] -i bfarm.terminologien.icd10gm -l true -o ./icd10gm``` -**Download ALLER Version eines namentlich bekannten Pakets** +**Download ALL versions of a specific named package** ```./download.sh -c [true|false] -i bfarm.terminologien.ops -l false -o ./ops``` -**Download ALLER Version ALLER vom ZTS verwalteten Pakete** - -```./download.sh -c [true|false] -i ALL -l false -o ./packages``` +**Download ALL versions of ALL packages managed by ZTS** +```./download.sh -c [true|false] -i ALL -l false -o ./packages``` \ No newline at end of file diff --git a/curl/download.sh b/curl/download.sh index 74f8855..1122027 100755 --- a/curl/download.sh +++ b/curl/download.sh @@ -1,43 +1,44 @@ #!/bin/bash # ==================================================================================================================================== -# Konfiguration +# Configuration # ==================================================================================================================================== -# Für die Verwendung des Skripts, muss explizit bestätigt werden, dass die jeweils geltenden Downloadbedingungen akzeptiert wurden -# vgl. https://terminologien.bfarm.de/download-conditions.html +# To use the script, you must explicitly confirm that the applicable download conditions have been accepted +# see https://terminologien.bfarm.de/download-conditions.html ACCEPTED_DOWNLOAD_CONDITIONS=false -# Pakete die heruntergeladen werden sollen. Diese können als Komma-separierte Liste angegeben werden. Wird der Wert 'ALL' gesetzt, werden alle Pakete heruntergeladen +# Packages to be downloaded. These can be specified as a comma-separated list. +# If the value 'ALL' is set, all available packages will be downloaded. INCLUDE_PACKAGES=ALL -# Pakete die NICHT heruntergeladen werden sollen. Diese müssen als Komma-separierte Liste angegeben werden +# Packages that should NOT be downloaded. These must be specified as a comma-separated list. EXCLUDE_PACKAGES= -# Beschränken des Downloads auf die als "latest" gekennzeichnete Version +# Limit the download to the version marked as "latest" LATEST_ONLY=true -# Der Wert der im User-Agent-Header gesetzt werden soll +# The value to be set in the User-Agent header USER_AGENT=example-zts-client/1.0 -# Endpunktadressen der ZTS-API +# Endpoint addresses of the ZTS API CATALOG_API_ENDPOINT=https://terminologien.bfarm.de/packages/catalog PACKAGE_API_ENDPOINT=https://terminologien.bfarm.de/packages TOKEN_API_ENDPOINT=https://terminologien.bfarm.de/api/generate-token -# Ausgabeverzeichnis, in welchem heruntergeladenen Paketversionen gespeichert werden +# Output directory where downloaded package versions will be stored OUTPUT_DIR=./packages -# Pfad-/Dateinamen für temporäre Arbeitsdateien +# Path/filenames for temporary working files CATALOG_METADATA_FILE=catalog.json PACKAGE_METADATA_FILE=response.json CURRENT_DIR=$(pwd) # ==================================================================================================================================== -# Hilfsfunktionen +# Helper functions # ==================================================================================================================================== -# Ausgabe der Verwendung des Skripts +# Display usage instructions for the script usage() { echo "$0 -c [true|false] -i [ALL|{packagelist}] -e {packageList} -l [true|false] -o [outputDir]" echo "Command Line Parameters:" @@ -59,10 +60,10 @@ usage() { } # ==================================================================================================================================== -# Verarbeitung der Kommandozeilenparameter (inkl. Validierung) +# Processing of command-line parameters (including validation) # ==================================================================================================================================== -# Kommandozeilenparameter verarbeiten +# Processing of command-line parameters while getopts "c:i:e:l:o:" opt; do case $opt in c) ACCEPTED_DOWNLOAD_CONDITIONS="$OPTARG" ;; @@ -74,110 +75,109 @@ while getopts "c:i:e:l:o:" opt; do esac done -# Prüfen, ob die Downloadbedingungen übernommen wurden +# Check if the download conditions have been accepted if [ "$ACCEPTED_DOWNLOAD_CONDITIONS" != true ]; then echo "Die Downloadbedingungen müssen bestätigt werden" usage fi -# Prüfen, ob die INCLUDE_PACKAGE Wert korrekt ist +# Check if the INCLUDE_PACKAGE value is correct if [[ ! "$INCLUDE_PACKAGES" =~ ^ALL$|^[a-z0-9]+(\.[a-z0-9]+)+(,[a-z0-9]+(\.[a-z0-9]+)+)*$ ]]; then echo "Fehler bei der Angabe der zu inkludierenden Pakete: '$INCLUDE_PACKAGES'" usage fi -# Prüfen, ob der EXCLUDE_PACKAGE Wert korrekt ist +# Check if the EXCLUDE_PACKAGE value is correct if [[ ! "$EXCLUDE_PACKAGES" =~ ^$|^[a-z0-9]+(\.[a-z0-9]+)+(,[a-z0-9]+(\.[a-z0-9]+)+)*$ ]]; then echo "Fehler bei der Angabe der zu exkludierenden Pakete: '$EXCLUDE_PACKAGES'" usage fi -# Prüfen, ob der LATEST_ONLY Wert korrekt ist +# Check if the LATEST_ONLY value is correct # ==================================================================================================================================== -# Vorbereiten der Umgebung +# Preparing the environment # ==================================================================================================================================== -# Anlegen eines (temporären) Ausgabeverzeichnisses +# Create a (temporary) output directory mkdir -p $OUTPUT_DIR # ==================================================================================================================================== -# Abruf der Liste unterstützten Pakete +# Retrieving the list of supported packages # ==================================================================================================================================== -# Catalog API nach Liste der unterstützten Terminologien anfragen - Das Ergebnis wird in eine Datei geschrieben +# Request the Catalog API for a list of supported terminologies — the result will be written to a file echo "Downloading ZTS-Gesamtkatalog" curl --user-agent "{$USER_AGENT}" -X GET "{$CATALOG_API_ENDPOINT}" -H "Accept: application/json" -sS -o $CATALOG_METADATA_FILE -# Iterieren über alle Einträge des Katalogs +# Iterate over all entries in the catalog jq -r '.[].name' $CATALOG_METADATA_FILE | while read name; do - # Nur wenn die INCLUDE und EXCLUDE-Kriterien eingehalten werden, laden wir überhaupt Inhalte herunter + # Only if the INCLUDE and EXCLUDE criteria are met, content will be downloaded if [[ "$INCLUDE_PACKAGES" == *"$name"* || "$INCLUDE_PACKAGES" == "ALL" ]] && [[ ! "$EXCLUDE_PACKAGES" == *"$name"* ]]; then - # Paketmetadaten herunterladen + # Download package metadata curl --user-agent "{$USER_AGENT}" -sS -X GET "{$PACKAGE_API_ENDPOINT}/{$name}" -H "Accept: application/json" -o $PACKAGE_METADATA_FILE - # Downloadbedingungen des Pakets akzeptieren - # Wichtig: Informieren Sie sich vorab über die jeweils gültigen Downloadbedingungen. Dies kann über die Webseite erfolgen. + # Accept the package's download conditions + # Important: Please make sure to review the applicable download conditions in advance. This can be done via the website. DOWNLOAD_TOKEN=$(curl --user-agent "{$USER_AGENT}" -sS -X POST -H "Content-Type: application/json" -d "{\"packages\":[\"$name\"]}" $TOKEN_API_ENDPOINT | jq -r '.token') if [[ "$LATEST_ONLY" == true ]]; then - # Wir laden nur die als 'latest' gekennzeichnete Version des Pakets herunter + # We only download the version of the package marked as 'latest' - # latest version mit "jq" aus Datei extrahieren + # Extract the latest version from the file using "jq" PACKAGE_VERSION_LATEST=$(jq -r '."dist-tags".latest' $PACKAGE_METADATA_FILE) - # Wechsel ins Ausgabeverzeichnis + # Change to the output directory cd $OUTPUT_DIR - # Erwarteten Dateinamen berechnen + # Calculate the expected filename EXPECTED_FILE_NAME="$name-$PACKAGE_VERSION_LATEST.tar.gz" - # Paketversionen werden nur heruntergeladen, wenn es sie noch nicht gibt + # Package versions are only downloaded if they do not already exist if [ -f $EXPECTED_FILE_NAME ]; then echo "$EXPECTED_FILE_NAME existiert bereits. Es wird kein erneuter Download dieser Paketversion durchgeführt." else - # Latest Paketversion herunterladen (und Dateinamen aus Content-Disposition Header übernehmen) + # Download the latest package version (and take the filename from the Content-Disposition header) echo "Downloading $name#$PACKAGE_VERSION_LATEST" curl --user-agent "{$USER_AGENT}" -X GET "{$PACKAGE_API_ENDPOINT}/{$name}/{$PACKAGE_VERSION_LATEST}" -H "Authorization: Bearer $DOWNLOAD_TOKEN" -sS -O --remote-header-name fi - # Wechsel ins ursprüngliches Arbeitsverzeichnis + # Change back to the original working directory cd $CURRENT_DIR else - # Wir laden alle vorhandenen Versionen des Pakets herunter + # We download all available versions of the package jq -r '.versions | keys[]' $PACKAGE_METADATA_FILE | while read version; do - # Wechsel ins Ausgabeverzeichnis + # Change to the output directory cd $OUTPUT_DIR - # Erwarteten Dateinamen berechnen + # Calculate the expected filename EXPECTED_FILE_NAME="$name-$version.tar.gz" - # Paketversionen werden nur heruntergeladen, wenn es sie noch nicht gibt + # Package versions are only downloaded if they do not already exist if [ -f $EXPECTED_FILE_NAME ]; then echo "$EXPECTED_FILE_NAME existiert bereits. Es wird kein erneuter Download dieser Paketversion durchgeführt." else - # Latest Paketversion herunterladen (und Dateinamen aus Content-Disposition Header übernehmen) + # Download the package version (and take the filename from the Content-Disposition header) echo "Downloading $name#$version" curl --user-agent "{$USER_AGENT}" -X GET "{$PACKAGE_API_ENDPOINT}/{$name}/{$version}" -H "Authorization: Bearer $DOWNLOAD_TOKEN" -sS -O --remote-header-name fi - # Wechsel ins ursprüngliches Arbeitsverzeichnis + # Change back to the original working directory cd $CURRENT_DIR done fi - # Heruntergeladene Metadaten des Pakets löschen + # Delete the downloaded metadata of the package rm $PACKAGE_METADATA_FILE fi done -# Heruntergeladenen Katalog löschen +# Delete the downloaded metadata of the package rm $CATALOG_METADATA_FILE - diff --git a/images/Gematik_Logo_Flag_With_Background.png b/images/Gematik_Logo_Flag_With_Background.png new file mode 100644 index 0000000000000000000000000000000000000000..a3c929317c0f07ee752cafac1567e547b77c961c GIT binary patch literal 36991 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 N;uJN{<tkX*{2%Dqdd~m= literal 0 HcmV?d00001 diff --git a/npm/README.md b/npm/README.md index 2b56439..c1633d1 100644 --- a/npm/README.md +++ b/npm/README.md @@ -1,26 +1,41 @@ +<img align="right" width="250" height="47" src="../images/Gematik_Logo_Flag_With_Background.png"/> <br/> + # npm -## Voraussetzung +<details> + <summary>Table of Contents</summary> + <ol> + <li><a href="#about-the-project">About The Project</a></li> + <li><a href="#prerequisites">Prerequisites</a></li> + <li><a href="#preliminary-note">Preliminary Note</a></li> + <li><a href="#usage">Usage</a></li> + </ol> +</details> -Folgende Pakete werden zur Ausführung des Skripts benötigt: +## About The Project +Example configuration/instructions for using npm to download and extract FHIR packages. + +## Prerequisites +The following packages are required to run the script: - **npm** (node package manager) - [Website](https://www.npmjs.com/) -- **curl** (command line tool and library for transferring data with URLs) - [Website](https://curl.se/) -- **jq** (leightweight and flexible command-line JSON processor) - [Website](https://jqlang.github.io/jq/) +- **curl** (command-line tool and library for transferring data with URLs) - [Website](https://curl.se/) +- **jq** (lightweight and flexible command-line JSON processor) - [Website](https://jqlang.github.io/jq/) -## Vorbemerkung -Die vom ZTS angebotenen Inhalte unterliegen Downloadbedingungen, welche unter [https://terminologien.bfarm.de/download-conditions.html](https://terminologien.bfarm.de/download-conditions.html) eingesehen werden können. Bitte stellen Sie sicher, dass Sie die jeweils geltenden Bedingungen akzeptieren, bevor Sie das angebotenen Skript nutzen. Technisch wird das Akzeptieren der Downloadbedingungen durch die Verwendung eines Access Tokens zum Ausdruck gebracht, welches in der NPM-Konfigurationsdatei `.npmrc` hinterlegt werden kann. +## Preliminary Note +The content offered by ZTS is subject to download conditions, which can be viewed at [https://terminologien.bfarm.de/download-conditions.html](https://terminologien.bfarm.de/download-conditions.html). Please ensure that you accept the applicable terms before using the provided script. Technically, acceptance of the download conditions is expressed by using an access token, which can be stored in the NPM configuration file `.npmrc`. -## Erstellen der ```npm``` Konfiguration -Voraussetzung für die Verwendung von ```npm``` ist das Erstellen einer passenden Konfigurationsdatei, die u.a. die für den Zugriff auf die Registry erforderlichen Credentials (in Form eines Download Token) beinhaltet. Die Erstellung einer Konfigurationsdatei kann dabei sehr einfach über das beigefügte Skript ```create_npm_config.sh``` erfolgen. +## Usage +### Creating the ```npm``` Configuration +To use ```npm```, a suitable configuration file must be created, which includes, among other things, the credentials required for accessing the registry (in the form of a download token). Creating a configuration file can be done easily with the provided script ```create_npm_config.sh```. -Bevor das Skript gestartet werden kann, sind Anpassungen an dessen Inhalt erforderlich. Hierzu müssen in der Konfigurationsvariable ```ACCEPTED_DOWNLOAD_CONDITIONS``` alle Pakete aufgeführt werden, für die der Nutzer die Downloadbedingungen (s.o.) akzeptiert. +Before running the script, adjustments are required. The configuration variable ```ACCEPTED_DOWNLOAD_CONDITIONS``` must list all packages for which the user has accepted the download conditions (see above). -Über ```./create_npm_config.sh``` kann das Skript gestartet werden. Für die hinterlegten Pakete wird nun ein Download Token erzeugt und mit einer Vorlagendatei (```.npmrc.template```) kombiniert. +The script can be started using ```./create_npm_config.sh```. A download token will then be generated for the listed packages and combined with a template file (```.npmrc.template```). -## Download von Paketen über ```npm``` -Über folgendes Kommando kann der Download eines bestimmten Pakets (hier ICD-10-GM in der aktuellen Version) über ```npm```angestoßen werden: +### Downloading Packages via ```npm``` +The download of a specific package (e.g., ICD-10-GM in its current version) can be initiated using the following command: ```npm --registry https://terminologien.bfarm.de/packages install bfarm.terminologien.icd10gm --userconfig ./.npmrc --prefix ./.packages``` -Im Ergebnis wird ein Verzeichnis ```.packages```angelegt in welchem das entpackte FHIR-Package in der 'latest'-Version zu finden ist. \ No newline at end of file +As a result, a directory named ```.packages``` will be created, where the unpacked FHIR package in its 'latest' version can be found. diff --git a/npm/create_npm_config.sh b/npm/create_npm_config.sh index b66424d..e8b6887 100755 --- a/npm/create_npm_config.sh +++ b/npm/create_npm_config.sh @@ -1,42 +1,42 @@ #!/bin/bash # ==================================================================================================================================== -# Konfiguration +# Configuration # ==================================================================================================================================== -# Liste der akzeptierten Downloadbedingungen, e.g. 'bfarm.terminologien.abc,bfarm.terminologien.xyz' -# Die Liste der akzeptierten Downloadbedingungen kann über die Webseite (https://terminologien.bfarm.de) eingesehen werden. +# List of accepted download conditions, e.g. 'bfarm.terminologien.abc,bfarm.terminologien.xyz' +# The list of accepted download conditions can be viewed on the website (https://terminologien.bfarm.de). ACCEPTED_DOWNLOAD_CONDITIONS=bfarm.terminologien.abc,bfarm.terminologien.xyz -# Der Endpunkt der Token-API +# The endpoint of the token API TOKEN_API_ENDPOINT=https://terminologien.bfarm.de/api/generate-token -# Der Wert der im User-Agent-Header gesetzt werden soll +# The value to be set in the User-Agent header USER_AGENT=example-zts-client/1.0 # ==================================================================================================================================== -# Struktur für Request an TOKEN_API_ENDPOINT generieren +# Generate structure for the request to TOKEN_API_ENDPOINT # ==================================================================================================================================== -# Iterieren über die Liste der gemäß Konfiguration akzeptierten Downloadbedingungen +# Iterate over the list of accepted download conditions as defined in the configuration IFS=',' read -ra items <<< "$ACCEPTED_DOWNLOAD_CONDITIONS" PACKAGE_ARRAY="[" for item in "${items[@]}"; do PACKAGE_ARRAY+="\"$item\"," done -# Letztes Komma entfernen und Array schließen +# Remove the trailing comma and close the array PACKAGE_ARRAY="${PACKAGE_ARRAY%,}]" -# Request Body für Anfrage an Token-API erstellen +# Create request body for the request to the token API REQUEST_BODY="{\"packages\":$PACKAGE_ARRAY}" # ==================================================================================================================================== -# Token für den Download generieren +# Generate token for the download # ==================================================================================================================================== -# Downloadbedingungen des Pakets akzeptieren -# Wichtig: Informieren Sie sich vorab über die jeweils gültigen Downloadbedingungen. Dies kann über die Webseite erfolgen. +# Accept the package's download conditions +# Important: Make sure to review the applicable download conditions in advance. This can be done via the website. DOWNLOAD_TOKEN=$(curl --user-agent "{$USER_AGENT}" -sS -X POST -H "Content-Type: application/json" -d "$REQUEST_BODY" $TOKEN_API_ENDPOINT | jq -r '.token') echo "Download Token: $DOWNLOAD_TOKEN" if [[ -z "$DOWNLOAD_TOKEN" ]] || [[ "$DOWNLOAD_TOKEN" == "null" ]]; then @@ -45,10 +45,10 @@ if [[ -z "$DOWNLOAD_TOKEN" ]] || [[ "$DOWNLOAD_TOKEN" == "null" ]]; then fi # ==================================================================================================================================== -# Konfigurationsdatei für npm erstellen +# Create configuration file for npm # ==================================================================================================================================== -# Erstellen der Konfigurationsdatei aus dem Template +# Create the configuration file from the template cat .npmrc.template | \ sed "s/{{DOWNLOAD_TOKEN}}/$DOWNLOAD_TOKEN/g" > .npmrc echo "Konfigurationsdatei erstellt" \ No newline at end of file diff --git a/sushi-wrap/BfArM-Package-Test/sushi-wrap.sh b/sushi-wrap/BfArM-Package-Test/sushi-wrap.sh index 71b724b..5ed79c3 100755 --- a/sushi-wrap/BfArM-Package-Test/sushi-wrap.sh +++ b/sushi-wrap/BfArM-Package-Test/sushi-wrap.sh @@ -1,72 +1,72 @@ #!/bin/bash # ==================================================================================================================================== -# Konfiguration +# Configuration # ==================================================================================================================================== -# Liste der akzeptierten Downloadbedingungen, e.g. 'bfarm.terminologien.abc,bfarm.terminologien.xyz' -# Die Liste der akzeptierten Downloadbedingungen kann über die Webseite (https://terminologien.bfarm.de) eingesehen werden. +# List of accepted download conditions, e.g. 'bfarm.terminologien.abc,bfarm.terminologien.xyz' +# The list of accepted download conditions can be viewed on the website (https://terminologien.bfarm.de). ACCEPTED_DOWNLOAD_CONDITIONS=bfarm.terminologien.abc,bfarm.terminologien.xyz -# Der Wert der im User-Agent-Header gesetzt werden soll +# The value to be set in the User-Agent header USER_AGENT=example-zts-client/1.0 -# Endpunktadressen der ZTS-API +# Endpoint addresses of the ZTS API CATALOG_API_ENDPOINT=https://terminologien.bfarm.de/packages/catalog PACKAGE_API_ENDPOINT=https://terminologien.bfarm.de/packages TOKEN_API_ENDPOINT=https://terminologien.bfarm.de/api/generate-token -# Pfad-/Dateinamen für temporäre Arbeitsdateien +# Path/filenames for temporary working files CATALOG_METADATA_FILE=catalog.json FHIR_HOME=~/.fhir OUTPUT_DIR=$(uuidgen) CURRENT_DIR=$(pwd) -# Dies und Das +# This and that DEBUG=false # ==================================================================================================================================== -# Hilfsfunktionen +# Helper functions # ==================================================================================================================================== -# Funktion, die prüft, ob ein Element in einem Array enthalten ist +# Function that checks if an element is present in an array contains_element() { local element="$1" shift local array=("$@") for e in "${array[@]}"; do if [[ "$e" == "$element" ]]; then - return 0 # gefunden + return 0 # found fi done - return 1 # nicht gefunden + return 1 # not found } # ==================================================================================================================================== -# Vorbereiten der Umgebung +# Preparing the environment # ==================================================================================================================================== -# Anlegen eines (temporären) Ausgabeverzeichnisses +# Create a (temporary) output directory mkdir $OUTPUT_DIR -# Umwandeln der Liste der akzeptierten Downloadbedingungen in ein Array +# Convert the list of accepted download conditions into an array IFS=',' read -ra accepted_conditions_packages <<< "$ACCEPTED_DOWNLOAD_CONDITIONS" echo "Pakete für die Downloadbedingungen akzeptiert wurden: ${accepted_conditions_packages[@]}" # ==================================================================================================================================== -# Abruf der Liste unterstützten Pakete +# Retrieve the list of supported packages # ==================================================================================================================================== -# Catalog API nach Liste der unterstützten Terminologien anfragen - Das Ergebnis wird in eine Datei geschrieben +# Request the Catalog API for a list of supported terminologies — the result will be written to a file curl --user-agent "{$USER_AGENT}" -X GET "{$CATALOG_API_ENDPOINT}" -H "Accept: application/json" -sS -o $CATALOG_METADATA_FILE -# Katalog in Array umwandeln, welches die Namen der unterstützten Pakete enthält. Das sind die Pakete, die auf dem ZTS verfügbar sind und heruntergelden werden können. +# Convert the catalog into an array containing the names of supported packages. These are the packages available on the ZTS and can be downloaded. available_packages=($(jq -r '.[].name' "$CATALOG_METADATA_FILE")) if [[ "$DEBUG" == "true" ]]; then echo "Auf ZTS verwaltete Pakete: ${available_packages[@]}" fi -# Schnittmenge zwischen den akzeptierten Paketen und den auf dem ZTS verfügbaren Paketen bilden. Das sind die Pakete, die heruntergeladen werden dürfen. +# Create the intersection between the accepted packages and the packages available on the ZTS. These are the packages that can be downloaded. downloadable_packages=() for item in "${accepted_conditions_packages[@]}"; do for element in "${available_packages[@]}"; do @@ -81,16 +81,16 @@ if [[ "$DEBUG" == "true" ]]; then fi # ==================================================================================================================================== -# Abhängigkeiten verarbeiten +# Process dependencies # ==================================================================================================================================== -# Abhängigkeiten aus der Konfigurationsdatei extrahieren und in ein Array umwandeln +# Extract dependencies from the configuration file and convert them into an array dependencies=($(yq '.dependencies' sushi-config.yaml | sed 's/:.*//')) if [[ "$DEBUG" == "true" ]]; then echo "Definierte Paketabhängigkeiten: ${dependencies[@]}" fi -# Schnittmenge zwischen den benötigten Paketen und den herunterladbaren Paketen bilden +# Create the intersection between the required packages and the downloadable packages final_packages=() for item in "${dependencies[@]}"; do for element in "${downloadable_packages[@]}"; do @@ -105,44 +105,44 @@ if [[ "$DEBUG" == "true" ]]; then fi # ==================================================================================================================================== -# Struktur für Request an TOKEN_API_ENDPOINT generieren +# Generate structure for the request to TOKEN_API_ENDPOINT # ==================================================================================================================================== -# Array für Anfrage Body vorbereiten +# Prepare array for request body PACKAGE_ARRAY="[" for item in "${downloadable_packages[@]}"; do PACKAGE_ARRAY+="\"$item\"," done -# Letztes Komma entfernen und Array schließen +# Remove trailing comma and close the array PACKAGE_ARRAY="${PACKAGE_ARRAY%,}]" -# Request Body für Anfrage an Token-API erstellen +# Create request body for the request to the Token API REQUEST_BODY="{\"packages\":$PACKAGE_ARRAY}" # ==================================================================================================================================== -# Token für den Download generieren +# # Generate token for the download # ==================================================================================================================================== -# Downloadbedingungen des Pakets akzeptieren -# Wichtig: Informieren Sie sich vorab über die jeweils gültigen Downloadbedingungen. Dies kann über die Webseite erfolgen. +# Accept the package's download conditions +# Important: Please make sure to review the applicable download conditions in advance. This can be done via the website. DOWNLOAD_TOKEN=$(curl --user-agent "{$USER_AGENT}" -sS -X POST -H "Content-Type: application/json" -d "$REQUEST_BODY" $TOKEN_API_ENDPOINT | jq -r '.token') if [[ "$DEBUG" == "true" ]]; then echo "Download Token: $DOWNLOAD_TOKEN" fi # ==================================================================================================================================== -# Download der Pakete +# Download Packages # ==================================================================================================================================== -# Iterieren über die definierten Paketabhängigkeiten +# Iterate over the defined package dependencies yq '.dependencies' sushi-config.yaml | while read package_version; do - # Paketname und Paketversion extrahieren + # Extract package name and package version name=$(echo $package_version | sed 's/:.*//' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') version=$(echo $package_version | sed 's/.*://' | sed 's/^[[:space:]]*//; s/[[:space:]]*$//') - # Nur wenn das Paket in der Liste der herunterladbaren Pakete enthalten ist, wird es heruntergeladen + # The package will only be downloaded if it is included in the list of downloadable packages if contains_element $name "${downloadable_packages[@]}"; then echo "Downloading $name#$version" curl --user-agent "{$USER_AGENT}" -sS -X GET "{$PACKAGE_API_ENDPOINT}/{$name}/{$version}" -H "Authorization: Bearer $DOWNLOAD_TOKEN" -O --remote-header-name --output-dir $OUTPUT_DIR @@ -152,27 +152,27 @@ yq '.dependencies' sushi-config.yaml | while read package_version; do done # ==================================================================================================================================== -# Heruntergeladene Pakete verarbeiten und in das FHIR-Verzeichnis verschieben +# # Process downloaded packages and move them to the FHIR directory # ==================================================================================================================================== cd $OUTPUT_DIR for file in *.tar.gz; do - # Paketname und Paketversion extrahieren + # Extract package name and package version export PACKAGE_NAME=$(echo $file | sed 's/-.*//') export PACKAGE_VERSION=$(echo $file | sed 's/.*-\([0-9.]*\)\..*/\1/') - # Verzeichnis für das Paket anlegen + # Create directory for the package mkdir $PACKAGE_NAME#$PACKAGE_VERSION - # Entpacken des Pakets + # Extract the package tar -xzf $file -C $PACKAGE_NAME#$PACKAGE_VERSION - # Paketdatei löschen + # Delete the package file rm $file - # Verschieben des entpackten Pakets in das FHIR-Verzeichnis + # Move the extracted package to the FHIR directory if [ -d $FHIR_HOME/packages/$PACKAGE_NAME#$PACKAGE_VERSION ]; then echo "Das Paket $PACKAGE_NAME#$PACKAGE_VERSION existiert bereits." else @@ -180,13 +180,13 @@ for file in *.tar.gz; do fi done -# Wechsel ins ursprüngliche Arbeitsverzeichnis und Aufräumen +# Change back to the original working directory and clean up cd $CURRENT_DIR rm -rf $OUTPUT_DIR rm $CATALOG_METADATA_FILE # ==================================================================================================================================== -# Sushi aufrufen +# Call sushi # ==================================================================================================================================== sushi . diff --git a/sushi-wrap/README.md b/sushi-wrap/README.md index 71b9d7e..4040e41 100644 --- a/sushi-wrap/README.md +++ b/sushi-wrap/README.md @@ -1,32 +1,47 @@ +<img align="right" width="250" height="47" src="../images/Gematik_Logo_Flag_With_Background.png"/> <br/> + # sushi-wrap -## Voraussetzung +<details> + <summary>Table of Contents</summary> + <ol> + <li><a href="#about-the-project">About The Project</a></li> + <li><a href="#prerequisites">Prerequisites</a></li> + <li><a href="#preliminary-note">Preliminary Note</a></li> + <li><a href="#structure-and-functionality">Structure and Functionality</a></li> + <li><a href="#usage">Usage</a></li> + </ol> +</details> -Folgende Pakete werden zur Ausführung des Skripts benötigt: +## About The Project +Example wrapper script to integrate an automated package download into Sushi workflows. -- **curl** (command line tool and library for transferring data with URLs) - [Website](https://curl.se/) -- **yq** (lightweight and portable command-line YAML processor) - [Website](https://github.com/mikefarah/yq/) -- **jq** (leightweight and flexible command-line JSON processor) - [Website](https://jqlang.github.io/jq/) +## Prerequisites +The following packages are required to run the script: -## Vorbemerkung -Die vom ZTS angebotenen Inhalte unterliegen Downloadbedingungen, welche unter [https://terminologien.bfarm.de/download-conditions.html](https://terminologien.bfarm.de/download-conditions.html) eingesehen werden können. Bitte stellen Sie sicher, dass Sie die jeweils geltenden Bedingungen akzeptieren, bevor Sie das angebotenen Skript nutzen. Technisch wird das Akzeptieren der Downloadbedingungen durch die Verwendung eines Access Tokens zum Ausdruck gebracht, welches während der Ausführung des Wrapper-Skripts erzeugt wird. +- **curl** (command-line tool and library for transferring data with URLs) - [Website](https://curl.se/) +- **yq** (lightweight and portable command-line YAML processor) - [Website](https://github.com/mikefarah/yq/) +- **jq** (lightweight and flexible command-line JSON processor) - [Website](https://jqlang.github.io/jq/) -## Struktur und Funktionsweise -Das Verzeichnis ```/BfArM-Package-Test``` enthält eine "normales" Sushi-Beispiel-Projekt, welches um ein Wrapper-Skript (```sushi-wrap```) ergänzt wurde. Dieses Skript funktioniert dabei nach folgendem Muster: +## Preliminary Note +The content offered by the ZTS is subject to download conditions, which can be viewed at [https://terminologien.bfarm.de/download-conditions.html](https://terminologien.bfarm.de/download-conditions.html). Please ensure that you accept the applicable terms and conditions before using the provided script. Technically, acceptance of the download conditions is expressed by using an access token, which is generated during the execution of the wrapper script. -1. Abruf der Liste vom ZTS unterstützter Pakete über die Catalog API -2. Abgleich der heruntergeladenen Liste mit Liste der akzeptierten Downloadbedingungen -3. Parsen der Datei ```sushi-config.yaml```mittels ```yq``` -4. Herunterladen aller Abhängigkeiten, die vom ZTS bereitgestellt werden und für die die Downloadbedingungen akzeptiert wurden -5. Entpacken der heruntergeladenen Paket-Versionen und verschieben der Dateien in das FHIR-Home-Verzeichnis -6. Aufräumen -7. Ausführen von ```sushi``` +## Structure and Functionality +The directory ```/BfArM-Package-Test``` contains a "normal" Sushi example project, which has been supplemented with a wrapper script (```sushi-wrap.sh```). This script works according to the following pattern: -Das Wrapper-Skript kann in beliebigen sushi-Projekten zum Einsatz kommen. +1. Retrieve the list of packages supported by ZTS via the Catalog API +2. Compare the downloaded list with the list of accepted download conditions +3. Parse the ```sushi-config.yaml``` file using ```yq``` +4. Download all dependencies provided by ZTS for which the download conditions have been accepted +5. Unpack the downloaded package versions and move the files to the FHIR home directory +6. Clean up +7. Execute ```sushi``` -## Notwendige Anpassungen am Wrapper-Skript -Bevor das Wrapper-Skript genutzt werden kann, sind Anpassungen an dessen Inhalt erforderlich. Hierzu müssen in der Konfigurationsvariable ```ACCEPTED_DOWNLOAD_CONDITIONS``` alle Pakete aufgeführt werden, für die der Nutzer die Downloadbedingungen (s.o.) akzeptiert. +The wrapper script can be used in any sushi project. -## Starten des Wrapper-Skripts -Durch den Aufruf von ```./sushi-wrap.sh```aus dem ```/BfArM-Package-Test```-Verzeichnis heraus, kann das Wrapper-Skript gestartet werden. +## Usage +### Required Adjustments to the Wrapper Script +Before the wrapper script can be used, adjustments are required. In particular, the configuration variable ```ACCEPTED_DOWNLOAD_CONDITIONS``` must include all packages for which the user has accepted the download conditions (see above). +### Starting the Wrapper Script +The wrapper script can be started by executing ```./sushi-wrap.sh``` from within the ```/BfArM-Package-Test``` directory. \ No newline at end of file -- GitLab