diff --git a/.github/workflows/build-images.yml b/.github/workflows/build-images.yml new file mode 100644 index 00000000..3178c66c --- /dev/null +++ b/.github/workflows/build-images.yml @@ -0,0 +1,110 @@ +name: build-images +run-name: build-images ${{ github.event.release.tag_name }} +on: + release: + types: [published] + +permissions: + contents: read + packages: write + +jobs: + prepare: + if: ${{ github.event_name == 'release' }} + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.release_tag.outputs.tag }} + version: ${{ steps.release_tag.outputs.version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Resolve release tag & version + id: release_tag + run: | + git fetch --tags --force + TAG="${{ github.event.release.tag_name }}" + if [ -z "$TAG" ]; then + echo "No Git tag found to check out" >&2 + exit 1 + fi + VER_NO_V="${TAG#v}" + echo "tag=$TAG" >> $GITHUB_OUTPUT + echo "version=$VER_NO_V" >> $GITHUB_OUTPUT + + build-image: + needs: prepare + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - name: rag-backend + dockerfile: services/rag-backend/Dockerfile + - name: admin-backend + dockerfile: services/admin-backend/Dockerfile + - name: document-extractor + dockerfile: services/document-extractor/Dockerfile + - name: mcp-server + dockerfile: services/mcp-server/Dockerfile + - name: frontend + dockerfile: services/frontend/apps/chat-app/Dockerfile + - name: admin-frontend + dockerfile: services/frontend/apps/admin-app/Dockerfile + env: + REGISTRY: ghcr.io + IMAGE_NS: ${{ github.repository }} + VERSION: ${{ needs.prepare.outputs.version }} + TAG: ${{ needs.prepare.outputs.tag }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Checkout release tag + run: git checkout "$TAG" + - name: Normalize IMAGE_NS to lowercase + run: echo "IMAGE_NS=$(echo '${{ env.IMAGE_NS }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.PR_AUTOMATION_TOKEN }} + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + - name: Build & push ${{ matrix.name }} + run: | + docker buildx build --push \ + -t "$REGISTRY/$IMAGE_NS/${{ matrix.name }}:${VERSION}" \ + -t "$REGISTRY/$IMAGE_NS/${{ matrix.name }}:latest" \ + -f "${{ matrix.dockerfile }}" . + - name: Capture digest + run: | + sudo apt-get update && sudo apt-get install -y jq + ref="$REGISTRY/$IMAGE_NS/${{ matrix.name }}:${VERSION}" + digest=$(docker buildx imagetools inspect "$ref" --format '{{json .Manifest.Digest}}' | jq -r . || true) + jq -n --arg name "${{ matrix.name }}" --arg tag "$VERSION" --arg digest "$digest" '{($name): {tag: $tag, digest: $digest}}' > digest.json + - name: Upload digest artifact + uses: actions/upload-artifact@v4 + with: + name: image-digest-${{ matrix.name }} + path: digest.json + + collect-digests: + needs: [build-image] + runs-on: ubuntu-latest + steps: + - name: Download digest artifacts + uses: actions/download-artifact@v4 + with: + pattern: image-digest-* + merge-multiple: false + - name: Merge digests + run: | + sudo apt-get update && sudo apt-get install -y jq + jq -s 'reduce .[] as $item ({}; . * $item)' image-digest-*/digest.json > image-digests.json + - name: Upload merged digests + uses: actions/upload-artifact@v4 + with: + name: image-digests + path: image-digests.json diff --git a/.github/workflows/bump-chart-version.yml b/.github/workflows/bump-chart-version.yml new file mode 100644 index 00000000..db83a823 --- /dev/null +++ b/.github/workflows/bump-chart-version.yml @@ -0,0 +1,59 @@ +name: bump-chart-version +on: + workflow_dispatch: + inputs: + chart_version: + description: "Chart version to set (does not touch appVersion)" + required: true + type: string + ref: + description: "Git ref to bump (default: main)" + required: false + type: string + +permissions: + contents: write + pull-requests: write + +jobs: + bump: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref || 'main' }} + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install deps + run: | + python -m pip install --upgrade pip + python -m pip install "packaging==25.0" "ruamel.yaml==0.18.6" + + - name: Bump chart version only + env: + CHART_VERSION: ${{ inputs.chart_version }} + run: | + if [ -z "${CHART_VERSION}" ]; then + echo "chart_version input is required" >&2 + exit 1 + fi + python tools/bump_chart_versions.py --mode chart-only --chart-version "$CHART_VERSION" + + - name: Open PR for chart version bump + uses: peter-evans/create-pull-request@v6 + with: + base: main + branch: chore/chart-bump-${{ inputs.chart_version }} + title: "chore(release): bump chart version to ${{ inputs.chart_version }}" + body: | + Bump Chart.yaml version to ${{ inputs.chart_version }} (appVersion unchanged). + commit-message: "chore(release): bump chart version to ${{ inputs.chart_version }}" + add-paths: | + infrastructure/**/Chart.yaml + token: ${{ secrets.PR_AUTOMATION_TOKEN }} + labels: chart-bump diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml new file mode 100644 index 00000000..49a875a0 --- /dev/null +++ b/.github/workflows/create-release.yml @@ -0,0 +1,68 @@ +name: create-release +on: + pull_request_target: + types: [closed] + branches: [main] + +permissions: + contents: write + +jobs: + release: + if: >- + ${{ + github.event.pull_request.merged == true && + contains(github.event.pull_request.labels.*.name, 'refresh-locks') + }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.PR_AUTOMATION_TOKEN }} + + - name: Derive version from PR title + id: ver + run: | + TITLE="${{ github.event.pull_request.title }}" + VERSION=$(echo "$TITLE" | sed -nE 's/.*([0-9]+\.[0-9]+\.[0-9]+(\.post[0-9]+)?).*/\1/p' || true) + if [ -z "$VERSION" ]; then + echo "Could not extract version from PR title: $TITLE" >&2 + exit 1 + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Verify appVersion matches release version (clean semver) + env: + RELEASE_VERSION: ${{ steps.ver.outputs.version }} + run: | + if echo "$RELEASE_VERSION" | grep -q '\.post'; then + echo "Release version must be clean semver (no .post): $RELEASE_VERSION" >&2 + exit 1 + fi + APP_VERSION=$(awk '/^appVersion:/ {print $2}' infrastructure/rag/Chart.yaml | tr -d "\"'") + if [ -z "$APP_VERSION" ]; then + echo "Could not read appVersion from infrastructure/rag/Chart.yaml" >&2 + exit 1 + fi + NORMALIZED_APP_VERSION="${APP_VERSION#v}" + NORMALIZED_APP_VERSION="${NORMALIZED_APP_VERSION#V}" + if [ "$NORMALIZED_APP_VERSION" != "$RELEASE_VERSION" ]; then + echo "Chart appVersion ($APP_VERSION) does not match release version ($RELEASE_VERSION)" >&2 + exit 1 + fi + + - name: Create Git tag + run: | + git config user.name "github-actions" + git config user.email "github-actions@github.com" + git tag -a "v${{ steps.ver.outputs.version }}" -m "Release v${{ steps.ver.outputs.version }}" + git push origin "v${{ steps.ver.outputs.version }}" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: v${{ steps.ver.outputs.version }} + name: v${{ steps.ver.outputs.version }} + generate_release_notes: true + token: ${{ secrets.PR_AUTOMATION_TOKEN }} diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 27b26b27..00182d9b 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -12,6 +12,12 @@ env: jobs: changes: + if: >- + ${{ + !contains(github.event.pull_request.labels.*.name, 'prepare-release') && + !contains(github.event.pull_request.labels.*.name, 'refresh-locks') && + !contains(github.event.pull_request.labels.*.name, 'chart-bump') + }} name: Detect Changes runs-on: ubuntu-latest outputs: diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml new file mode 100644 index 00000000..19f5620b --- /dev/null +++ b/.github/workflows/prepare-release.yml @@ -0,0 +1,116 @@ +name: prepare-release +on: + pull_request: + types: [closed] + branches: + - main + workflow_dispatch: + inputs: + version: + description: "Override release version (e.g., 3.5.0.postYYYYMMDDHHMMSS). If empty, semantic-release dry-run is used." + required: false + type: string + +permissions: + contents: write + pull-requests: write + +jobs: + changes: + if: >- + ${{ + github.event_name == 'workflow_dispatch' || + ( + github.event.pull_request.merged && + !contains(github.event.pull_request.labels.*.name, 'prepare-release') && + !contains(github.event.pull_request.labels.*.name, 'refresh-locks') && + !contains(github.event.pull_request.labels.*.name, 'chart-bump') + ) + }} + name: Detect release-relevant changes + runs-on: ubuntu-latest + outputs: + releasable: ${{ steps.manual.outputs.releasable || steps.filter.outputs.releasable }} + steps: + - name: Allow manual run + id: manual + if: ${{ github.event_name == 'workflow_dispatch' }} + run: echo "releasable=true" >> "$GITHUB_OUTPUT" + + - uses: actions/checkout@v4 + if: ${{ github.event_name == 'pull_request' }} + with: + fetch-depth: 0 + + - name: Filter paths + id: filter + if: ${{ github.event_name == 'pull_request' }} + uses: dorny/paths-filter@v2 + with: + filters: | + releasable: + - 'services/**' + - 'libs/**' + + prepare: + if: ${{ needs.changes.outputs.releasable == 'true' }} + runs-on: ubuntu-latest + needs: [changes] + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: '25' + + - name: Install semantic-release deps + run: npm ci + + - name: verify-dependencies-integrity + run: npm audit signatures + + - name: Compute next version (dry-run) + id: semrel + env: + GITHUB_TOKEN: ${{ secrets.PR_AUTOMATION_TOKEN }} + run: | + if [ -n "${{ github.event.inputs.version }}" ]; then + echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT + exit 0 + fi + npx semantic-release --dry-run --no-ci | tee semrel.log + BASE_VERSION=$(grep -Eo "next release version is [0-9]+\.[0-9]+\.[0-9]+" semrel.log | awk '{print $5}') + if [ -z "$BASE_VERSION" ]; then echo "No new release required"; exit 1; fi + VERSION="${BASE_VERSION}.post$(date +%Y%m%d%H%M%S)" + echo "version=$VERSION" >> $GITHUB_OUTPUT + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install bump script deps + run: | + python -m pip install --upgrade pip + python -m pip install "tomlkit==0.13.3" "pyyaml==6.0.2" "packaging==25.0" + + - name: Bump internal libs only (no service pins) + run: | + python tools/bump_pyproject_deps.py --version "${{ steps.semrel.outputs.version }}" --bump-libs + + - name: Commit and open PR + uses: peter-evans/create-pull-request@v6 + with: + branch: chore/release-${{ steps.semrel.outputs.version }} + title: "chore(release): prepare ${{ steps.semrel.outputs.version }}" + body: | + Prepare release ${{ steps.semrel.outputs.version }} + - bump internal libs versions only + commit-message: "chore(release): prepare ${{ steps.semrel.outputs.version }}" + add-paths: | + libs/**/pyproject.toml + labels: prepare-release + token: ${{ secrets.PR_AUTOMATION_TOKEN }} diff --git a/.github/workflows/promote-clean-semver.yml b/.github/workflows/promote-clean-semver.yml new file mode 100644 index 00000000..565ea9b5 --- /dev/null +++ b/.github/workflows/promote-clean-semver.yml @@ -0,0 +1,205 @@ +name: promote-clean-semver +on: + workflow_dispatch: + inputs: + clean_version: + description: "Clean semver to promote (no .post)" + required: true + type: string + ref: + description: "Git ref to use (defaults to main)" + required: false + type: string + pre_version: + description: "Pre-release version (optional, for bookkeeping)" + required: false + type: string + dry_run: + description: "If true, skip publishing to PyPI (only TestPyPI)" + required: false + default: false + type: boolean + +permissions: + contents: write + pull-requests: write + packages: write + +jobs: + promote: + name: Publish clean semver, refresh locks, bump appVersion + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref || 'main' }} + + - name: Load version metadata (workflow_run) + if: ${{ github.event_name == 'workflow_run' }} + uses: actions/download-artifact@v4 + with: + name: pre-release-meta + github-token: ${{ secrets.GITHUB_TOKEN }} + run-id: ${{ github.event.workflow_run.id }} + path: meta + + - name: Determine versions + id: versions + run: | + set -euo pipefail + CLEAN_VERSION_INPUT="${{ inputs.clean_version || '' }}" + if [ -f meta/version.env ]; then + source meta/version.env + fi + CLEAN_VERSION="${CLEAN_VERSION_INPUT:-${CLEAN_VERSION:-}}" + if [ -z "${CLEAN_VERSION:-}" ]; then + echo "CLEAN_VERSION is required (input or artifact)" >&2 + exit 1 + fi + # Allow optional leading "v" in input (e.g., v3.5.5) + CLEAN_VERSION="${CLEAN_VERSION#v}" + CLEAN_VERSION="${CLEAN_VERSION#V}" + CLEAN_VERSION_TAG="v${CLEAN_VERSION}" + if echo "$CLEAN_VERSION" | grep -q '\.post'; then + echo "CLEAN_VERSION must be clean semver (no .post): $CLEAN_VERSION" >&2 + exit 1 + fi + echo "clean_version=$CLEAN_VERSION" >> $GITHUB_OUTPUT + echo "clean_version_tag=$CLEAN_VERSION_TAG" >> $GITHUB_OUTPUT + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install Poetry and deps + run: | + pip install poetry==2.1.3 + python -m pip install --upgrade pip + python -m pip install "tomlkit==0.13.3" "pyyaml==6.0.2" "packaging==25.0" "ruamel.yaml==0.18.6" + + - name: Configure TestPyPI repository + run: | + poetry config repositories.testpypi https://test.pypi.org/legacy/ + + - name: Install jq + run: sudo apt-get update && sudo apt-get install -y jq + + - name: Update internal libs and service pins to clean version + env: + VERSION: ${{ steps.versions.outputs.clean_version }} + run: | + python tools/bump_pyproject_deps.py --version "$VERSION" --bump-libs --bump-service-pins + + - name: Publish clean semver to TestPyPI and PyPI (core-first) + env: + CLEAN_VERSION: ${{ steps.versions.outputs.clean_version }} + POETRY_HTTP_BASIC_TESTPYPI_USERNAME: __token__ + POETRY_HTTP_BASIC_TESTPYPI_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} + POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_TOKEN }} + DRY_RUN: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run || 'false' }} + run: | + set -euo pipefail + if [ -z "${POETRY_HTTP_BASIC_TESTPYPI_PASSWORD:-}" ]; then + echo "Missing TEST_PYPI_TOKEN secret" >&2 + exit 1 + fi + if [ "${DRY_RUN:-false}" != "true" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then + echo "Missing PYPI_TOKEN secret" >&2 + exit 1 + fi + + source tools/publish_libs.sh + + echo "Publishing clean version $CLEAN_VERSION (core-first) to TestPyPI..." + publish_lib "rag-core-lib" "-r testpypi" "$CLEAN_VERSION" + wait_for_index "rag-core-lib" "$CLEAN_VERSION" "https://test.pypi.org" "TestPyPI" + for lib in rag-core-api admin-api-lib extractor-api-lib; do + publish_lib "$lib" "-r testpypi" "$CLEAN_VERSION" + done + + if [ "${DRY_RUN:-false}" = "true" ]; then + echo "Dry run enabled: skipping PyPI publish." + else + echo "Publishing clean version $CLEAN_VERSION (core-first) to PyPI..." + publish_lib "rag-core-lib" "" "$CLEAN_VERSION" + wait_for_index "rag-core-lib" "$CLEAN_VERSION" "https://pypi.org" "PyPI" + for lib in rag-core-api admin-api-lib extractor-api-lib; do + publish_lib "$lib" "" "$CLEAN_VERSION" + done + fi + + - name: Clear poetry caches + run: | + poetry cache clear --all pypi -n || true + poetry cache clear --all testpypi -n || true + + - name: Force rag-core-lib from TestPyPI for dry-run locking + if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.dry_run == 'true' }} + run: | + python tools/set_rag_core_lib_testpypi_source.py + + - name: Refresh lib lockfiles + env: + VERSION: ${{ steps.versions.outputs.clean_version }} + run: | + for lib in libs/rag-core-lib libs/rag-core-api libs/admin-api-lib libs/extractor-api-lib; do + if [ -f "$lib/pyproject.toml" ]; then + echo "Locking $lib" + ( + cd "$lib" + poetry lock -v || ( + echo "Lock failed, clearing caches and retrying..."; + poetry cache clear --all pypi -n || true; + poetry cache clear --all testpypi -n || true; + sleep 10; + poetry lock -v + ) + ) + fi + done + + - name: Refresh service lockfiles + env: + VERSION: ${{ steps.versions.outputs.clean_version }} + run: | + for svc in services/rag-backend services/admin-backend services/document-extractor services/mcp-server; do + if [ -f "$svc/pyproject.toml" ]; then + echo "Locking $svc" + ( + cd "$svc" + poetry lock -v || ( + echo "Lock failed, clearing caches and retrying..."; + poetry cache clear --all pypi -n || true; + poetry cache clear --all testpypi -n || true; + sleep 10; + poetry lock -v + ) + ) + fi + done + + - name: Bump Chart appVersion to clean version (leave chart version for manual chart publish) + env: + APP_VERSION: ${{ steps.versions.outputs.clean_version_tag }} + run: | + python tools/bump_chart_versions.py --app-version "$APP_VERSION" --mode app-only + + - name: Open PR with updated locks, pins, and Chart appVersion + id: cpr + uses: peter-evans/create-pull-request@v6 + with: + branch: chore/refresh-locks-${{ steps.versions.outputs.clean_version }}-${{ github.run_number }} + title: "chore(release): refresh service lockfiles for ${{ steps.versions.outputs.clean_version }}" + body: | + Refresh service poetry.lock files, dependency pins, and Chart appVersion for version ${{ steps.versions.outputs.clean_version }}. + commit-message: "chore(release): refresh service lockfiles, pins, and Chart appVersion" + add-paths: | + services/**/pyproject.toml + services/**/poetry.lock + infrastructure/**/Chart.yaml + libs/**/pyproject.toml + libs/**/poetry.lock + labels: refresh-locks + token: ${{ secrets.PR_AUTOMATION_TOKEN }} diff --git a/.github/workflows/publish-chart-packages.yml b/.github/workflows/publish-chart-packages.yml new file mode 100644 index 00000000..9ca793cf --- /dev/null +++ b/.github/workflows/publish-chart-packages.yml @@ -0,0 +1,133 @@ +name: publish-chart-packages +on: + push: + branches: [main] + workflow_dispatch: + inputs: + chart_version: + description: "Chart version to publish (default: read from Chart.yaml)" + required: false + type: string + ref: + description: "Git ref to package from (default: main)" + required: false + type: string + +permissions: + contents: write + pull-requests: read + packages: write + pages: write + id-token: write + +env: + OCI_REGISTRY: ghcr.io + +jobs: + gate: + runs-on: ubuntu-latest + outputs: + allow: ${{ steps.allow_manual.outputs.allow || steps.allow_push.outputs.allow }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Allow manual run + id: allow_manual + if: ${{ github.event_name == 'workflow_dispatch' }} + run: echo "allow=true" >> "$GITHUB_OUTPUT" + + - name: Check chart-bump label on merged PR + id: allow_push + if: ${{ github.event_name == 'push' }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + python tools/allow_chart_bump.py + + publish: + needs: gate + runs-on: ubuntu-latest + if: ${{ needs.gate.outputs.allow == 'true' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ inputs.ref || 'main' }} + + - name: Setup Helm + uses: azure/setup-helm@v4 + + - name: Login to GHCR for Helm OCI + run: echo ${{ secrets.PR_AUTOMATION_TOKEN }} | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Determine chart version + id: meta + run: | + set -euo pipefail + INPUT_VER="${{ inputs.chart_version }}" + FILE_VER=$(awk '/^version:/ {print $2}' infrastructure/rag/Chart.yaml | tr -d "\"'") + CHART_VERSION="${INPUT_VER:-$FILE_VER}" + if [ -z "$CHART_VERSION" ]; then + echo "Could not determine chart version" >&2 + exit 1 + fi + echo "chart_version=$CHART_VERSION" >> $GITHUB_OUTPUT + + - name: Verify chart version matches input (if provided) + env: + INPUT_VER: ${{ inputs.chart_version }} + FILE_VER: ${{ steps.meta.outputs.chart_version }} + run: | + if [ -n "$INPUT_VER" ] && [ "$INPUT_VER" != "$FILE_VER" ]; then + echo "Chart.yaml version ($FILE_VER) does not match input $INPUT_VER" >&2 + exit 1 + fi + + - name: Package chart + run: | + set -euo pipefail + CHART_DIR="infrastructure/rag" + mkdir -p dist + helm dependency update "$CHART_DIR" || true + helm package "$CHART_DIR" --destination dist + ls -la dist + + - name: Push chart to GHCR (OCI) + env: + CHART_VERSION: ${{ steps.meta.outputs.chart_version }} + run: | + set -euo pipefail + PKG=$(ls dist/*.tgz) + helm show chart "$PKG" | grep -E "^version: " + helm push "$PKG" oci://$OCI_REGISTRY/${{ github.repository_owner }}/charts + + - name: Build Helm repo index for Pages + env: + CHART_VERSION: ${{ steps.meta.outputs.chart_version }} + run: | + set -euo pipefail + PKG=$(ls dist/*.tgz) + REPO="${GITHUB_REPOSITORY#*/}" + BASE_URL="https://${GITHUB_REPOSITORY_OWNER}.github.io/${REPO}" + helm repo index dist --url "$BASE_URL" + echo "Index generated for $BASE_URL" + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: dist + + deploy-pages: + needs: publish + runs-on: ubuntu-latest + if: ${{ needs.publish.result == 'success' }} + permissions: + pages: write + id-token: write + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/publish-pre-and-qa.yml b/.github/workflows/publish-pre-and-qa.yml new file mode 100644 index 00000000..427fc05d --- /dev/null +++ b/.github/workflows/publish-pre-and-qa.yml @@ -0,0 +1,275 @@ +name: publish-pre-and-qa +on: + pull_request: + branches: [main] + types: [closed] + workflow_dispatch: + inputs: + clean_version: + description: "Clean semver to promote (no .post)" + required: true + type: string + ref: + description: "Git ref to use (defaults to main)" + required: false + type: string + pre_version: + description: "Pre-release version (optional, for bookkeeping)" + required: false + type: string + dry_run: + description: "If true, skip publishing to PyPI (only TestPyPI)" + required: false + default: false + type: boolean + +permissions: + contents: write + pull-requests: write + packages: write + issues: write + +jobs: + publish-pre: + name: Publish pre-release to TestPyPI (core-first) + if: ${{ github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'prepare-release') || github.event_name == 'workflow_dispatch' }} + runs-on: ubuntu-latest + outputs: + version: ${{ steps.ver.outputs.version }} + clean_version: ${{ steps.ver.outputs.clean_version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Derive version from PR title + id: ver + run: | + set -euo pipefail + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + VERSION="${{ github.event.inputs.pre_version || '' }}" + if [ -n "$VERSION" ]; then + CLEAN_VERSION="${{ github.event.inputs.clean_version }}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "clean_version=$CLEAN_VERSION" >> $GITHUB_OUTPUT + exit 0 + fi + fi + TITLE="${{ github.event.pull_request.title }}" + VERSION=$(echo "$TITLE" | sed -nE 's/.*prepare ([0-9]+\.[0-9]+\.[0-9]+(\.post[0-9]+)?).*/\1/p' || true) + if [ -z "$VERSION" ]; then + echo "Could not derive version from PR title: $TITLE" >&2 + exit 1 + fi + CLEAN_VERSION="${VERSION%%.post*}" + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "clean_version=$CLEAN_VERSION" >> $GITHUB_OUTPUT + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install Poetry + run: | + pip install poetry==2.1.3 + + - name: Configure TestPyPI repository + run: | + poetry config repositories.testpypi https://test.pypi.org/legacy/ + + - name: Install jq + run: sudo apt-get update && sudo apt-get install -y jq + + - name: Publish rag-core-lib first (TestPyPI) and wait for index + env: + VERSION: ${{ steps.ver.outputs.version }} + POETRY_HTTP_BASIC_TESTPYPI_USERNAME: __token__ + POETRY_HTTP_BASIC_TESTPYPI_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} + run: | + set -euo pipefail + if [ -z "${POETRY_HTTP_BASIC_TESTPYPI_PASSWORD:-}" ]; then + echo "Missing TEST_PYPI_TOKEN secret" >&2 + exit 1 + fi + source tools/publish_libs.sh + publish_lib "rag-core-lib" "-r testpypi" "$VERSION" + wait_for_index "rag-core-lib" "$VERSION" "https://test.pypi.org" "TestPyPI" + + - name: Publish remaining libs to TestPyPI + env: + VERSION: ${{ steps.ver.outputs.version }} + POETRY_HTTP_BASIC_TESTPYPI_USERNAME: __token__ + POETRY_HTTP_BASIC_TESTPYPI_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} + run: | + set -euo pipefail + source tools/publish_libs.sh + for lib in rag-core-api admin-api-lib extractor-api-lib; do + path="libs/$lib" + [ -d "$path" ] || { echo "Missing $path" >&2; exit 1; } + publish_lib "$lib" "-r testpypi" "$VERSION" "$path" + done + + - name: Persist version metadata for downstream workflows + env: + VERSION: ${{ steps.ver.outputs.version }} + CLEAN_VERSION: ${{ steps.ver.outputs.clean_version }} + run: | + set -euo pipefail + mkdir -p meta + { + echo "PRE_VERSION=${VERSION}" + echo "CLEAN_VERSION=${CLEAN_VERSION}" + } > meta/version.env + # Upload artifact for workflow_run trigger consumption + - name: Upload version artifact + uses: actions/upload-artifact@v4 + with: + name: pre-release-meta + path: meta/version.env + retention-days: 5 + + qa-verify: + name: Build QA images (${{ matrix.name }}) + runs-on: ubuntu-latest + needs: publish-pre + if: ${{ needs.publish-pre.result == 'success' }} + strategy: + fail-fast: false + matrix: + include: + - name: rag-backend + dockerfile: services/rag-backend/Dockerfile + context: . + - name: admin-backend + dockerfile: services/admin-backend/Dockerfile + context: . + - name: document-extractor + dockerfile: services/document-extractor/Dockerfile + context: . + - name: mcp-server + dockerfile: services/mcp-server/Dockerfile + context: . + - name: frontend + dockerfile: services/frontend/apps/chat-app/Dockerfile + context: . + - name: admin-frontend + dockerfile: services/frontend/apps/admin-app/Dockerfile + context: . + env: + PRE_RELEASE_VERSION: ${{ needs.publish-pre.outputs.version }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate QA secrets are present + run: | + missing=() + [ -z "${{ secrets.STACKIT_REGISTRY_USERNAME }}" ] && missing+=("STACKIT_REGISTRY_USERNAME") + [ -z "${{ secrets.STACKIT_REGISTRY_PASSWORD }}" ] && missing+=("STACKIT_REGISTRY_PASSWORD") + [ -z "${{ secrets.QA_IMAGE_REGISTRY }}" ] && echo "QA_IMAGE_REGISTRY not set, defaulting to registry.onstackit.cloud/qa-rag-template" + if [ ${#missing[@]} -gt 0 ]; then + echo "Missing required secrets: ${missing[*]}" >&2 + exit 1 + fi + + - name: Set image registry and version + env: + QA_IMAGE_REGISTRY: ${{ secrets.QA_IMAGE_REGISTRY }} + run: | + IMAGE_REGISTRY="${QA_IMAGE_REGISTRY:-registry.onstackit.cloud/qa-rag-template}" + echo "IMAGE_REGISTRY=${IMAGE_REGISTRY}" >> "$GITHUB_ENV" + echo "IMAGE_TAG=${PRE_RELEASE_VERSION}" >> "$GITHUB_ENV" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to STACKIT registry + env: + STACKIT_REGISTRY_USERNAME: ${{ secrets.STACKIT_REGISTRY_USERNAME }} + STACKIT_REGISTRY_PASSWORD: ${{ secrets.STACKIT_REGISTRY_PASSWORD }} + run: | + echo "$STACKIT_REGISTRY_PASSWORD" | docker login registry.onstackit.cloud -u "$STACKIT_REGISTRY_USERNAME" --password-stdin + + - name: Build and push QA image + env: + IMAGE_REGISTRY: ${{ env.IMAGE_REGISTRY }} + IMAGE_TAG: ${{ env.IMAGE_TAG }} + run: | + set -euo pipefail + ref="$IMAGE_REGISTRY/${{ matrix.name }}:$IMAGE_TAG" + echo "Building and pushing $ref (Dockerfile=${{ matrix.dockerfile }} context=${{ matrix.context }})" + docker buildx build --platform linux/amd64 -t "$ref" -f "${{ matrix.dockerfile }}" "${{ matrix.context }}" --push + + update-qa-deploy: + name: Update QA deployment repo + runs-on: ubuntu-latest + needs: [publish-pre, qa-verify] + if: ${{ needs.publish-pre.result == 'success' && needs.qa-verify.result == 'success' }} + env: + PRE_RELEASE_VERSION: ${{ needs.publish-pre.outputs.version }} + steps: + - name: Validate QA secrets are present + run: | + missing=() + [ -z "${{ secrets.DEPLOY_REPO_URL }}" ] && missing+=("DEPLOY_REPO_URL") + [ -z "${{ secrets.DEPLOY_REPO_TOKEN }}" ] && missing+=("DEPLOY_REPO_TOKEN") + if [ ${#missing[@]} -gt 0 ]; then + echo "Missing required secrets: ${missing[*]}" >&2 + exit 1 + fi + + - name: Set image registry and version + env: + QA_IMAGE_REGISTRY: ${{ secrets.QA_IMAGE_REGISTRY }} + run: | + IMAGE_REGISTRY="${QA_IMAGE_REGISTRY:-registry.onstackit.cloud/qa-rag-template}" + echo "IMAGE_REGISTRY=${IMAGE_REGISTRY}" >> "$GITHUB_ENV" + echo "IMAGE_TAG=${PRE_RELEASE_VERSION}" >> "$GITHUB_ENV" + + - name: Checkout deployment repo + env: + DEPLOY_REPO_URL: ${{ secrets.DEPLOY_REPO_URL }} + DEPLOY_REPO_BRANCH: ${{ secrets.DEPLOY_REPO_BRANCH || 'main' }} + DEPLOY_REPO_TOKEN: ${{ secrets.DEPLOY_REPO_TOKEN }} + run: | + set -euo pipefail + mkdir -p /tmp/deploy-repo + AUTH_URL="${DEPLOY_REPO_URL/https:\/\//https://${DEPLOY_REPO_TOKEN}@}" + git clone --depth 1 --branch "${DEPLOY_REPO_BRANCH:-main}" "$AUTH_URL" /tmp/deploy-repo + + - name: Update values file in deployment repo + env: + IMAGE_REGISTRY: ${{ env.IMAGE_REGISTRY }} + IMAGE_TAG: ${{ env.IMAGE_TAG }} + DEPLOY_VALUES_FILE: ${{ secrets.DEPLOY_VALUES_FILE || 'values-qa.yaml' }} + run: | + set -euo pipefail + cd /tmp/deploy-repo + python -m pip install --quiet pyyaml + python "$GITHUB_WORKSPACE/tools/update_deploy_values.py" \ + --values-file "$DEPLOY_VALUES_FILE" \ + --image-registry "$IMAGE_REGISTRY" \ + --image-tag "$IMAGE_TAG" + + - name: Commit and push deployment repo changes + env: + DEPLOY_REPO_BRANCH: ${{ secrets.DEPLOY_REPO_BRANCH || 'main' }} + DEPLOY_REPO_TOKEN: ${{ secrets.DEPLOY_REPO_TOKEN }} + DEPLOY_REPO_URL: ${{ secrets.DEPLOY_REPO_URL }} + DEPLOY_GIT_USER_NAME: ${{ secrets.DEPLOY_GIT_USER_NAME || 'github-actions' }} + DEPLOY_GIT_USER_EMAIL: ${{ secrets.DEPLOY_GIT_USER_EMAIL || 'github-actions@users.noreply.github.com' }} + run: | + set -euo pipefail + cd /tmp/deploy-repo + git config user.name "${DEPLOY_GIT_USER_NAME}" + git config user.email "${DEPLOY_GIT_USER_EMAIL}" + git add . + if git diff --cached --quiet; then + echo "No changes to commit" + exit 0 + fi + git commit -m "chore: update QA images to ${IMAGE_TAG}" + AUTH_URL="${DEPLOY_REPO_URL/https:\/\//https://${DEPLOY_REPO_TOKEN}@}" + git push "$AUTH_URL" "HEAD:${DEPLOY_REPO_BRANCH:-main}" diff --git a/.github/workflows/semantic-release.yml b/.github/workflows/semantic-release.yml deleted file mode 100644 index 4a8c44e3..00000000 --- a/.github/workflows/semantic-release.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: semantic-release -on: - workflow_dispatch: - push: - # Only trigger on merged PRs, not on every PR push - pull_request: - types: [closed] - branches: - - main - -permissions: - contents: write - packages: write - -jobs: - semantic-release: - name: semantic-release - runs-on: ubuntu-latest - # Only run on push to main, manual dispatch, or when PR is merged - if: github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) - outputs: - new-release-published: ${{ steps.semantic-release.outputs.new-release-published }} - new-release-version: ${{ steps.semantic-release.outputs.new-release-version }} - steps: - - name: checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - submodules: false - - - name: setup-node - uses: actions/setup-node@v4 - with: - node-version: "22.20.0" - - - name: create-archives - run: | - TEMP_DIR=$(mktemp -d) - tar --warning=no-file-changed \ - --exclude=".git" \ - --exclude="/.git" \ - --exclude="node_modules" \ - -czf "$TEMP_DIR/action-main-release-trials.tar.gz" . - zip -r "$TEMP_DIR/action-main-release-trials.zip" . \ - -x ".git" "node_modules" - mv "$TEMP_DIR"/*.{tar.gz,zip} . - rm -rf "$TEMP_DIR" - - - name: install-dependencies - run: npm ci - - - name: verify-dependencies-integrity - run: npm audit signatures - - - name: create-semantic-release - id: semantic-release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - # Run semantic-release and capture the output - npx semantic-release > semantic-release-output.txt 2>&1 || true - - # Check if a new release was published by looking for the success message - if grep -q "Published release" semantic-release-output.txt; then - echo "new-release-published=true" >> $GITHUB_OUTPUT - - # Extract the version from the output - VERSION=$(grep "Published release" semantic-release-output.txt | sed -n 's/.*Published release \([0-9]\+\.[0-9]\+\.[0-9]\+\).*/\1/p') - - if [[ -n "$VERSION" ]]; then - echo "new-release-version=$VERSION" >> $GITHUB_OUTPUT - echo "āœ… New release published: $VERSION" - else - echo "āŒ Could not extract version from semantic-release output" - exit 1 - fi - else - echo "new-release-published=false" >> $GITHUB_OUTPUT - echo "ā„¹ļø No new release published" - fi - - build-and-push-images: - name: build-and-push-images - runs-on: ubuntu-latest - needs: semantic-release - if: needs.semantic-release.outputs.new-release-published == 'true' - strategy: - matrix: - service: - - name: rag-backend - dockerfile: services/rag-backend/Dockerfile - image: rag-backend - - name: admin-backend - dockerfile: services/admin-backend/Dockerfile - image: admin-backend - - name: document-extractor - dockerfile: services/document-extractor/Dockerfile - image: document-extractor - - name: mcp-server - dockerfile: services/mcp-server/Dockerfile - image: mcp-server - - name: frontend - dockerfile: services/frontend/apps/chat-app/Dockerfile - image: frontend - - name: admin-frontend - dockerfile: services/frontend/apps/admin-app/Dockerfile - image: admin-frontend - steps: - - name: debug-job-inputs - run: | - echo "šŸ” Debug: needs.semantic-release.outputs.new-release-published = ${{ needs.semantic-release.outputs.new-release-published }}" - echo "šŸ” Debug: needs.semantic-release.outputs.new-release-version = ${{ needs.semantic-release.outputs.new-release-version }}" - - - name: checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - submodules: false - - - name: login-to-github-container-registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: build-and-push-${{ matrix.service.name }} - run: | - docker build \ - --tag ghcr.io/${{ github.repository_owner }}/rag-template/${{ matrix.service.image }}:v${{ needs.semantic-release.outputs.new-release-version }} \ - --tag ghcr.io/${{ github.repository_owner }}/rag-template/${{ matrix.service.image }}:latest \ - --file ${{ matrix.service.dockerfile }} \ - . - - docker push ghcr.io/${{ github.repository_owner }}/rag-template/${{ matrix.service.image }}:v${{ needs.semantic-release.outputs.new-release-version }} - docker push ghcr.io/${{ github.repository_owner }}/rag-template/${{ matrix.service.image }}:latest - - - name: deployment-summary - if: strategy.job-index == 0 # Only run on first job in matrix - run: | - echo "## šŸš€ Deployment Summary" >> $GITHUB_STEP_SUMMARY - echo "**New version:** v${{ needs.semantic-release.outputs.new-release-version }}" >> $GITHUB_STEP_SUMMARY - echo "**Services built and deployed:**" >> $GITHUB_STEP_SUMMARY - echo "- rag-backend" >> $GITHUB_STEP_SUMMARY - echo "- admin-backend" >> $GITHUB_STEP_SUMMARY - echo "- document-extractor" >> $GITHUB_STEP_SUMMARY - echo "- mcp-server" >> $GITHUB_STEP_SUMMARY - echo "- frontend" >> $GITHUB_STEP_SUMMARY - echo "- admin-frontend" >> $GITHUB_STEP_SUMMARY - echo "**Registry:** ghcr.io/${{ github.repository_owner }}/rag-template" >> $GITHUB_STEP_SUMMARY diff --git a/libs/admin-api-lib/pyproject.toml b/libs/admin-api-lib/pyproject.toml index 0b65d3bf..687dbbe7 100644 --- a/libs/admin-api-lib/pyproject.toml +++ b/libs/admin-api-lib/pyproject.toml @@ -18,6 +18,11 @@ license = "Apache-2.0" repository = "https://github.com/stackitcloud/rag-template" homepage = "https://pypi.org/project/admin-api-lib" +[[tool.poetry.source]] +name = "testpypi" +url = "https://test.pypi.org/simple/" +priority = "explicit" + [tool.flake8] exclude= [".eggs", "./libs/*", "./src/admin_api_lib/models/*", "./src/admin_api_lib/rag_backend_client/*", "./src/admin_api_lib/extractor_api_client/*", ".git", ".hg", ".mypy_cache", ".tox", ".venv", ".devcontainer", "venv", "_build", "buck-out", "build", "dist", "**/__init__.py"] statistics = true diff --git a/libs/extractor-api-lib/poetry.lock b/libs/extractor-api-lib/poetry.lock index adf511a6..03846fbb 100644 --- a/libs/extractor-api-lib/poetry.lock +++ b/libs/extractor-api-lib/poetry.lock @@ -7613,4 +7613,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt [metadata] lock-version = "2.1" python-versions = ">=3.13,<3.14" -content-hash = "a66536faae6ddea393d9e81b5f215416eb3dd5c75620fc61583cada25ab3f01f" +content-hash = "9e5bb9f495aebab13474d234e684e4734d15a90b870070cdae75ec5670fcec89" diff --git a/libs/extractor-api-lib/pyproject.toml b/libs/extractor-api-lib/pyproject.toml index 2fbda1a5..4d02fcac 100644 --- a/libs/extractor-api-lib/pyproject.toml +++ b/libs/extractor-api-lib/pyproject.toml @@ -23,6 +23,12 @@ name = "pytorch_cpu" url = "https://download.pytorch.org/whl/cpu" priority = "explicit" + +[[tool.poetry.source]] +name = "testpypi" +url = "https://test.pypi.org/simple/" +priority = "explicit" + [tool.flake8] exclude = [".eggs", "./src/extractor_api_lib/models/*", ".git", ".hg", ".mypy_cache", ".tox", ".venv", ".devcontainer", "venv", "_build", "buck-out", "build", "dist", "**/__init__.py", "tests/test_data/generate_test_pdfs.py"] statistics = true @@ -115,8 +121,8 @@ pypandoc-binary = "^1.15" starlette = ">=0.49.1" markitdown = {version = "^0.1.3", extras = ["all"]} docling = "2.61.2" -torch = { version = "^2.9.0+cpu", source = "pytorch_cpu" } -torchvision = { version = "^0.24.1+cpu", source = "pytorch_cpu" } +torch = { version = "^2.9.0", source = "pytorch_cpu" } +torchvision = { version = "^0.24.1", source = "pytorch_cpu" } transformers = ">=4.53.3,<5.0.0" pypandoc = ">=1.6.2" pypandoc_binary = ">=1.6.2" @@ -160,3 +166,4 @@ log_cli = true log_cli_level = "DEBUG" pythonpath = "src" testpaths = "src/tests" + diff --git a/libs/rag-core-api/pyproject.toml b/libs/rag-core-api/pyproject.toml index 2bb84d62..99d3154b 100644 --- a/libs/rag-core-api/pyproject.toml +++ b/libs/rag-core-api/pyproject.toml @@ -77,6 +77,10 @@ black = "^25.1.0" flake8-logging-format = "^2024.24.12" flake8-docstrings = "^1.7.0" +[[tool.poetry.source]] +name = "testpypi" +url = "https://test.pypi.org/simple/" +priority = "explicit" [tool.flake8] exclude= [".eggs", "src/rag_core_api/models", ".git", ".hg", ".mypy_cache", ".tox", ".venv", ".devcontainer", "venv", "_build", "buck-out", "build", "dist", "**/__init__.py"] diff --git a/package-lock.json b/package-lock.json index dec6b938..f62eadbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -112,6 +112,7 @@ "integrity": "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.1", @@ -2468,6 +2469,7 @@ "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", "dev": true, "license": "MIT", + "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -2983,6 +2985,34 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/npm/node_modules/@npmcli/arborist/node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/arborist/node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm/node_modules/@npmcli/config": { "version": "10.4.3", "dev": true, @@ -3002,6 +3032,34 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/npm/node_modules/@npmcli/config/node_modules/abbrev": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-3.0.1.tgz", + "integrity": "sha512-AO2ac6pjRB3SJmGJo+v5/aK6Omggp6fsLrs6wN9bd35ulu4cCwaAU9+7ZhXjeqHVkaHThLuzH0nZr0YpCDhygg==", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/@npmcli/config/node_modules/nopt": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-8.1.0.tgz", + "integrity": "sha512-ieGu42u/Qsa4TFktmaKEwM6MQH0pOWnaB3htzh0JRtx84+Mebc0cbZYN5bC+6WTZ4+77xrL9Pn5m7CV6VIkV7A==", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "abbrev": "^3.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm/node_modules/@npmcli/fs": { "version": "4.0.0", "dev": true, @@ -3920,6 +3978,49 @@ "node": "^20.17.0 || >=22.9.0" } }, + "node_modules/npm/node_modules/libnpmdiff/node_modules/@npmcli/installed-package-contents": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-3.0.0.tgz", + "integrity": "sha512-fkxoPuFGvxyrH+OQzyTkX2LUEamrF4jZSmxjAtPPHHGO0dqsQ8tTKjnIS8SAnPHdk2I03BDtSMR5K/4loKg79Q==", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "bin": { + "installed-package-contents": "bin/index.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff/node_modules/npm-bundled": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-4.0.0.tgz", + "integrity": "sha512-IxaQZDMsqfQ2Lz37VvyyEtKLe8FsRZuysmedy/N06TU1RyVppYKXrO4xIhR0F+7ubIBox6Q7nir6fQI3ej39iA==", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm/node_modules/libnpmdiff/node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/npm/node_modules/libnpmexec": { "version": "10.1.9", "dev": true, @@ -4902,6 +5003,7 @@ "dev": true, "inBundle": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -5578,6 +5680,7 @@ "integrity": "sha512-6qGjWccl5yoyugHt3jTgztJ9Y0JVzyH8/Voc/D8PlLat9pwxQYXz7W1Dpnq5h0/G5GCYGUaDSlYcyk3AMh5A6g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/error": "^4.0.0", @@ -6433,6 +6536,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, diff --git a/services/document-extractor/poetry.lock b/services/document-extractor/poetry.lock index 2d0bf2d5..15d0de1e 100644 --- a/services/document-extractor/poetry.lock +++ b/services/document-extractor/poetry.lock @@ -1585,8 +1585,8 @@ requests-oauthlib = "^2.0.0" starlette = ">=0.49.1" tabulate = "^0.9.0" tesserocr = "^2.9.1" -torch = "^2.9.0+cpu" -torchvision = "^0.24.1+cpu" +torch = "^2.9.0" +torchvision = "^0.24.1" transformers = ">=4.53.3,<5.0.0" unstructured = {version = "0.18.15", extras = ["docx", "pptx"]} uvicorn = "^0.37.0" diff --git a/services/document-extractor/pyproject.toml b/services/document-extractor/pyproject.toml index 3c8b0216..2fda8a24 100644 --- a/services/document-extractor/pyproject.toml +++ b/services/document-extractor/pyproject.toml @@ -111,6 +111,11 @@ name = "testpypi" url = "https://test.pypi.org/simple/" priority = "supplemental" +[[tool.poetry.source]] +name = "pytorch_cpu" +url = "https://download.pytorch.org/whl/cpu" +priority = "explicit" + [tool.poetry.group.prod.dependencies] # Try PyPI first, then TestPyPI automatically due to supplemental priority extractor-api-lib = "==3.4.0" @@ -118,8 +123,3 @@ extractor-api-lib = "==3.4.0" [tool.poetry.group.prod-local.dependencies] # Use local path for Tilt/development with production Dockerfile extractor-api-lib = {path = "../../libs/extractor-api-lib"} - -[[tool.poetry.source]] -name = "pytorch_cpu" -url = "https://download.pytorch.org/whl/cpu" -priority = "explicit" diff --git a/services/frontend/package-lock.json b/services/frontend/package-lock.json index b261599c..2dad65d5 100644 --- a/services/frontend/package-lock.json +++ b/services/frontend/package-lock.json @@ -19,7 +19,6 @@ "devDependencies": { "@eslint/js": "^9.36.0", "@intlify/unplugin-vue-i18n": "^11.0.0", - "@nrwl/eslint-plugin-nx": "^19.8.14", "@nx/cypress": "^21.6.4", "@nx/eslint": "^21.6.4", "@nx/eslint-plugin": "^21.6.4", @@ -29,10 +28,10 @@ "@nx/web": "^21.6.4", "@nx/workspace": "^21.6.4", "@rushstack/eslint-patch": "^1.2.0", + "@sit-onyx/icons": "^1.3.0", "@tailwindcss/postcss": "^4.1.14", "@tailwindcss/typography": "^0.5.19", "@tailwindcss/vite": "^4.1.14", - "@sit-onyx/icons": "^1.3.0", "@tsconfig/node21": "^21.0.1", "@types/jsdom": "^27.0.0", "@types/node": "^22.0.0", @@ -3192,92 +3191,83 @@ "node": ">= 8" } }, - "node_modules/@nrwl/devkit": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nrwl/devkit/-/devkit-19.8.14.tgz", - "integrity": "sha512-Oud7BPhFNqE3/YStULn/gHyuGSw2QyxUaHXJApr+DybmYtUms7hQ+cWnY1IY+hRpdtU9ldlg8UYx+VslpS9YNQ==", + "node_modules/@nx/cypress": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-21.6.8.tgz", + "integrity": "sha512-r/HmyxNA4wFM6iIc+aXeMDmNEO3qRkea4/cCOjNXSaEksBReHPRlQTz/M5n58xpqxAhOSVHDBH162pznCGP1cg==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "19.8.14" + "@nx/devkit": "21.6.8", + "@nx/eslint": "21.6.8", + "@nx/js": "21.6.8", + "@phenomnomnominal/tsquery": "~5.0.1", + "detect-port": "^1.5.1", + "semver": "^7.6.3", + "tree-kill": "1.2.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "cypress": ">= 3 < 15" + }, + "peerDependenciesMeta": { + "cypress": { + "optional": true + } } }, - "node_modules/@nrwl/devkit/node_modules/@nx/devkit": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.14.tgz", - "integrity": "sha512-A8dCGttbuqgg9P56VTb0ElD2vM5nc5g0aLnX5PSXo4SkFXwd8DV5GgwJKWB1GO9hYyEtbj4gKek0KxnCtdav4g==", + "node_modules/@nx/devkit": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-21.6.8.tgz", + "integrity": "sha512-N0cj0NqdxY2pcI0IJV+fAu362B6tppdv2ohSBNGacNeSqxfAlJxO5TFZePDmxX5nt0t9hAqT+iasfu4BSYGfZw==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/devkit": "19.8.14", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", "minimatch": "9.0.3", "semver": "^7.5.3", - "tmp": "~0.2.1", "tslib": "^2.3.0", "yargs-parser": "21.1.1" }, "peerDependencies": { - "nx": ">= 19 <= 21" - } - }, - "node_modules/@nrwl/eslint-plugin-nx": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nrwl/eslint-plugin-nx/-/eslint-plugin-nx-19.8.14.tgz", - "integrity": "sha512-nnwWYW+XS3r8aCzVahpIVSu63J8UD5WAzO7yUZpk8etRlmRrVXl+JXxNLkOF0KNTuGuqFZUrN9ZO/NkigPPtUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/eslint-plugin": "19.8.14" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "nx": ">= 20 <= 22" } }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/devkit": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.14.tgz", - "integrity": "sha512-A8dCGttbuqgg9P56VTb0ElD2vM5nc5g0aLnX5PSXo4SkFXwd8DV5GgwJKWB1GO9hYyEtbj4gKek0KxnCtdav4g==", + "node_modules/@nx/eslint": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-21.6.8.tgz", + "integrity": "sha512-dloTsg1n1zlAyP2Ohwiw9vhoUrF5XYo5pdmxAmnpE/P+e4ihWQfGtlu3JvEQNBp9Wwk4E7XkJVmVhJOm47PIww==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/devkit": "19.8.14", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", + "@nx/devkit": "21.6.8", + "@nx/js": "21.6.8", "semver": "^7.5.3", - "tmp": "~0.2.1", "tslib": "^2.3.0", - "yargs-parser": "21.1.1" + "typescript": "~5.9.2" }, "peerDependencies": { - "nx": ">= 19 <= 21" + "@zkochan/js-yaml": "0.0.7", + "eslint": "^8.0.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "@zkochan/js-yaml": { + "optional": true + } } }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/eslint-plugin": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-19.8.14.tgz", - "integrity": "sha512-0wYTqP3J3mJPGilf9xCiFD8Rw7f/knCDwXmoXv1tZb/N/3oExreqVPz0wnRcQh+clDAEVlY3onvqqkSBw5K/Fg==", + "node_modules/@nx/eslint-plugin": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-21.6.8.tgz", + "integrity": "sha512-uDJxGrNF9WmP35pSR6EjMA720GIb2XpbygA6u26lhS9/VJt6pC+/bvLwXLf0bG3sWHjmpUNsIWlK4WMQe9q8wg==", "dev": true, "license": "MIT", "dependencies": { - "@eslint/compat": "^1.1.1", - "@nrwl/eslint-plugin-nx": "19.8.14", - "@nx/devkit": "19.8.14", - "@nx/js": "19.8.14", + "@nx/devkit": "21.6.8", + "@nx/js": "21.6.8", + "@phenomnomnominal/tsquery": "~5.0.1", "@typescript-eslint/type-utils": "^8.0.0", "@typescript-eslint/utils": "^8.0.0", "chalk": "^4.1.0", @@ -3289,7 +3279,7 @@ }, "peerDependencies": { "@typescript-eslint/parser": "^6.13.2 || ^7.0.0 || ^8.0.0", - "eslint-config-prettier": "^9.0.0" + "eslint-config-prettier": "^10.0.0" }, "peerDependenciesMeta": { "eslint-config-prettier": { @@ -3297,10 +3287,10 @@ } } }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/js": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.14.tgz", - "integrity": "sha512-Nk0eEB2F/ZbBkH2iT+cgLWIittY8n5eOrA/uBBG2XMdencJZ9E2HNA/UzSGPZmD4EYVk0R1vm83k5+IMS1VAZA==", + "node_modules/@nx/js": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/js/-/js-21.6.8.tgz", + "integrity": "sha512-I9Wu//28DXiSIFoW1IGbLRRfULITkYMOKGMnityQ71iJ8+9vi90a8xFyCWt4VzNxpMEreaoNynWJTf+I8UTGaw==", "dev": true, "license": "MIT", "dependencies": { @@ -3311,32 +3301,31 @@ "@babel/preset-env": "^7.23.2", "@babel/preset-typescript": "^7.22.5", "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.8.14", - "@nx/devkit": "19.8.14", - "@nx/workspace": "19.8.14", + "@nx/devkit": "21.6.8", + "@nx/workspace": "21.6.8", + "@zkochan/js-yaml": "0.0.7", "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", + "babel-plugin-macros": "^3.1.0", "babel-plugin-transform-typescript-metadata": "^0.3.1", "chalk": "^4.1.0", "columnify": "^1.6.0", "detect-port": "^1.5.1", "enquirer": "~2.3.6", - "fast-glob": "3.2.7", "ignore": "^5.0.4", "js-tokens": "^4.0.0", "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", "npm-package-arg": "11.0.1", "npm-run-path": "^4.0.1", "ora": "5.3.0", + "picocolors": "^1.1.0", + "picomatch": "4.0.2", "semver": "^7.5.3", "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", + "tinyglobby": "^0.2.12", "tslib": "^2.3.0" }, "peerDependencies": { - "verdaccio": "^5.0.4" + "verdaccio": "^6.0.5" }, "peerDependenciesMeta": { "verdaccio": { @@ -3344,10 +3333,23 @@ } } }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-darwin-arm64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.14.tgz", - "integrity": "sha512-bZUFf23gAzuwVw71dR8rngye5aCR8Z/ouIo+KayjqB0LWWoi3WzO73s4S69ljftYt4n6z9wvD+Trbb1BKm2fPg==", + "node_modules/@nx/js/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@nx/nx-darwin-arm64": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-21.6.8.tgz", + "integrity": "sha512-MG5bhSYhG49r+e0mLuztQVHz1sEy7cs8BvZJ56mm7JNQ1VfbaTyLAR7VcNw8O/1mJA8jYcg9fmxOIZOUnY1cEQ==", "cpu": [ "arm64" ], @@ -3356,15 +3358,12 @@ "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-darwin-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.14.tgz", - "integrity": "sha512-UXXVea8icFG/3rFwpbLYsD6O4wlyJ1STQfOdhGK1Hyuga70AUUdrjVm7HzigAQP/Sb2Nzd7155YXHzfpRPDFYA==", + "node_modules/@nx/nx-darwin-x64": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-21.6.8.tgz", + "integrity": "sha512-e9oXVTd6U6RFEc3k22PGoe5OSy40fyyytl+svSJQmK+5rxZalvAUna/mXtFcQC9m6No2daqqpfAZlyN5nG6WHw==", "cpu": [ "x64" ], @@ -3373,15 +3372,12 @@ "optional": true, "os": [ "darwin" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-freebsd-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.14.tgz", - "integrity": "sha512-TK2xuXn+BI6hxGaRK1HRUPWeF/nOtezKSqM+6rbippfCzjES/crmp9l5nbI764MMthtUmykCyWvhEfkDca6kbA==", + "node_modules/@nx/nx-freebsd-x64": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-21.6.8.tgz", + "integrity": "sha512-gK3rsTXQj0hHCyaAvZmPZeCPkb3jzesgtkXuZf+7pCm5b4wiEA1i22ufp1UzwaTmWgbub/6NVMEDOGsVcay8mA==", "cpu": [ "x64" ], @@ -3390,15 +3386,12 @@ "optional": true, "os": [ "freebsd" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.14.tgz", - "integrity": "sha512-33rptyRraqaeQ2Kq6pcZKQqgnYY/7zcGH8fHXgKK7XzKk+7QuPViq+jMEUZP5E3UzZPkIYhsfmZcZqhNRvepJQ==", + "node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-21.6.8.tgz", + "integrity": "sha512-TXt3HTFhM4kuL9larxBuo3XpSngoA1JCtHavfYLRC3A8knACi7LwNQwnF5RWAcYgKMVE3/8IAhV8LuemXrPKKw==", "cpu": [ "arm" ], @@ -3407,15 +3400,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.14.tgz", - "integrity": "sha512-2E70qMKOhh7Fp4JGcRbRLvFKq0+ANVdAgSzH47plxOLygIeVAfIXRSuQbCI0EUFa5Sy6hImLaoRSB2GdgKihAw==", + "node_modules/@nx/nx-linux-arm64-gnu": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-21.6.8.tgz", + "integrity": "sha512-QwZREYIhqhDVEIf+KAv2VFipxMUoULXXS3qyLX3/q/4u8Y32fyM5wd+FXpv89cRCiveVsZp8io2W178R6lfKng==", "cpu": [ "arm64" ], @@ -3424,15 +3414,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.14.tgz", - "integrity": "sha512-ltty/PDWqkYgu/6Ye65d7v5nh3D6e0n3SacoKRs2Vtfz5oHYRUkSKizKIhEVfRNuHn3d9j8ve1fdcCN4SDPUBQ==", + "node_modules/@nx/nx-linux-arm64-musl": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-21.6.8.tgz", + "integrity": "sha512-UZJyrZ6utU8g1W7E31iHDhWj1SjMidmDNyrVP4xK6IUrotx6qGrwfwWqzqvphhc1cA7w4Zz9N/rCCPQkdHzjLw==", "cpu": [ "arm64" ], @@ -3441,15 +3428,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.14.tgz", - "integrity": "sha512-JzE3BuO9RCBVdgai18CCze6KUzG0AozE0TtYFxRokfSC05NU3nUhd/o62UsOl7s6Bqt/9nwrW7JC8pNDiCi9OQ==", + "node_modules/@nx/nx-linux-x64-gnu": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-21.6.8.tgz", + "integrity": "sha512-HXINTg4P0/Yj76vsvqBAb7MNlLpkH1pl9JF2blXScOFXWzNoStd7b6xyrpCROdmi0Hk8y3UEwc8OIyLFIfixJg==", "cpu": [ "x64" ], @@ -3458,15 +3442,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.14.tgz", - "integrity": "sha512-2rPvDOQLb7Wd6YiU88FMBiLtYco0dVXF99IJBRGAWv+WTI7MNr47OyK2ze+JOsbYY1d8aOGUvckUvCCZvZKEfg==", + "node_modules/@nx/nx-linux-x64-musl": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-21.6.8.tgz", + "integrity": "sha512-2YbXLhuSlElCtQTR1Ib94O3T4fX9uzSIkUMYGL3n04agG0HemXoxJa91TWwwOUMbEZffkhcPsJBOh2S5l47s9Q==", "cpu": [ "x64" ], @@ -3475,15 +3456,12 @@ "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.14.tgz", - "integrity": "sha512-JxW+YPS+EjhUsLw9C6wtk9pQTG3psyFwxhab8y/dgk2s4AOTLyIm0XxgcCJVvB6i4uv+s1g0QXRwp6+q3IR6hg==", + "node_modules/@nx/nx-win32-arm64-msvc": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-21.6.8.tgz", + "integrity": "sha512-/VSGtqa1oGHo5n24R39ZuGxMrGyf7pxFuCtL5hAzBHdTxFg/VZomPGd7BeV5VN5SbIw+fie+nTGkC5q3TOPGXw==", "cpu": [ "arm64" ], @@ -3492,15 +3470,12 @@ "optional": true, "os": [ "win32" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.14.tgz", - "integrity": "sha512-RxiPlBWPcGSf9TzIIy62iKRdRhokXMDUsPub9DL2VdVyTMXPZQR25aY/PJeasJN1EQU74hg097LK2wSHi+vzOQ==", + "node_modules/@nx/nx-win32-x64-msvc": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-21.6.8.tgz", + "integrity": "sha512-xeBL7PcDqHH/Zw4d2A2qP7eLImzzcMO3hiKs5G42Wi92ACejAdUqpIduTL4RpArsXIHm5VEbE4KvHNii1mMU1A==", "cpu": [ "x64" ], @@ -3509,1860 +3484,57 @@ "optional": true, "os": [ "win32" - ], - "engines": { - "node": ">= 10" - } + ] }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@nx/workspace": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.14.tgz", - "integrity": "sha512-Yb3d5WVjCyLill8MycKU+P/kbTyatKKqoUCu5zWokkysABiMWRLlrCYNzqwjTjeIIGj9MMGRHAQEemkBdL4tdg==", + "node_modules/@nx/vite": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/vite/-/vite-21.6.8.tgz", + "integrity": "sha512-+0d2A8rAkWH5wSttlz36gfTov02pdE9yLqe/FjaaRJtb/4tmRi1pahKvCxStrct2sY6uEktel0PU6y5IRoCF8w==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/workspace": "19.8.14", - "@nx/devkit": "19.8.14", + "@nx/devkit": "21.6.8", + "@nx/js": "21.6.8", + "@phenomnomnominal/tsquery": "~5.0.1", + "@typescript-eslint/type-utils": "^8.0.0", + "@typescript-eslint/utils": "^8.0.0", "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.8.14", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" + "confusing-browser-globals": "^1.0.9", + "globals": "^15.9.0", + "jsonc-eslint-parser": "^2.1.0", + "semver": "^7.5.3", + "tslib": "^2.3.0" }, - "engines": { - "node": ">=14.15.0" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "peerDependencies": { + "@typescript-eslint/parser": "^6.13.2 || ^7.0.0 || ^8.0.0", + "eslint-config-prettier": "^10.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@nx/vue": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/vue/-/vue-21.6.8.tgz", + "integrity": "sha512-RdybaMrKUVmFgMV2geaHzG6pezlbV/TdHYsxaY74EsCeoEiGExPUd00yGW5HPsrCIgimH7syW1a669ftpby4tw==", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "~1.0.2" + "@nx/devkit": "21.6.8", + "@nx/eslint": "21.6.8", + "@nx/js": "21.6.8", + "@nx/vite": "21.6.8", + "@nx/web": "21.6.8", + "picomatch": "^4.0.2", + "tslib": "^2.3.0" } }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/nx": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.14.tgz", - "integrity": "sha512-yprBOWV16eQntz5h5SShYHMVeN50fUb6yHfzsqNiFneCJeyVjyJ585m+2TuVbE11vT1amU0xCjHcSGfJBBnm8g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.8.14", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.8.14", - "@nx/nx-darwin-x64": "19.8.14", - "@nx/nx-freebsd-x64": "19.8.14", - "@nx/nx-linux-arm-gnueabihf": "19.8.14", - "@nx/nx-linux-arm64-gnu": "19.8.14", - "@nx/nx-linux-arm64-musl": "19.8.14", - "@nx/nx-linux-x64-gnu": "19.8.14", - "@nx/nx-linux-x64-musl": "19.8.14", - "@nx/nx-win32-arm64-msvc": "19.8.14", - "@nx/nx-win32-x64-msvc": "19.8.14" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/eslint-plugin-nx/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@nrwl/js": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nrwl/js/-/js-19.8.14.tgz", - "integrity": "sha512-DilRYVrqoecsNOkV2j4QDvcIjJXaO2krV7bbfGU/9TSmDzNcdB1R++dEgpa0seo2FrEfVgKffOl/6zzi8PhsgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/js": "19.8.14" - } - }, - "node_modules/@nrwl/js/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/devkit": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.14.tgz", - "integrity": "sha512-A8dCGttbuqgg9P56VTb0ElD2vM5nc5g0aLnX5PSXo4SkFXwd8DV5GgwJKWB1GO9hYyEtbj4gKek0KxnCtdav4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nrwl/devkit": "19.8.14", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 19 <= 21" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/js": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-19.8.14.tgz", - "integrity": "sha512-Nk0eEB2F/ZbBkH2iT+cgLWIittY8n5eOrA/uBBG2XMdencJZ9E2HNA/UzSGPZmD4EYVk0R1vm83k5+IMS1VAZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nrwl/js": "19.8.14", - "@nx/devkit": "19.8.14", - "@nx/workspace": "19.8.14", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^2.8.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "enquirer": "~2.3.6", - "fast-glob": "3.2.7", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "minimatch": "9.0.3", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "ts-node": "10.9.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^5.0.4" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-darwin-arm64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.14.tgz", - "integrity": "sha512-bZUFf23gAzuwVw71dR8rngye5aCR8Z/ouIo+KayjqB0LWWoi3WzO73s4S69ljftYt4n6z9wvD+Trbb1BKm2fPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-darwin-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.14.tgz", - "integrity": "sha512-UXXVea8icFG/3rFwpbLYsD6O4wlyJ1STQfOdhGK1Hyuga70AUUdrjVm7HzigAQP/Sb2Nzd7155YXHzfpRPDFYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-freebsd-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.14.tgz", - "integrity": "sha512-TK2xuXn+BI6hxGaRK1HRUPWeF/nOtezKSqM+6rbippfCzjES/crmp9l5nbI764MMthtUmykCyWvhEfkDca6kbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.14.tgz", - "integrity": "sha512-33rptyRraqaeQ2Kq6pcZKQqgnYY/7zcGH8fHXgKK7XzKk+7QuPViq+jMEUZP5E3UzZPkIYhsfmZcZqhNRvepJQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.14.tgz", - "integrity": "sha512-2E70qMKOhh7Fp4JGcRbRLvFKq0+ANVdAgSzH47plxOLygIeVAfIXRSuQbCI0EUFa5Sy6hImLaoRSB2GdgKihAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.14.tgz", - "integrity": "sha512-ltty/PDWqkYgu/6Ye65d7v5nh3D6e0n3SacoKRs2Vtfz5oHYRUkSKizKIhEVfRNuHn3d9j8ve1fdcCN4SDPUBQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.14.tgz", - "integrity": "sha512-JzE3BuO9RCBVdgai18CCze6KUzG0AozE0TtYFxRokfSC05NU3nUhd/o62UsOl7s6Bqt/9nwrW7JC8pNDiCi9OQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.14.tgz", - "integrity": "sha512-2rPvDOQLb7Wd6YiU88FMBiLtYco0dVXF99IJBRGAWv+WTI7MNr47OyK2ze+JOsbYY1d8aOGUvckUvCCZvZKEfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.14.tgz", - "integrity": "sha512-JxW+YPS+EjhUsLw9C6wtk9pQTG3psyFwxhab8y/dgk2s4AOTLyIm0XxgcCJVvB6i4uv+s1g0QXRwp6+q3IR6hg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.14.tgz", - "integrity": "sha512-RxiPlBWPcGSf9TzIIy62iKRdRhokXMDUsPub9DL2VdVyTMXPZQR25aY/PJeasJN1EQU74hg097LK2wSHi+vzOQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/js/node_modules/@nx/workspace": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.14.tgz", - "integrity": "sha512-Yb3d5WVjCyLill8MycKU+P/kbTyatKKqoUCu5zWokkysABiMWRLlrCYNzqwjTjeIIGj9MMGRHAQEemkBdL4tdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nrwl/workspace": "19.8.14", - "@nx/devkit": "19.8.14", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.8.14", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nrwl/js/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nrwl/js/node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.15.0" - } - }, - "node_modules/@nrwl/js/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nrwl/js/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@nrwl/js/node_modules/babel-plugin-macros": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", - "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.7.2", - "cosmiconfig": "^6.0.0", - "resolve": "^1.12.0" - } - }, - "node_modules/@nrwl/js/node_modules/cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/js/node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@nrwl/js/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@nrwl/js/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/js/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@nrwl/js/node_modules/nx": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.14.tgz", - "integrity": "sha512-yprBOWV16eQntz5h5SShYHMVeN50fUb6yHfzsqNiFneCJeyVjyJ585m+2TuVbE11vT1amU0xCjHcSGfJBBnm8g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.8.14", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.8.14", - "@nx/nx-darwin-x64": "19.8.14", - "@nx/nx-freebsd-x64": "19.8.14", - "@nx/nx-linux-arm-gnueabihf": "19.8.14", - "@nx/nx-linux-arm64-gnu": "19.8.14", - "@nx/nx-linux-arm64-musl": "19.8.14", - "@nx/nx-linux-x64-gnu": "19.8.14", - "@nx/nx-linux-x64-musl": "19.8.14", - "@nx/nx-win32-arm64-msvc": "19.8.14", - "@nx/nx-win32-x64-msvc": "19.8.14" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nrwl/js/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/js/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@nrwl/tao": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nrwl/tao/-/tao-19.8.14.tgz", - "integrity": "sha512-zBeYzzwg43T/Z8ZtLblv0fcKuqJULttqYDekSLILThXp3UOMSerEvruhUgwddCY1jUssfLscz8vacMKISv5X4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "nx": "19.8.14", - "tslib": "^2.3.0" - }, - "bin": { - "tao": "index.js" - } - }, - "node_modules/@nrwl/tao/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-darwin-arm64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.14.tgz", - "integrity": "sha512-bZUFf23gAzuwVw71dR8rngye5aCR8Z/ouIo+KayjqB0LWWoi3WzO73s4S69ljftYt4n6z9wvD+Trbb1BKm2fPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-darwin-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.14.tgz", - "integrity": "sha512-UXXVea8icFG/3rFwpbLYsD6O4wlyJ1STQfOdhGK1Hyuga70AUUdrjVm7HzigAQP/Sb2Nzd7155YXHzfpRPDFYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-freebsd-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.14.tgz", - "integrity": "sha512-TK2xuXn+BI6hxGaRK1HRUPWeF/nOtezKSqM+6rbippfCzjES/crmp9l5nbI764MMthtUmykCyWvhEfkDca6kbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.14.tgz", - "integrity": "sha512-33rptyRraqaeQ2Kq6pcZKQqgnYY/7zcGH8fHXgKK7XzKk+7QuPViq+jMEUZP5E3UzZPkIYhsfmZcZqhNRvepJQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.14.tgz", - "integrity": "sha512-2E70qMKOhh7Fp4JGcRbRLvFKq0+ANVdAgSzH47plxOLygIeVAfIXRSuQbCI0EUFa5Sy6hImLaoRSB2GdgKihAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.14.tgz", - "integrity": "sha512-ltty/PDWqkYgu/6Ye65d7v5nh3D6e0n3SacoKRs2Vtfz5oHYRUkSKizKIhEVfRNuHn3d9j8ve1fdcCN4SDPUBQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.14.tgz", - "integrity": "sha512-JzE3BuO9RCBVdgai18CCze6KUzG0AozE0TtYFxRokfSC05NU3nUhd/o62UsOl7s6Bqt/9nwrW7JC8pNDiCi9OQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.14.tgz", - "integrity": "sha512-2rPvDOQLb7Wd6YiU88FMBiLtYco0dVXF99IJBRGAWv+WTI7MNr47OyK2ze+JOsbYY1d8aOGUvckUvCCZvZKEfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.14.tgz", - "integrity": "sha512-JxW+YPS+EjhUsLw9C6wtk9pQTG3psyFwxhab8y/dgk2s4AOTLyIm0XxgcCJVvB6i4uv+s1g0QXRwp6+q3IR6hg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.14.tgz", - "integrity": "sha512-RxiPlBWPcGSf9TzIIy62iKRdRhokXMDUsPub9DL2VdVyTMXPZQR25aY/PJeasJN1EQU74hg097LK2wSHi+vzOQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/tao/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nrwl/tao/node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.15.0" - } - }, - "node_modules/@nrwl/tao/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nrwl/tao/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@nrwl/tao/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/tao/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@nrwl/tao/node_modules/nx": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.14.tgz", - "integrity": "sha512-yprBOWV16eQntz5h5SShYHMVeN50fUb6yHfzsqNiFneCJeyVjyJ585m+2TuVbE11vT1amU0xCjHcSGfJBBnm8g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.8.14", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.8.14", - "@nx/nx-darwin-x64": "19.8.14", - "@nx/nx-freebsd-x64": "19.8.14", - "@nx/nx-linux-arm-gnueabihf": "19.8.14", - "@nx/nx-linux-arm64-gnu": "19.8.14", - "@nx/nx-linux-arm64-musl": "19.8.14", - "@nx/nx-linux-x64-gnu": "19.8.14", - "@nx/nx-linux-x64-musl": "19.8.14", - "@nx/nx-win32-arm64-msvc": "19.8.14", - "@nx/nx-win32-x64-msvc": "19.8.14" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nrwl/tao/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/workspace": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nrwl/workspace/-/workspace-19.8.14.tgz", - "integrity": "sha512-I4eZtnHMkqnmOXVy6yN59fQopQZ+Sg0OFWwGluhKD5XPZULrlzECB8d4vblY9pcmQlN/6fat+KBrWkmKl41ZKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/workspace": "19.8.14" - } - }, - "node_modules/@nrwl/workspace/node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/devkit": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-19.8.14.tgz", - "integrity": "sha512-A8dCGttbuqgg9P56VTb0ElD2vM5nc5g0aLnX5PSXo4SkFXwd8DV5GgwJKWB1GO9hYyEtbj4gKek0KxnCtdav4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nrwl/devkit": "19.8.14", - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tmp": "~0.2.1", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 19 <= 21" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-darwin-arm64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-19.8.14.tgz", - "integrity": "sha512-bZUFf23gAzuwVw71dR8rngye5aCR8Z/ouIo+KayjqB0LWWoi3WzO73s4S69ljftYt4n6z9wvD+Trbb1BKm2fPg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-darwin-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-19.8.14.tgz", - "integrity": "sha512-UXXVea8icFG/3rFwpbLYsD6O4wlyJ1STQfOdhGK1Hyuga70AUUdrjVm7HzigAQP/Sb2Nzd7155YXHzfpRPDFYA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-freebsd-x64": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-19.8.14.tgz", - "integrity": "sha512-TK2xuXn+BI6hxGaRK1HRUPWeF/nOtezKSqM+6rbippfCzjES/crmp9l5nbI764MMthtUmykCyWvhEfkDca6kbA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-19.8.14.tgz", - "integrity": "sha512-33rptyRraqaeQ2Kq6pcZKQqgnYY/7zcGH8fHXgKK7XzKk+7QuPViq+jMEUZP5E3UzZPkIYhsfmZcZqhNRvepJQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-19.8.14.tgz", - "integrity": "sha512-2E70qMKOhh7Fp4JGcRbRLvFKq0+ANVdAgSzH47plxOLygIeVAfIXRSuQbCI0EUFa5Sy6hImLaoRSB2GdgKihAw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-linux-arm64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-19.8.14.tgz", - "integrity": "sha512-ltty/PDWqkYgu/6Ye65d7v5nh3D6e0n3SacoKRs2Vtfz5oHYRUkSKizKIhEVfRNuHn3d9j8ve1fdcCN4SDPUBQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-linux-x64-gnu": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-19.8.14.tgz", - "integrity": "sha512-JzE3BuO9RCBVdgai18CCze6KUzG0AozE0TtYFxRokfSC05NU3nUhd/o62UsOl7s6Bqt/9nwrW7JC8pNDiCi9OQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-linux-x64-musl": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-19.8.14.tgz", - "integrity": "sha512-2rPvDOQLb7Wd6YiU88FMBiLtYco0dVXF99IJBRGAWv+WTI7MNr47OyK2ze+JOsbYY1d8aOGUvckUvCCZvZKEfg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-19.8.14.tgz", - "integrity": "sha512-JxW+YPS+EjhUsLw9C6wtk9pQTG3psyFwxhab8y/dgk2s4AOTLyIm0XxgcCJVvB6i4uv+s1g0QXRwp6+q3IR6hg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/nx-win32-x64-msvc": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-19.8.14.tgz", - "integrity": "sha512-RxiPlBWPcGSf9TzIIy62iKRdRhokXMDUsPub9DL2VdVyTMXPZQR25aY/PJeasJN1EQU74hg097LK2wSHi+vzOQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nrwl/workspace/node_modules/@nx/workspace": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/@nx/workspace/-/workspace-19.8.14.tgz", - "integrity": "sha512-Yb3d5WVjCyLill8MycKU+P/kbTyatKKqoUCu5zWokkysABiMWRLlrCYNzqwjTjeIIGj9MMGRHAQEemkBdL4tdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nrwl/workspace": "19.8.14", - "@nx/devkit": "19.8.14", - "chalk": "^4.1.0", - "enquirer": "~2.3.6", - "nx": "19.8.14", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - } - }, - "node_modules/@nrwl/workspace/node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nrwl/workspace/node_modules/@yarnpkg/parsers": { - "version": "3.0.0-rc.46", - "resolved": "https://registry.npmjs.org/@yarnpkg/parsers/-/parsers-3.0.0-rc.46.tgz", - "integrity": "sha512-aiATs7pSutzda/rq8fnuPwTglyVwjM22bNnK2ZgjrpAjQHSSl3lztd2f9evst1W/qnC58DRz7T7QndUDumAR4Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "js-yaml": "^3.10.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=14.15.0" - } - }, - "node_modules/@nrwl/workspace/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@nrwl/workspace/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@nrwl/workspace/node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nrwl/workspace/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@nrwl/workspace/node_modules/nx": { - "version": "19.8.14", - "resolved": "https://registry.npmjs.org/nx/-/nx-19.8.14.tgz", - "integrity": "sha512-yprBOWV16eQntz5h5SShYHMVeN50fUb6yHfzsqNiFneCJeyVjyJ585m+2TuVbE11vT1amU0xCjHcSGfJBBnm8g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@napi-rs/wasm-runtime": "0.2.4", - "@nrwl/tao": "19.8.14", - "@yarnpkg/lockfile": "^1.1.0", - "@yarnpkg/parsers": "3.0.0-rc.46", - "@zkochan/js-yaml": "0.0.7", - "axios": "^1.7.4", - "chalk": "^4.1.0", - "cli-cursor": "3.1.0", - "cli-spinners": "2.6.1", - "cliui": "^8.0.1", - "dotenv": "~16.4.5", - "dotenv-expand": "~11.0.6", - "enquirer": "~2.3.6", - "figures": "3.2.0", - "flat": "^5.0.2", - "front-matter": "^4.0.2", - "ignore": "^5.0.4", - "jest-diff": "^29.4.1", - "jsonc-parser": "3.2.0", - "lines-and-columns": "2.0.3", - "minimatch": "9.0.3", - "node-machine-id": "1.1.12", - "npm-run-path": "^4.0.1", - "open": "^8.4.0", - "ora": "5.3.0", - "semver": "^7.5.3", - "string-width": "^4.2.3", - "strong-log-transformer": "^2.1.0", - "tar-stream": "~2.2.0", - "tmp": "~0.2.1", - "tsconfig-paths": "^4.1.2", - "tslib": "^2.3.0", - "yargs": "^17.6.2", - "yargs-parser": "21.1.1" - }, - "bin": { - "nx": "bin/nx.js", - "nx-cloud": "bin/nx-cloud.js" - }, - "optionalDependencies": { - "@nx/nx-darwin-arm64": "19.8.14", - "@nx/nx-darwin-x64": "19.8.14", - "@nx/nx-freebsd-x64": "19.8.14", - "@nx/nx-linux-arm-gnueabihf": "19.8.14", - "@nx/nx-linux-arm64-gnu": "19.8.14", - "@nx/nx-linux-arm64-musl": "19.8.14", - "@nx/nx-linux-x64-gnu": "19.8.14", - "@nx/nx-linux-x64-musl": "19.8.14", - "@nx/nx-win32-arm64-msvc": "19.8.14", - "@nx/nx-win32-x64-msvc": "19.8.14" - }, - "peerDependencies": { - "@swc-node/register": "^1.8.0", - "@swc/core": "^1.3.85" - }, - "peerDependenciesMeta": { - "@swc-node/register": { - "optional": true - }, - "@swc/core": { - "optional": true - } - } - }, - "node_modules/@nrwl/workspace/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@nx/cypress": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/cypress/-/cypress-21.6.8.tgz", - "integrity": "sha512-r/HmyxNA4wFM6iIc+aXeMDmNEO3qRkea4/cCOjNXSaEksBReHPRlQTz/M5n58xpqxAhOSVHDBH162pznCGP1cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "21.6.8", - "@nx/eslint": "21.6.8", - "@nx/js": "21.6.8", - "@phenomnomnominal/tsquery": "~5.0.1", - "detect-port": "^1.5.1", - "semver": "^7.6.3", - "tree-kill": "1.2.2", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "cypress": ">= 3 < 15" - }, - "peerDependenciesMeta": { - "cypress": { - "optional": true - } - } - }, - "node_modules/@nx/devkit": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/devkit/-/devkit-21.6.8.tgz", - "integrity": "sha512-N0cj0NqdxY2pcI0IJV+fAu362B6tppdv2ohSBNGacNeSqxfAlJxO5TFZePDmxX5nt0t9hAqT+iasfu4BSYGfZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ejs": "^3.1.7", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "minimatch": "9.0.3", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "yargs-parser": "21.1.1" - }, - "peerDependencies": { - "nx": ">= 20 <= 22" - } - }, - "node_modules/@nx/eslint": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/eslint/-/eslint-21.6.8.tgz", - "integrity": "sha512-dloTsg1n1zlAyP2Ohwiw9vhoUrF5XYo5pdmxAmnpE/P+e4ihWQfGtlu3JvEQNBp9Wwk4E7XkJVmVhJOm47PIww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "21.6.8", - "@nx/js": "21.6.8", - "semver": "^7.5.3", - "tslib": "^2.3.0", - "typescript": "~5.9.2" - }, - "peerDependencies": { - "@zkochan/js-yaml": "0.0.7", - "eslint": "^8.0.0 || ^9.0.0" - }, - "peerDependenciesMeta": { - "@zkochan/js-yaml": { - "optional": true - } - } - }, - "node_modules/@nx/eslint-plugin": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/eslint-plugin/-/eslint-plugin-21.6.8.tgz", - "integrity": "sha512-uDJxGrNF9WmP35pSR6EjMA720GIb2XpbygA6u26lhS9/VJt6pC+/bvLwXLf0bG3sWHjmpUNsIWlK4WMQe9q8wg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "21.6.8", - "@nx/js": "21.6.8", - "@phenomnomnominal/tsquery": "~5.0.1", - "@typescript-eslint/type-utils": "^8.0.0", - "@typescript-eslint/utils": "^8.0.0", - "chalk": "^4.1.0", - "confusing-browser-globals": "^1.0.9", - "globals": "^15.9.0", - "jsonc-eslint-parser": "^2.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.13.2 || ^7.0.0 || ^8.0.0", - "eslint-config-prettier": "^10.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/@nx/js": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/js/-/js-21.6.8.tgz", - "integrity": "sha512-I9Wu//28DXiSIFoW1IGbLRRfULITkYMOKGMnityQ71iJ8+9vi90a8xFyCWt4VzNxpMEreaoNynWJTf+I8UTGaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.23.2", - "@babel/plugin-proposal-decorators": "^7.22.7", - "@babel/plugin-transform-class-properties": "^7.22.5", - "@babel/plugin-transform-runtime": "^7.23.2", - "@babel/preset-env": "^7.23.2", - "@babel/preset-typescript": "^7.22.5", - "@babel/runtime": "^7.22.6", - "@nx/devkit": "21.6.8", - "@nx/workspace": "21.6.8", - "@zkochan/js-yaml": "0.0.7", - "babel-plugin-const-enum": "^1.0.1", - "babel-plugin-macros": "^3.1.0", - "babel-plugin-transform-typescript-metadata": "^0.3.1", - "chalk": "^4.1.0", - "columnify": "^1.6.0", - "detect-port": "^1.5.1", - "enquirer": "~2.3.6", - "ignore": "^5.0.4", - "js-tokens": "^4.0.0", - "jsonc-parser": "3.2.0", - "npm-package-arg": "11.0.1", - "npm-run-path": "^4.0.1", - "ora": "5.3.0", - "picocolors": "^1.1.0", - "picomatch": "4.0.2", - "semver": "^7.5.3", - "source-map-support": "0.5.19", - "tinyglobby": "^0.2.12", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "verdaccio": "^6.0.5" - }, - "peerDependenciesMeta": { - "verdaccio": { - "optional": true - } - } - }, - "node_modules/@nx/js/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@nx/nx-darwin-arm64": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-arm64/-/nx-darwin-arm64-21.6.8.tgz", - "integrity": "sha512-MG5bhSYhG49r+e0mLuztQVHz1sEy7cs8BvZJ56mm7JNQ1VfbaTyLAR7VcNw8O/1mJA8jYcg9fmxOIZOUnY1cEQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@nx/nx-darwin-x64": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-darwin-x64/-/nx-darwin-x64-21.6.8.tgz", - "integrity": "sha512-e9oXVTd6U6RFEc3k22PGoe5OSy40fyyytl+svSJQmK+5rxZalvAUna/mXtFcQC9m6No2daqqpfAZlyN5nG6WHw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@nx/nx-freebsd-x64": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-freebsd-x64/-/nx-freebsd-x64-21.6.8.tgz", - "integrity": "sha512-gK3rsTXQj0hHCyaAvZmPZeCPkb3jzesgtkXuZf+7pCm5b4wiEA1i22ufp1UzwaTmWgbub/6NVMEDOGsVcay8mA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-21.6.8.tgz", - "integrity": "sha512-TXt3HTFhM4kuL9larxBuo3XpSngoA1JCtHavfYLRC3A8knACi7LwNQwnF5RWAcYgKMVE3/8IAhV8LuemXrPKKw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-21.6.8.tgz", - "integrity": "sha512-QwZREYIhqhDVEIf+KAv2VFipxMUoULXXS3qyLX3/q/4u8Y32fyM5wd+FXpv89cRCiveVsZp8io2W178R6lfKng==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@nx/nx-linux-arm64-musl": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-21.6.8.tgz", - "integrity": "sha512-UZJyrZ6utU8g1W7E31iHDhWj1SjMidmDNyrVP4xK6IUrotx6qGrwfwWqzqvphhc1cA7w4Zz9N/rCCPQkdHzjLw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@nx/nx-linux-x64-gnu": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-21.6.8.tgz", - "integrity": "sha512-HXINTg4P0/Yj76vsvqBAb7MNlLpkH1pl9JF2blXScOFXWzNoStd7b6xyrpCROdmi0Hk8y3UEwc8OIyLFIfixJg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@nx/nx-linux-x64-musl": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-21.6.8.tgz", - "integrity": "sha512-2YbXLhuSlElCtQTR1Ib94O3T4fX9uzSIkUMYGL3n04agG0HemXoxJa91TWwwOUMbEZffkhcPsJBOh2S5l47s9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-21.6.8.tgz", - "integrity": "sha512-/VSGtqa1oGHo5n24R39ZuGxMrGyf7pxFuCtL5hAzBHdTxFg/VZomPGd7BeV5VN5SbIw+fie+nTGkC5q3TOPGXw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@nx/nx-win32-x64-msvc": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-21.6.8.tgz", - "integrity": "sha512-xeBL7PcDqHH/Zw4d2A2qP7eLImzzcMO3hiKs5G42Wi92ACejAdUqpIduTL4RpArsXIHm5VEbE4KvHNii1mMU1A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@nx/vite": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/vite/-/vite-21.6.8.tgz", - "integrity": "sha512-+0d2A8rAkWH5wSttlz36gfTov02pdE9yLqe/FjaaRJtb/4tmRi1pahKvCxStrct2sY6uEktel0PU6y5IRoCF8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "21.6.8", - "@nx/js": "21.6.8", - "@phenomnomnominal/tsquery": "~5.0.1", - "@typescript-eslint/type-utils": "^8.0.0", - "@typescript-eslint/utils": "^8.0.0", - "chalk": "^4.1.0", - "confusing-browser-globals": "^1.0.9", - "globals": "^15.9.0", - "jsonc-eslint-parser": "^2.1.0", - "semver": "^7.5.3", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^6.13.2 || ^7.0.0 || ^8.0.0", - "eslint-config-prettier": "^10.0.0" - }, - "peerDependenciesMeta": { - "eslint-config-prettier": { - "optional": true - } - } - }, - "node_modules/@nx/vue": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/vue/-/vue-21.6.8.tgz", - "integrity": "sha512-RdybaMrKUVmFgMV2geaHzG6pezlbV/TdHYsxaY74EsCeoEiGExPUd00yGW5HPsrCIgimH7syW1a669ftpby4tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nx/devkit": "21.6.8", - "@nx/eslint": "21.6.8", - "@nx/js": "21.6.8", - "@nx/vite": "21.6.8", - "@nx/web": "21.6.8", - "picomatch": "^4.0.2", - "tslib": "^2.3.0" - } - }, - "node_modules/@nx/web": { - "version": "21.6.8", - "resolved": "https://registry.npmjs.org/@nx/web/-/web-21.6.8.tgz", - "integrity": "sha512-0JFoX/wL95jlnpKpYkptodWmuC0z4qGxFSRC7llEdP5hc7Spr1nDJ55GODrhr9M6lCb94vv7amuWk8SAyBw9iw==", + "node_modules/@nx/web": { + "version": "21.6.8", + "resolved": "https://registry.npmjs.org/@nx/web/-/web-21.6.8.tgz", + "integrity": "sha512-0JFoX/wL95jlnpKpYkptodWmuC0z4qGxFSRC7llEdP5hc7Spr1nDJ55GODrhr9M6lCb94vv7amuWk8SAyBw9iw==", "dev": true, "license": "MIT", "dependencies": { @@ -5972,6 +4144,16 @@ "dev": true, "license": "MIT" }, + "node_modules/@sit-onyx/icons": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sit-onyx/icons/-/icons-1.3.0.tgz", + "integrity": "sha512-HfgMNLIMC66TFnjJ5Cy5xku3fZRsdrbxJB+Giei7lTBAk29tqasL+CN+Hqv7f5Z63+dLqg6nzLROC+j02QERtg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=20" + } + }, "node_modules/@tailwindcss/node": { "version": "4.1.14", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.14.tgz", @@ -6210,6 +4392,66 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.5.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.5.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.0.5", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.5.0", + "@emnapi/runtime": "^1.5.0", + "@tybys/wasm-util": "^0.10.1" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.1.14", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz", @@ -6258,16 +4500,6 @@ "tailwindcss": "4.1.14" } }, - "node_modules/@sit-onyx/icons": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@sit-onyx/icons/-/icons-1.3.0.tgz", - "integrity": "sha512-HfgMNLIMC66TFnjJ5Cy5xku3fZRsdrbxJB+Giei7lTBAk29tqasL+CN+Hqv7f5Z63+dLqg6nzLROC+j02QERtg==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=20" - } - }, "node_modules/@tailwindcss/typography": { "version": "0.5.19", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz", diff --git a/services/frontend/package.json b/services/frontend/package.json index ffb355a8..28f06d71 100644 --- a/services/frontend/package.json +++ b/services/frontend/package.json @@ -30,7 +30,6 @@ "devDependencies": { "@eslint/js": "^9.36.0", "@intlify/unplugin-vue-i18n": "^11.0.0", - "@nrwl/eslint-plugin-nx": "^19.8.14", "@nx/cypress": "^21.6.4", "@nx/eslint": "^21.6.4", "@nx/eslint-plugin": "^21.6.4", diff --git a/tools/allow_chart_bump.py b/tools/allow_chart_bump.py new file mode 100644 index 00000000..0338c173 --- /dev/null +++ b/tools/allow_chart_bump.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import json +import os +import re +import sys +import urllib.request + + +API_VERSION = "2022-11-28" + + +def github_request(url: str, token: str, accept: str | None = None): + req = urllib.request.Request(url) + req.add_header("Authorization", f"Bearer {token}") + req.add_header("Accept", accept or "application/vnd.github+json") + req.add_header("X-GitHub-Api-Version", API_VERSION) + with urllib.request.urlopen(req) as resp: + return json.load(resp) + + +def parse_pr_number(event_path: str | None) -> int | None: + if not event_path or not os.path.exists(event_path): + return None + with open(event_path, "r", encoding="utf-8") as handle: + event = json.load(handle) + + if "pull_request" in event: + return event["pull_request"].get("number") + + messages: list[str] = [] + head = event.get("head_commit", {}) + if head.get("message"): + messages.append(head["message"]) + for commit in event.get("commits", []): + if commit.get("message"): + messages.append(commit["message"]) + + for msg in messages: + match = re.search(r"Merge pull request #(\d+)", msg) + if match: + return int(match.group(1)) + match = re.search(r"\(#(\d+)\)\s*$", msg) + if match: + return int(match.group(1)) + return None + + +def pr_has_chart_bump(repo: str, pr_number: int, token: str) -> bool: + url = f"https://api.github.com/repos/{repo}/issues/{pr_number}" + data = github_request(url, token) + labels = {lbl["name"] for lbl in data.get("labels", [])} + return "chart-bump" in labels + + +def find_pr_by_commit(repo: str, sha: str, token: str) -> int | None: + url = f"https://api.github.com/repos/{repo}/commits/{sha}/pulls" + data = github_request( + url, + token, + accept="application/vnd.github+json, application/vnd.github.groot-preview+json", + ) + if data: + return data[0].get("number") + return None + + +def find_pr_by_merge_sha(repo: str, sha: str, token: str) -> int | None: + for page in range(1, 4): + url = ( + f"https://api.github.com/repos/{repo}/pulls" + f"?state=closed&sort=updated&direction=desc&per_page=100&page={page}" + ) + data = github_request(url, token) + for pr in data: + if pr.get("merge_commit_sha") == sha: + return pr.get("number") + if len(data) < 100: + break + return None + + +def main() -> int: + repo = os.environ.get("GITHUB_REPOSITORY") + sha = os.environ.get("GITHUB_SHA") + token = os.environ.get("GH_TOKEN") + output_path = os.environ.get("GITHUB_OUTPUT") + event_path = os.environ.get("GITHUB_EVENT_PATH") + + if not repo or not sha or not token or not output_path: + print("Missing required environment variables for chart-bump check.", file=sys.stderr) + return 1 + + try: + pr_number = parse_pr_number(event_path) + if pr_number is None: + pr_number = find_pr_by_commit(repo, sha, token) + if pr_number is None: + pr_number = find_pr_by_merge_sha(repo, sha, token) + if pr_number is None: + allow = False + else: + allow = pr_has_chart_bump(repo, pr_number, token) + except Exception as exc: + print(f"Failed to query PRs for commit: {exc}", file=sys.stderr) + return 1 + + out = f"allow={'true' if allow else 'false'}\n" + with open(output_path, "a", encoding="utf-8") as handle: + handle.write(out) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/bump_chart_versions.py b/tools/bump_chart_versions.py new file mode 100644 index 00000000..eca5101f --- /dev/null +++ b/tools/bump_chart_versions.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +import argparse +import pathlib +import re +import sys + +from ruamel.yaml import YAML +from ruamel.yaml.scalarstring import DoubleQuotedScalarString, SingleQuotedScalarString + +ROOT = pathlib.Path(__file__).resolve().parents[1] + + +def _to_chart_version(app_version: str) -> str: + """Convert app_version to a SemVer 2.0.0 compliant Helm chart version. + + Examples: + - "2.0.0.post20250904105936" -> "2.0.0-post.20250904105936" + - "2.0.1" -> "2.0.1" + - "2.0.1-rc.1" -> "2.0.1-rc.1" + - Fallback: if an unexpected format is provided, try to keep a valid semver + by extracting the leading MAJOR.MINOR.PATCH. + """ + normalized = app_version.lstrip("vV") + # Case 1: our prepare-release format "X.Y.Z.post" + m = re.fullmatch(r"(?P\d+\.\d+\.\d+)\.post(?P\d+)", normalized) + if m: + return f"{m.group('base')}-post.{m.group('ts')}" + + # Case 2: already valid semver (optionally with pre-release or build metadata) + if re.fullmatch(r"\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?", normalized): + return normalized + + # Fallback: keep only the base version if present + base = re.match(r"(\d+\.\d+\.\d+)", normalized) + return base.group(1) if base else normalized + + +def _preserve_style(old_value, new_value: str): + if isinstance(old_value, DoubleQuotedScalarString): + return DoubleQuotedScalarString(new_value) + if isinstance(old_value, SingleQuotedScalarString): + return SingleQuotedScalarString(new_value) + return new_value + + +def bump_chart(chart_path: pathlib.Path, app_version: str, mode: str): + yaml = YAML() + yaml.preserve_quotes = True + yaml.width = 4096 + + data = yaml.load(chart_path.read_text()) + if data is None: + return + + if mode in ("app-and-chart", "app-only"): + if not app_version: + raise ValueError("app_version is required for mode app-and-chart or app-only") + old_app = data.get("appVersion") + data["appVersion"] = _preserve_style(old_app, str(app_version)) + + if mode in ("app-and-chart", "chart-only"): + if mode == "chart-only" and not app_version: + raise ValueError("chart-only mode requires chart_version provided via app_version argument") + chart_version = _to_chart_version(str(app_version)) + old_version = data.get("version") + data["version"] = _preserve_style(old_version, chart_version) + + with chart_path.open("w") as handle: + yaml.dump(data, handle) + + +def main(): + p = argparse.ArgumentParser() + p.add_argument('--app-version', help='App version to set (required for app-and-chart/app-only)') + p.add_argument('--chart-version', help='Chart version to set (required for chart-only)') + p.add_argument( + '--mode', + choices=['app-and-chart', 'app-only', 'chart-only'], + default='app-and-chart', + help='app-and-chart: bump appVersion and chart version; app-only: bump only appVersion; chart-only: bump only chart version' + ) + args = p.parse_args() + + app_version = args.app_version + if args.mode == 'chart-only': + app_version = args.chart_version + + charts = list((ROOT / 'infrastructure').glob('*/Chart.yaml')) + for ch in charts: + bump_chart(ch, app_version, args.mode) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/bump_pyproject_deps.py b/tools/bump_pyproject_deps.py new file mode 100644 index 00000000..8e3688b8 --- /dev/null +++ b/tools/bump_pyproject_deps.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +import argparse +import pathlib +import re +import sys +from typing import Any, List, Optional + +import tomlkit + +ROOT = pathlib.Path(__file__).resolve().parents[1] + +# Only bump versions for internal libs here +LIBS_VERSION_FILES = [ + ROOT / 'libs' / 'rag-core-lib' / 'pyproject.toml', + ROOT / 'libs' / 'rag-core-api' / 'pyproject.toml', + ROOT / 'libs' / 'admin-api-lib' / 'pyproject.toml', + ROOT / 'libs' / 'extractor-api-lib' / 'pyproject.toml', +] + +# Service pins to update after libs are published +SERVICE_PINS = { + ROOT / 'services' / 'rag-backend' / 'pyproject.toml': { + 'tool.poetry.group.prod.dependencies.rag-core-api': '=={v}', + 'tool.poetry.group.prod.dependencies.rag-core-lib': '=={v}', + }, + ROOT / 'services' / 'admin-backend' / 'pyproject.toml': { + 'tool.poetry.group.prod.dependencies.admin-api-lib': '=={v}', + 'tool.poetry.group.prod.dependencies.rag-core-lib': '=={v}', + }, + ROOT / 'services' / 'document-extractor' / 'pyproject.toml': { + 'tool.poetry.group.prod.dependencies.extractor-api-lib': '=={v}', + }, +} + + +def replace_version_line(text: str, new_version: str) -> str: + lines = text.splitlines(keepends=True) + in_tool_poetry = False + for i, line in enumerate(lines): + stripped = line.strip() + if stripped.startswith('[tool.poetry]'): + in_tool_poetry = True + continue + if in_tool_poetry and stripped.startswith('[') and not stripped.startswith('[tool.poetry]'): + # left the section without finding version; stop scanning section + break + if in_tool_poetry and stripped.startswith('version'): + # Replace only the version value, keep indentation and spacing + lines[i] = re.sub(r'version\s*=\s*"[^"]*"', f'version = "{new_version}"', line) + return ''.join(lines) + # If no version line found, append it to the [tool.poetry] section + out = ''.join(lines) + return out + f"\n[tool.poetry]\nversion = \"{new_version}\"\n" + + +def _get_table(doc: tomlkit.TOMLDocument, path: List[str]) -> Optional[Any]: + ref: Any = doc + for key in path: + try: + if key not in ref: # mapping-like check + return None + ref = ref[key] + except Exception: + return None + return ref + + +def bump(version: str, bump_libs: bool = True, bump_service_pins: bool = True): + # 1) bump libs versions (textual, non-destructive) + if bump_libs: + for file in LIBS_VERSION_FILES: + txt = file.read_text() + new_txt = replace_version_line(txt, version) + file.write_text(new_txt) + print(f"Updated {file} -> tool.poetry.version = {version}") + + # 2) bump service pins only inside [tool.poetry.group.prod.dependencies] + if bump_service_pins: + for file, mapping in SERVICE_PINS.items(): + txt = file.read_text() + doc = tomlkit.parse(txt) + deps = _get_table(doc, [ + 'tool', 'poetry', 'group', 'prod', 'dependencies' + ]) + if deps is None or not hasattr(deps, '__contains__'): + print(f"Skip {file}: prod dependencies table not found") + file.write_text(tomlkit.dumps(doc)) + continue + for dotted, template in mapping.items(): + pkg = dotted.split('.')[-1] + if pkg in deps: + val = template.format(v=version) + deps[pkg] = val + print(f"Pinned {file} -> {pkg} = {val}") + else: + print(f"Skip {file}: {pkg} not present in prod dependencies") + file.write_text(tomlkit.dumps(doc)) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument('--version', required=True) + ap.add_argument('--bump-libs', action='store_true', help='Bump versions in internal libs only') + ap.add_argument('--bump-service-pins', action='store_true', help='Bump service dependency pins only') + args = ap.parse_args() + + # Backward compatibility: if neither flag is provided, do both + bump_libs = args.bump_libs or (not args.bump_libs and not args.bump_service_pins) + bump_service_pins = args.bump_service_pins or (not args.bump_libs and not args.bump_service_pins) + + bump(args.version, bump_libs=bump_libs, bump_service_pins=bump_service_pins) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/tools/publish_libs.sh b/tools/publish_libs.sh new file mode 100755 index 00000000..99a5fe8d --- /dev/null +++ b/tools/publish_libs.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Shared helpers for publishing internal libs and waiting for index visibility. +set -euo pipefail + +publish_lib() { + local lib="$1" + local repo_flag="$2" # "" or "-r testpypi" + local version="$3" + local path="${4:-libs/$lib}" + if [ ! -d "$path" ]; then + echo "Missing $path" >&2 + exit 1 + fi + local pyproject="$path/pyproject.toml" + if [ -f "$pyproject" ]; then + python - "$pyproject" "$version" <<'PY' +import re +import sys +from pathlib import Path + +pyproject = Path(sys.argv[1]) +version = sys.argv[2] +text = pyproject.read_text() +pattern = r'^(\s*rag-core-lib\s*=\s*)\{[^\n]*path\s*=\s*"[^"]+"[^\n]*\}\s*$' +replacement = r'\1"=={}"'.format(version) +new_text = re.sub(pattern, replacement, text, flags=re.M) +if new_text != text: + pyproject.write_text(new_text) + print(f"Rewrote rag-core-lib path dependency in {pyproject} to =={version}") +PY + fi + echo "Publishing $lib ($version) to ${repo_flag:-pypi default}" + (cd "$path" && poetry version "$version" && poetry build && poetry publish $repo_flag) +} + +wait_for_index() { + local name="$1" + local version="$2" + local base_url="$3" + local label="$4" + echo "Waiting for $name==$version on $label" + for _ in $(seq 1 60); do + json_ok=false + simple_ok=false + if curl -fsSL "$base_url/pypi/$name/json" -o /tmp/"$name".json; then + if jq -e --arg v "$version" '.releases[$v] | length > 0' /tmp/"$name".json >/dev/null; then + json_ok=true + fi + fi + if curl -fsSL "$base_url/simple/$name/" -o /tmp/"$name".html; then + if grep -q "$version" /tmp/"$name".html; then + simple_ok=true + fi + fi + if [ "$json_ok" = true ] && [ "$simple_ok" = true ]; then + echo "$name==$version visible on $label" + return 0 + fi + sleep 5 + done + echo "$name==$version not visible on $label after waiting" >&2 + return 1 +} diff --git a/tools/set_rag_core_lib_testpypi_source.py b/tools/set_rag_core_lib_testpypi_source.py new file mode 100644 index 00000000..e2a87cf6 --- /dev/null +++ b/tools/set_rag_core_lib_testpypi_source.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +from pathlib import Path + +import tomlkit + + +REPO_ROOT = Path(__file__).resolve().parents[1] +LIB_PYPROJECTS = [ + REPO_ROOT / "libs" / "rag-core-lib" / "pyproject.toml", + REPO_ROOT / "libs" / "rag-core-api" / "pyproject.toml", + REPO_ROOT / "libs" / "admin-api-lib" / "pyproject.toml", + REPO_ROOT / "libs" / "extractor-api-lib" / "pyproject.toml", +] +RAG_CORE_LIB = "rag-core-lib" + + +def get_dependencies(doc: tomlkit.TOMLDocument): + ref = doc + for key in ["tool", "poetry", "dependencies"]: + if key not in ref: + return None + ref = ref[key] + return ref + + +def set_rag_core_lib_source(pyproject: Path) -> bool: + if not pyproject.exists(): + return False + + doc = tomlkit.parse(pyproject.read_text()) + deps = get_dependencies(doc) + if deps is None or RAG_CORE_LIB not in deps: + return False + + val = deps[RAG_CORE_LIB] + if isinstance(val, str): + it = tomlkit.inline_table() + it.add("version", val) + it.add("source", "testpypi") + deps[RAG_CORE_LIB] = it + elif hasattr(val, "get"): + if "path" in val: + return False + val["source"] = "testpypi" + else: + return False + + doc["tool"]["poetry"]["dependencies"] = deps + pyproject.write_text(tomlkit.dumps(doc)) + return True + + +def main() -> int: + for pyproject in LIB_PYPROJECTS: + set_rag_core_lib_source(pyproject) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/tools/update-helm-values.py b/tools/update-helm-values.py deleted file mode 100644 index 283ad051..00000000 --- a/tools/update-helm-values.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python3 -""" -Update Helm values.yaml with new version tags for specific services only, -preserving all existing formatting and disabling line wrapping via ruamel.yaml. -""" - -import sys -from ruamel.yaml import YAML -from ruamel.yaml.scalarstring import DoubleQuotedScalarString - -def update_helm_values(file_path, new_version): - """Update specific service image tags in values.yaml with ruamel.yaml.""" - yaml = YAML() - yaml.preserve_quotes = True - yaml.width = float('inf') # ← no wrapping, even for long lines - yaml.indent(mapping=2, sequence=4, offset=2) - - with open(file_path, 'r') as f: - data = yaml.load(f) - - services_to_update = [ - ('backend', 'mcp', 'image', 'tag'), - ('backend', 'image', 'tag'), - ('frontend', 'image', 'tag'), - ('adminBackend', 'image', 'tag'), - ('extractor', 'image', 'tag'), - ('adminFrontend', 'image', 'tag'), - ] - - new_tag = f"v{new_version}" - updated_count = 0 - - for path in services_to_update: - node = data - try: - for key in path[:-1]: - node = node[key] - tag_key = path[-1] - if tag_key in node: - old = node[tag_key] - if str(old) != new_tag: - if hasattr(old, 'style') and old.style in ('"', "'"): - node[tag_key] = DoubleQuotedScalarString(new_tag) - else: - node[tag_key] = new_tag - print(f"āœ… Updated {'.'.join(path)}: {old!r} → {new_tag!r}") - updated_count += 1 - else: - print(f"āš ļø {'.'.join(path)} already at {new_tag!r}") - else: - print(f"āŒ Could not find {'.'.join(path)}") - except (KeyError, TypeError) as e: - print(f"āŒ Could not access {'.'.join(path)}: {e}") - - if updated_count: - with open(file_path, 'w') as f: - yaml.dump(data, f) - print(f"\nāœ… Updated {updated_count} tag(s) in {file_path}") - return True - else: - print(f"\nāš ļø No changes needed in {file_path}") - return False - -if __name__ == '__main__': - if len(sys.argv) != 2: - print("Usage: update-helm-values.py ") - sys.exit(1) - - version = sys.argv[1] - file_path = 'infrastructure/rag/values.yaml' - success = update_helm_values(file_path, version) - sys.exit(0 if success else 1) diff --git a/tools/update_deploy_values.py b/tools/update_deploy_values.py new file mode 100644 index 00000000..4f460830 --- /dev/null +++ b/tools/update_deploy_values.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""Update deployment repo values file with image registry/tag overrides.""" + +from __future__ import annotations + +import argparse +from pathlib import Path +from typing import Any, Dict + +import yaml + + +def ensure(mapping: Dict[str, Any], key: str) -> Dict[str, Any]: + """Ensure key exists and is a dict.""" + if key not in mapping or mapping[key] is None: + mapping[key] = {} + if not isinstance(mapping[key], dict): + raise TypeError(f"Expected dict at {key}, got {type(mapping[key])}") + return mapping[key] + + +def update_values(values_path: Path, image_registry: str, image_tag: str) -> None: + if values_path.exists(): + data = yaml.safe_load(values_path.read_text(encoding="utf-8")) or {} + else: + data = {} + + components = { + "backend": "rag-backend", + "adminBackend": "admin-backend", + "extractor": "document-extractor", + "frontend": "frontend", + "adminFrontend": "admin-frontend", + } + + for key, image_name in components.items(): + comp = ensure(data, key) + image_block = ensure(comp, "image") + image_block["repository"] = f"{image_registry}/{image_name}" + image_block["tag"] = image_tag + + backend = ensure(data, "backend") + mcp = ensure(backend, "mcp") + mcp_image = ensure(mcp, "image") + mcp_image["repository"] = f"{image_registry}/mcp-server" + mcp_image["tag"] = image_tag + + values_path.write_text(yaml.safe_dump(data, sort_keys=False), encoding="utf-8") + + +def main() -> None: + parser = argparse.ArgumentParser(description="Update image overrides in a values file.") + parser.add_argument("--values-file", required=True, help="Path to values-qa.yaml in deployment repo") + parser.add_argument("--image-registry", required=True, help="Image registry base (e.g. registry.onstackit.cloud/qa-rag-template)") + parser.add_argument("--image-tag", required=True, help="Image tag/version to set") + args = parser.parse_args() + + update_values(Path(args.values_file), args.image_registry, args.image_tag) + + +if __name__ == "__main__": + main()