diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 77ef770e1..f3889480f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,7 +37,7 @@ jobs: sudo rm -rf /usr/local/lib/android sudo rm -rf /opt/ghc - name: checkout code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v7.0.1 - name: setup java uses: actions/setup-java@v5.2.0 with: @@ -96,7 +96,7 @@ jobs: OPEN_API_TEST: "true" steps: - name: checkout code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v7.0.1 - name: setup java uses: actions/setup-java@v5.2.0 with: @@ -118,14 +118,14 @@ jobs: runs-on: ubuntu-latest steps: - name: checkout code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v7.0.1 - name: Build docker image run: docker build -t cda:build-latest . build-schema-migration-image: runs-on: ubuntu-latest steps: - name: checkout code - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v7.0.1 # No uploads, we're just verifying that nothing broke the docker image. - name: Build Migration image uses: ./.github/actions/database-migration-image @@ -143,7 +143,7 @@ jobs: if: always() && (github.ref_name == 'develop') steps: - name: Badge Branch - uses: actions/checkout@v5.0.0 + uses: actions/checkout@v7.0.1 with: ref: badges fetch-depth: 1 diff --git a/.github/workflows/web-gui-checks.yml b/.github/workflows/web-gui-checks.yml index e7056bdab..95a02b845 100644 --- a/.github/workflows/web-gui-checks.yml +++ b/.github/workflows/web-gui-checks.yml @@ -22,10 +22,8 @@ on: jobs: audit: runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - + - uses: actions/checkout@v7.0.1 - name: install node for cda-gui audit uses: actions/setup-node@v4 with: diff --git a/AGENTS.md b/AGENTS.md index df2a619e5..544f35e89 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ Guidance for coding agents working in `USACE/cwms-data-api`. - GitHub repository: `USACE/cwms-data-api` - Primary branch: `develop` - Product: CWMS Data API (CDA), formerly RADAR, a REST API for USACE CWMS water data. -- Runtime/build target: Java 11. Newer JDKs may work, but do not introduce Java APIs beyond Java 11. +- Runtime/build target: Java 17. Newer JDKs may work, but do not introduce Java APIs beyond Java 17. - License/contribution model: MIT license with DCO sign-off expectations in `CONTRIBUTING.md` and `CONTRIBUTORS.md`. - Formal `CODEOWNERS` is not present. Treat maintainership/review routing as social context, not policy. Visible long-running contributors include Mike Neilson, Ryan Ripken/RMA, Adam Korynta, Bryson Spilman, Ryan Miles, Zach Olson, and Charles Graham. Verify current reviewers on GitHub before assigning or naming people in PR text. diff --git a/Dockerfile b/Dockerfile index 61571a44a..c1b458a36 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,6 @@ -FROM gradle:8.5-jdk11 AS builder +FROM gradle:8.5-jdk17 AS builder USER $USER RUN --mount=type=cache,target=/home/gradle/.gradle -WORKDIR /builddir -COPY . /builddir/ RUN apt update && apt install -y curl ENV NVM_DIR="/root/.nvm" RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash @@ -12,55 +10,16 @@ SHELL ["/bin/bash", "-c"] RUN . "$NVM_DIR/nvm.sh" && nvm install $NODE_VERSION && nvm use $NODE_VERSION ENV NODE_PATH=$NVM_DIR/v$NODE_VERSION/lib/node_modules ENV PATH=$NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH -RUN gradle prepareDockerBuild --info --no-daemon - -FROM alpine:3.24.3 AS tomcat_base -RUN apk --no-cache upgrade && \ - apk --no-cache add \ - openjdk11-jre \ - curl \ - bash - - -RUN mkdir /download && \ - cd /download && \ - wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.121/bin/apache-tomcat-9.0.121.tar.gz && \ - echo "16494dd4745f808d3c506807b5275521fd71044d976f441d18eeeab0f5a38bc1b5344ca395292f6f26eb7612cd8c8e746d01ccdfb29893d394052d9f4b1f4c11 *apache-tomcat-9.0.121.tar.gz" > checksum.txt && \ - sha512sum -c checksum.txt && \ - tar xzf apache-tomcat-*tar.gz && \ - mv apache-tomcat-9.0.121 /usr/local/tomcat/ && \ - cd / && \ - rm -rf /usr/local/tomcat/webapps/* && \ - mkdir /usr/local/tomcat/webapps/ROOT && \ - printf "<%% response.sendRedirect(\"/cwms-data/\"); %%>\n" > /usr/local/tomcat/webapps/ROOT/index.jsp && \ - printf "User-agent: *\nAllow: /cwms-data/\nDisallow: /cwms-data/auth/\nDisallow: /cwms-data/catalog/\nDisallow: /cwms-data/timeseries/\nDisallow: /cwms-data/swagger-docs\nDisallow: /auth/\nSitemap: https://cwms-data.usace.army.mil/sitemap.xml\n" > /usr/local/tomcat/webapps/ROOT/robots.txt && \ - mkdir -p /usr/local/tomcat/conf/Catalina/localhost -# Now replace the Tomcat logging with logback -# NOTE: I have reviewed this jar in jd-gui and do not see anything malicious, packages are isolated to avoid issues -# with other code. -# Additionally, when we are not also accounting for some legacy systems, we will likely shift to -# Jetty, or Embedded Tomcat, to simplify the deployment process, making this subtitution unnecessary. -RUN cd /download && \ - wget https://repo1.maven.org/maven2/com/github/tomcat-slf4j-logback/tomcat9-slf4j-logback/9.0.120/tomcat9-slf4j-logback-9.0.120.jar && \ - echo "a24f49d57012472701172d8ec4509faa781a57a51e63b329441bdef80861e4550577fe703a333a7c5a6d5159ff14e96a16be631acef5df2ce14ec3c8cd6dae75 tomcat9-slf4j-logback-9.0.120.jar" > checksum.logback.txt && \ - sha512sum -c checksum.logback.txt -RUN cd /download && \ - cp tomcat9-slf4j-logback-9.0.120.jar /usr/local/tomcat/bin/tomcat-juli.jar && \ - rm /usr/local/tomcat/conf/logging.properties && \ - rm -rf /download -CMD ["/usr/local/tomcat/bin/catalina.sh","run"] - -FROM tomcat_base AS api +# Do this last no everything above can cache +COPY . /builddir/ +WORKDIR /builddir +RUN ./gradlew installDist -x test --info --no-daemon -COPY --from=builder /builddir/cda-gui/dist/sitemap.xml /usr/local/tomcat/webapps/ROOT/sitemap.xml -COPY --from=builder /builddir/cwms-data-api/build/docker/cda/ /usr/local/tomcat -COPY --from=builder /builddir/cwms-data-api/build/docker/context.xml /usr/local/tomcat/conf -COPY --from=builder /builddir/cwms-data-api/build/docker/server.xml /usr/local/tomcat/conf -COPY --from=builder /builddir/cwms-data-api/build/docker/setenv.sh /usr/local/tomcat/bin -COPY --from=builder /builddir/cwms-data-api/build/docker/libs/ /usr/local/tomcat/lib -COPY --from=builder /builddir/cwms-data-api/build/docker/logback.xml /logback.xml -COPY --from=builder /builddir/cwms-data-api/build/docker/logback-juli.xml /logback-juli.xml -COPY --from=builder /builddir/cwms-data-api/build/docker/app-context.xml /usr/local/tomcat/conf/Catalina/localhost/cwms-data.xml +FROM eclipse-temurin:17-jre-alpine-3.24 AS api +RUN apk del brotli-libs +RUN adduser -D cda +COPY --from=builder /builddir/cwms-data-api/build/install/cwms-data-api /cda +COPY --from=builder /builddir/cwms-data-api/src/docker/logback.xml /logback.xml ENV CDA_JDBC_DRIVER="oracle.jdbc.driver.OracleDriver" ENV CDA_JDBC_URL="" @@ -84,3 +43,5 @@ ENV TS_USE_DMZ_INCLUDE="true" # used to simplify redeploy in certain contexts. Update to match - in image label ENV IMAGE_MARKER="a" EXPOSE 7000 +USER cda +CMD ["/cda/bin/cwms-data-api", "/cwms-data", "/cda/wars/ui.war"] diff --git a/access-manager-api/build.gradle b/access-manager-api/build.gradle index 9408f500d..b569f2334 100644 --- a/access-manager-api/build.gradle +++ b/access-manager-api/build.gradle @@ -8,6 +8,7 @@ dependencies { exclude group: "org.eclipse.jetty" exclude group: "org.eclipse.jetty.websocket" } + compileOnly (libs.bundles.javalin.openapi) compileOnly(libs.swagger.core) { exclude group: "jakarta.xml.bind", module: "*" } diff --git a/access-manager-api/src/main/java/cwms/cda/spi/IdentityProvider.java b/access-manager-api/src/main/java/cwms/cda/spi/IdentityProvider.java index a878ba906..b20079767 100644 --- a/access-manager-api/src/main/java/cwms/cda/spi/IdentityProvider.java +++ b/access-manager-api/src/main/java/cwms/cda/spi/IdentityProvider.java @@ -1,7 +1,8 @@ package cwms.cda.spi; import io.javalin.http.Context; -import io.swagger.v3.oas.models.security.SecurityScheme; +//import io.swagger.v3.oas.models.security.SecurityScheme; +import io.javalin.openapi.SecurityScheme; import java.security.Principal; diff --git a/buildSrc/src/main/groovy/cda.deps-conventions.gradle b/buildSrc/src/main/groovy/cda.deps-conventions.gradle index 597546c99..252bd2ba0 100644 --- a/buildSrc/src/main/groovy/cda.deps-conventions.gradle +++ b/buildSrc/src/main/groovy/cda.deps-conventions.gradle @@ -13,9 +13,6 @@ repositories { excludeModule("javax.media", "jai_core") } - maven { - url = uri('https://repo.maven.apache.org/maven2') - } gradlePluginPortal() } diff --git a/buildSrc/src/main/groovy/cda.java-conventions.gradle b/buildSrc/src/main/groovy/cda.java-conventions.gradle index 8fe281bb1..cdb04a461 100644 --- a/buildSrc/src/main/groovy/cda.java-conventions.gradle +++ b/buildSrc/src/main/groovy/cda.java-conventions.gradle @@ -14,8 +14,8 @@ eclipse { tasks.withType(JavaCompile) { options.encoding = "UTF-8" - sourceCompatibility = '11' - targetCompatibility = '11' + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } test { diff --git a/cda-gui/.prettierignore b/cda-gui/.prettierignore index 233182a15..9d64b684f 100644 --- a/cda-gui/.prettierignore +++ b/cda-gui/.prettierignore @@ -1,3 +1,4 @@ dist storybook-static build +bin diff --git a/cda-gui/build.gradle b/cda-gui/build.gradle index 06e5fa023..288ec5a81 100644 --- a/cda-gui/build.gradle +++ b/cda-gui/build.gradle @@ -2,7 +2,10 @@ import com.github.gradle.node.npm.task.NpmTask import com.github.gradle.node.npm.task.NpxTask plugins { - id 'java' + id 'base' + id 'cda.deps-conventions' + id 'cda.java-conventions' + id 'war' id 'com.github.node-gradle.node' version '7.1.0' } @@ -20,6 +23,17 @@ def cdaGuiViteMode = providers.gradleProperty('cdaGuiMode') .orElse(providers.environmentVariable('CDA_GUI_MODE')) .orElse('production') +dependencies { + compileOnly(libs.javalin.core) // TO get the transitive web-api spec + testImplementation(libs.javalin.core) + testImplementation(libs.bundles.junit) + testImplementation(libs.mockito.core) +} + +configurations { + warOutput +} + task buildGuiVite(type:NpxTask) { dependsOn npmInstall command = "vite" @@ -62,16 +76,12 @@ task runGuiDev(type: Exec) { workingDir project.layout.projectDirectory } -sourceSets { - java { - main { - resources { - srcDir(project.layout.projectDirectory.dir('dist')) - } - } - } -} - -tasks.named('processResources') { +war { dependsOn buildGui + archiveBaseName = 'cwms-data-ui' + from(project.layout.projectDirectory.dir('dist')) } + +artifacts { + warOutput tasks.war +} \ No newline at end of file diff --git a/cda-gui/package-lock.json b/cda-gui/package-lock.json index 8683fb537..686df8fd9 100644 --- a/cda-gui/package-lock.json +++ b/cda-gui/package-lock.json @@ -452,9 +452,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -469,9 +469,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -486,9 +486,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -503,9 +503,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -520,9 +520,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -537,9 +537,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -554,9 +554,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -571,9 +571,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -588,9 +588,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -605,9 +605,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -622,9 +622,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -639,9 +639,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -656,9 +656,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -673,9 +673,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -690,9 +690,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -707,9 +707,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -724,9 +724,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -741,9 +741,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -758,9 +758,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -775,9 +775,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -792,9 +792,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -809,9 +809,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -826,9 +826,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -843,9 +843,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -860,9 +860,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -877,9 +877,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -1166,9 +1166,9 @@ } }, "node_modules/@joshwooding/vite-plugin-react-docgen-typescript/node_modules/brace-expansion": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", - "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", + "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", "dev": true, "license": "MIT", "dependencies": { @@ -1693,9 +1693,9 @@ } }, "node_modules/@oxc-resolver/binding-android-arm-eabi": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.24.2.tgz", - "integrity": "sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm-eabi/-/binding-android-arm-eabi-11.21.2.tgz", + "integrity": "sha512-xQoCRv+gKax9KTdwdaQNnAFOai8neay7g3jExDIORzhbrejwGSJaZNTdOJHR5ziLg2joMxOCMOFMo4zuxza2uQ==", "cpu": [ "arm" ], @@ -1707,9 +1707,9 @@ ] }, "node_modules/@oxc-resolver/binding-android-arm64": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.24.2.tgz", - "integrity": "sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-android-arm64/-/binding-android-arm64-11.21.2.tgz", + "integrity": "sha512-HF5oiE2L05yInPYCFD/4uxSrEZW4SuIfn99Y6L1xnJnzl066JR+MJs2rIdstw8A2MPlAKH+13dpFPNycjqzvGg==", "cpu": [ "arm64" ], @@ -1721,9 +1721,9 @@ ] }, "node_modules/@oxc-resolver/binding-darwin-arm64": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.24.2.tgz", - "integrity": "sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-arm64/-/binding-darwin-arm64-11.21.2.tgz", + "integrity": "sha512-UX4u49CVCAD8QZNELaW8eMGgMAGwFWYEPbvNsh+3r/gs4NX3KfpiACMVwRQT0EuH3uat9hM5Zl+Ppm9pJD8tgg==", "cpu": [ "arm64" ], @@ -1735,9 +1735,9 @@ ] }, "node_modules/@oxc-resolver/binding-darwin-x64": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.24.2.tgz", - "integrity": "sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-darwin-x64/-/binding-darwin-x64-11.21.2.tgz", + "integrity": "sha512-J9xPx7YBkrRmJ+xl561ztnMWEc1aOyjEIxBiGX1dVb3u7bGSnfObfcZk+Pd+uM0HZAPNsQ1xvD8j52A/uOSqNQ==", "cpu": [ "x64" ], @@ -1749,9 +1749,9 @@ ] }, "node_modules/@oxc-resolver/binding-freebsd-x64": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.24.2.tgz", - "integrity": "sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-freebsd-x64/-/binding-freebsd-x64-11.21.2.tgz", + "integrity": "sha512-fRlt7OvSaQkWj6+EDTVxawVxOlqJB2QSnBfkeCyK4RTvsGctbw3BiH2Tb7DzMs7bikc4BRBpvWP5zF9K8b54Zg==", "cpu": [ "x64" ], @@ -1763,9 +1763,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm-gnueabihf": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.24.2.tgz", - "integrity": "sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-11.21.2.tgz", + "integrity": "sha512-gK+vPUcPQITkGwBKpZGrcDHSlU6eDGl7AQacxS2CEKAZIBHWkOVFeJwLZ4tYnA1acJqRM5lt7yYwPCVqGHIJ7A==", "cpu": [ "arm" ], @@ -1777,9 +1777,9 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm-musleabihf": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.24.2.tgz", - "integrity": "sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-11.21.2.tgz", + "integrity": "sha512-L/Rgas7SrOKy/z7IH+HxSFRqVO4PuLDKLEGKvnhoCBBq3UJ0YzGBou3qMzaAGgkJwsIvX2pBF+7ojzfUhLiZxQ==", "cpu": [ "arm" ], @@ -1791,13 +1791,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm64-gnu": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.24.2.tgz", - "integrity": "sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-11.21.2.tgz", + "integrity": "sha512-CUEYvlX1Fk7E9kUMzuswru1J9HLxMwnpDeQGjQuI4ZH+iNCoa2X9T+pvyzrbsgl7WnIeTFTlNlHsRfVdf5g9/g==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1805,13 +1808,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-arm64-musl": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.24.2.tgz", - "integrity": "sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-arm64-musl/-/binding-linux-arm64-musl-11.21.2.tgz", + "integrity": "sha512-ViN1ZibQyxwC67GpoP33oo+S9UyUnkog13vzQb9+v9bCNvrVzJuk0MRdacjtv/9xfRMVF/eqHFyl8YOeykI10Q==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1819,13 +1825,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-ppc64-gnu": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.24.2.tgz", - "integrity": "sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-11.21.2.tgz", + "integrity": "sha512-CU1sCqWnhGqYD5I1HedHk5pujrn7ssDkNB/AEQd/pd3D/EojVSgJUlpbafwIbyhia3PgIfkvdFpRPWSALzVumA==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1833,13 +1842,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-riscv64-gnu": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.24.2.tgz", - "integrity": "sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-11.21.2.tgz", + "integrity": "sha512-jWVyZtIHca4Gb96x7dag+y69vlei7ffjrsveLkmf2ZhqEAz6ZSBnY1GWvgZUaZlwZP62A3xD092BW97Q5VGc+g==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1847,13 +1859,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-riscv64-musl": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.24.2.tgz", - "integrity": "sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-11.21.2.tgz", + "integrity": "sha512-LF29obFqNgBUgDX7rmUK7M4D0JQG5LxhYzn3xXmECcHU9aQAdWG7NiY052qybtesEdwHQXKNTWYQ7mTsybNvWg==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1861,13 +1876,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-s390x-gnu": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.24.2.tgz", - "integrity": "sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-11.21.2.tgz", + "integrity": "sha512-+NYcm+cCHBbtdQQ3A4phQTSuVRYnNHz7wrl9XRAPEovcdoqi0mb1K5ZOl+jN54ZD+q1zz3V0vltbFJmzecJKmw==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1875,13 +1893,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-x64-gnu": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.24.2.tgz", - "integrity": "sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-gnu/-/binding-linux-x64-gnu-11.21.2.tgz", + "integrity": "sha512-UQqZDdG2r2HhAOsZEgufkIWHPQ886IUyuJQkoZByvzhW8j51R4UNzGBJFkTiTnLhQnggwJRdJgFWK4uY6ZVIMw==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1889,13 +1910,16 @@ ] }, "node_modules/@oxc-resolver/binding-linux-x64-musl": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.24.2.tgz", - "integrity": "sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-linux-x64-musl/-/binding-linux-x64-musl-11.21.2.tgz", + "integrity": "sha512-3Q9PMRjalWkT6NZ4jfujuqTCFwoWErg3y3BnOgb544B8IMw4PktiwWOigMfOHNRLMghZeJ7hpfpZf4CP7rV7Og==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1903,9 +1927,9 @@ ] }, "node_modules/@oxc-resolver/binding-openharmony-arm64": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.24.2.tgz", - "integrity": "sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-openharmony-arm64/-/binding-openharmony-arm64-11.21.2.tgz", + "integrity": "sha512-Eljeq3ndtyKhM+Es8LITi4Zl2htzuRZcrPMF3kMCsrILztvU6AjZ3FuEhHHKobPUB9rMpzLpJP5bDqXI7r+iog==", "cpu": [ "arm64" ], @@ -1917,9 +1941,9 @@ ] }, "node_modules/@oxc-resolver/binding-wasm32-wasi": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.24.2.tgz", - "integrity": "sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-wasm32-wasi/-/binding-wasm32-wasi-11.21.2.tgz", + "integrity": "sha512-HGDbNsIywqc4LxU38+CTJNnB/6BF7rheWOJ259b4eE0aEnelYblC8x+1tEd63bp31fYne63RQz9Jb4yVnC7Yig==", "cpu": [ "wasm32" ], @@ -1927,18 +1951,18 @@ "license": "MIT", "optional": true, "dependencies": { - "@emnapi/core": "1.11.2", - "@emnapi/runtime": "1.11.2", - "@napi-rs/wasm-runtime": "^1.1.6" + "@emnapi/core": "1.11.0", + "@emnapi/runtime": "1.11.0", + "@napi-rs/wasm-runtime": "^1.1.5" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@oxc-resolver/binding-wasm32-wasi/node_modules/@emnapi/core": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.2.tgz", - "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.0.tgz", + "integrity": "sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==", "dev": true, "license": "MIT", "optional": true, @@ -1948,9 +1972,9 @@ } }, "node_modules/@oxc-resolver/binding-wasm32-wasi/node_modules/@emnapi/runtime": { - "version": "1.11.2", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", - "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.0.tgz", + "integrity": "sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==", "dev": true, "license": "MIT", "optional": true, @@ -1970,9 +1994,9 @@ } }, "node_modules/@oxc-resolver/binding-win32-arm64-msvc": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.24.2.tgz", - "integrity": "sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-11.21.2.tgz", + "integrity": "sha512-iWx25CBEgH49iE9q5coEGI/jb1jl5kkCY9z6U5Og67xCkQ/WFMDc2J5U78+AE91SUxM2NqSLhJC8/PLfWnImww==", "cpu": [ "arm64" ], @@ -1984,9 +2008,9 @@ ] }, "node_modules/@oxc-resolver/binding-win32-x64-msvc": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.24.2.tgz", - "integrity": "sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/@oxc-resolver/binding-win32-x64-msvc/-/binding-win32-x64-msvc-11.21.2.tgz", + "integrity": "sha512-VPoCAhKvCQTlG7vxqaBXcmuvbh77BfnGXj8g0pbvVXpm1F/R8rDVwqIWcEbMzrI1JvJlm8v7T9uMVQb6UctMRg==", "cpu": [ "x64" ], @@ -2506,9 +2530,9 @@ } }, "node_modules/@storybook/addon-vitest": { - "version": "10.5.7", - "resolved": "https://registry.npmjs.org/@storybook/addon-vitest/-/addon-vitest-10.5.7.tgz", - "integrity": "sha512-7NK7Kzazc2vb2h8nGlH15QlUn5J6/LV0xF70VziAK0bxu3r1JupLCoBvckX39vHzFXiAZljXZtt1Wq/OidBxow==", + "version": "10.6.5", + "resolved": "https://registry.npmjs.org/@storybook/addon-vitest/-/addon-vitest-10.6.5.tgz", + "integrity": "sha512-0N0E7TQgmdrPNCPqNiVdTWOEQ1Nes+YsUphYX/abzlp6ReOyYBoQJw6mZ0b7BN5ACgdXQsr9Tth161t72k+51Q==", "dev": true, "license": "MIT", "dependencies": { @@ -2520,11 +2544,10 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@vitest/browser": "^3.0.0 || ^4.0.0", - "@vitest/browser-playwright": "^4.0.0", - "@vitest/runner": "^3.0.0 || ^4.0.0", - "storybook": "^10.5.7", - "vitest": "^3.0.0 || ^4.0.0" + "@vitest/browser": "^4.0.0 || ^5.0.0", + "@vitest/browser-playwright": "^4.0.0 || ^5.0.0", + "storybook": "^10.6.5", + "vitest": "^4.0.0 || ^5.0.0" }, "peerDependenciesMeta": { "@vitest/browser": { @@ -2533,9 +2556,6 @@ "@vitest/browser-playwright": { "optional": true }, - "@vitest/runner": { - "optional": true - }, "vitest": { "optional": true } @@ -2967,18 +2987,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/node": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.1.tgz", - "integrity": "sha512-VqGJBMCtdhqkBUCcBLvywI0NJ+KLuVzgNnlBUNFOQjqVxzo2lxLUNg1DSey8+u2u6ktswSAxg+s68QLzWHNOuA==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "undici-types": "~8.9.0" - } - }, "node_modules/@types/prop-types": { "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", @@ -3388,13 +3396,13 @@ "license": "ISC" }, "node_modules/@usace-watermanagement/groundwork-water": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@usace-watermanagement/groundwork-water/-/groundwork-water-4.2.0.tgz", - "integrity": "sha512-IqUFEBTku4p24pS2ERDbZzEJ+zqq3MrhJjJWv5velW/aa3i4dKpUIk2jCu9Nq/eiXZ+7b6ndyRkWcstsfTZUXQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@usace-watermanagement/groundwork-water/-/groundwork-water-4.3.0.tgz", + "integrity": "sha512-rF3DUtJAaOeULd9+RHf871Mi1ooGOstXrGXP18BFuSCKu8VGadeZlL/QQScQXAyKFmN8ZTy+AMSXIbqqDmhT3g==", "license": "MIT", "dependencies": { "@tanstack/react-virtual": "^3.14.6", - "cwmsjs": "^2.3.0-2024.12.10", + "cwmsjs": "^2.4.0-2026.3.16", "d3": "^7.9.0", "dayjs": "^1.11.11", "deepmerge": "^4.3.1", @@ -3414,9 +3422,9 @@ } }, "node_modules/@usace-watermanagement/groundwork-water/node_modules/cwmsjs": { - "version": "2.3.0-2024.12.10", - "resolved": "https://registry.npmjs.org/cwmsjs/-/cwmsjs-2.3.0-2024.12.10.tgz", - "integrity": "sha512-5uPKl24caND+JR0C/3LLQ9cXmHy/lW4//PB+bykQ2kCKGvKOu8sdmeOaP3NbMGyHdsc6kGWJplZKmcsJEp0tBA==" + "version": "2.4.0-2026.3.16", + "resolved": "https://registry.npmjs.org/cwmsjs/-/cwmsjs-2.4.0-2026.3.16.tgz", + "integrity": "sha512-V4Qv7DDPrPyd9OD5fn/qvOCjXtaje8qEMjZBgEo/8iQQCTRy682taepfcF1N6ZrNfb/abiXMeLdqvpxB6OqIXQ==" }, "node_modules/@usace/groundwork": { "version": "3.15.6", @@ -4185,9 +4193,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.10.38", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz", - "integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==", + "version": "2.11.33", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.33.tgz", + "integrity": "sha512-yiVKDX+qCMRKBE084lXvq9EcwFUhKZ2nU8TK1EQQuOgPNR/lmbGxXOeDdlGUqC2Zz11Cs9rk1d/8NfgBmlkt0w==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4249,9 +4257,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -4271,9 +4279,9 @@ } }, "node_modules/browserslist": { - "version": "4.28.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz", - "integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==", + "version": "4.29.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.5.tgz", + "integrity": "sha512-khTmKu5NGYTotqcYo8Bew2k4RAE9PuXRSFRXG2lQBrCEQHyeQ/vX6gKMxfokwywBsLiXZMnHsmWMG1pnO8J7uQ==", "dev": true, "funding": [ { @@ -4291,11 +4299,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.10.38", - "caniuse-lite": "^1.0.30001799", - "electron-to-chromium": "^1.5.376", - "node-releases": "^2.0.48", - "update-browserslist-db": "^1.2.3" + "baseline-browser-mapping": "^2.11.33", + "caniuse-lite": "^1.0.30001819", + "electron-to-chromium": "^1.5.464", + "node-releases": "^2.0.60", + "update-browserslist-db": "^1.3.4" }, "bin": { "browserslist": "cli.js" @@ -4440,9 +4448,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001799", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz", - "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==", + "version": "1.0.30001819", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001819.tgz", + "integrity": "sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==", "dev": true, "funding": [ { @@ -5484,9 +5492,9 @@ "license": "ISC" }, "node_modules/electron-to-chromium": { - "version": "1.5.377", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.377.tgz", - "integrity": "sha512-cH1jZgJHoezfTnKfKwnScpHywTFVnJUNITDPREFdhNjiuD502+QFpG0Qk7G8jhsV/f+CEAFlIrzP1fT+IMb92g==", + "version": "1.5.466", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.466.tgz", + "integrity": "sha512-WkgFvScwZjvCPupYGfQr5qlKCv/Tu+GYELGMCGcoBOQbNb6nx/TqGwJyLMwcNAAy2kKJF2agjM7KZKest538JA==", "dev": true, "license": "ISC" }, @@ -5734,9 +5742,9 @@ } }, "node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -5747,32 +5755,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escalade": { @@ -7355,9 +7363,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, "funding": [ { @@ -8054,9 +8062,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.15", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", - "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "version": "3.3.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz", + "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==", "funding": [ { "type": "github", @@ -8098,9 +8106,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.48", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz", - "integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==", + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.60.tgz", + "integrity": "sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==", "dev": true, "license": "MIT", "engines": { @@ -8404,34 +8412,34 @@ } }, "node_modules/oxc-resolver": { - "version": "11.24.2", - "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.24.2.tgz", - "integrity": "sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==", + "version": "11.21.2", + "resolved": "https://registry.npmjs.org/oxc-resolver/-/oxc-resolver-11.21.2.tgz", + "integrity": "sha512-w5tLwYN3Zo24w5EeWJjJWZOwhYqTtC8PS2B1tIt7BZUuqTIcU07sQValbDw+rq7+AuAGzOHklgK+ifsy4lpXfw==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/Boshen" }, "optionalDependencies": { - "@oxc-resolver/binding-android-arm-eabi": "11.24.2", - "@oxc-resolver/binding-android-arm64": "11.24.2", - "@oxc-resolver/binding-darwin-arm64": "11.24.2", - "@oxc-resolver/binding-darwin-x64": "11.24.2", - "@oxc-resolver/binding-freebsd-x64": "11.24.2", - "@oxc-resolver/binding-linux-arm-gnueabihf": "11.24.2", - "@oxc-resolver/binding-linux-arm-musleabihf": "11.24.2", - "@oxc-resolver/binding-linux-arm64-gnu": "11.24.2", - "@oxc-resolver/binding-linux-arm64-musl": "11.24.2", - "@oxc-resolver/binding-linux-ppc64-gnu": "11.24.2", - "@oxc-resolver/binding-linux-riscv64-gnu": "11.24.2", - "@oxc-resolver/binding-linux-riscv64-musl": "11.24.2", - "@oxc-resolver/binding-linux-s390x-gnu": "11.24.2", - "@oxc-resolver/binding-linux-x64-gnu": "11.24.2", - "@oxc-resolver/binding-linux-x64-musl": "11.24.2", - "@oxc-resolver/binding-openharmony-arm64": "11.24.2", - "@oxc-resolver/binding-wasm32-wasi": "11.24.2", - "@oxc-resolver/binding-win32-arm64-msvc": "11.24.2", - "@oxc-resolver/binding-win32-x64-msvc": "11.24.2" + "@oxc-resolver/binding-android-arm-eabi": "11.21.2", + "@oxc-resolver/binding-android-arm64": "11.21.2", + "@oxc-resolver/binding-darwin-arm64": "11.21.2", + "@oxc-resolver/binding-darwin-x64": "11.21.2", + "@oxc-resolver/binding-freebsd-x64": "11.21.2", + "@oxc-resolver/binding-linux-arm-gnueabihf": "11.21.2", + "@oxc-resolver/binding-linux-arm-musleabihf": "11.21.2", + "@oxc-resolver/binding-linux-arm64-gnu": "11.21.2", + "@oxc-resolver/binding-linux-arm64-musl": "11.21.2", + "@oxc-resolver/binding-linux-ppc64-gnu": "11.21.2", + "@oxc-resolver/binding-linux-riscv64-gnu": "11.21.2", + "@oxc-resolver/binding-linux-riscv64-musl": "11.21.2", + "@oxc-resolver/binding-linux-s390x-gnu": "11.21.2", + "@oxc-resolver/binding-linux-x64-gnu": "11.21.2", + "@oxc-resolver/binding-linux-x64-musl": "11.21.2", + "@oxc-resolver/binding-openharmony-arm64": "11.21.2", + "@oxc-resolver/binding-wasm32-wasi": "11.21.2", + "@oxc-resolver/binding-win32-arm64-msvc": "11.21.2", + "@oxc-resolver/binding-win32-x64-msvc": "11.21.2" } }, "node_modules/p-limit": { @@ -8702,9 +8710,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.32.tgz", + "integrity": "sha512-LJlKCCAUFKOuZxipUdYw1NzIITEsPcgyOG9LkvRJvuKj/bRzbuRY0ARXvL0pWGpsZvn8jku+LMep2eU0seHp8g==", "funding": [ { "type": "opencollective", @@ -8721,9 +8729,9 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.20", "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" + "source-map-js": "^1.2.2" }, "engines": { "node": "^10 || ^12 || >=14" @@ -8860,9 +8868,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", - "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.5.tgz", + "integrity": "sha512-TEHFzb5KRDKaOgJ4TYE+0jyJtFbjLvkdVOu0fZ2b6MTWzoqZd4Le+61aEppWkvTlYePgOX4ATL1wsAIPMLTw6Q==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -9147,9 +9155,9 @@ } }, "node_modules/react-router": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.0.tgz", - "integrity": "sha512-pTTGt8J+ji1NOmYnjzT+bAJy/1zD+Jp4ziO6cL7T3ZLvXKtusO7BpFqlRXitqpcPVqllsIXFHRMt+2/k3Xn6HQ==", + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.4.tgz", + "integrity": "sha512-PUPQcMhMGRAslLcvtlPz/kmzBEWPhLdgLFrL7pLNepBL6dX0lWj4WD2cUYVgYCuT3jxvghYFg81cDTj44DhetQ==", "license": "MIT", "dependencies": { "cookie": "^1.0.1", @@ -9169,12 +9177,12 @@ } }, "node_modules/react-router-dom": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.0.tgz", - "integrity": "sha512-Fi0yY6kgtKae/Th2xibdWK0KSdYZ4B53Gyf6wRtomOKWgpNm7H7+DyfDhncdz9FKbpS+1jmDhg3F4WoGJ+yFOA==", + "version": "7.18.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.4.tgz", + "integrity": "sha512-yrfmJHIpDG7taCpqKjT1G5B6q3O2K+RN8/fgNf0lTjCwiPbQ0ei6vXX9ZjQR+7ld8Tr7Z5xmyMnZ8YJrphWQUw==", "license": "MIT", "dependencies": { - "react-router": "7.18.0" + "react-router": "7.18.4" }, "engines": { "node": ">=20.0.0" @@ -9711,9 +9719,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.3.tgz", + "integrity": "sha512-irZHtTqurLna57KQG/s+fzOwv/J6XSH4cs8M/vsrY3uCaQ3S6+QJguAH0WdN47SXlk82voMZ4naWMQf8fdEoIg==", "license": "MIT" }, "node_modules/set-function-length": { @@ -9946,9 +9954,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -9983,9 +9991,9 @@ } }, "node_modules/storybook": { - "version": "10.5.7", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.5.7.tgz", - "integrity": "sha512-oiKvWIwIoOhFP1i6dASYyMXwPHKEtVZMshqSB7EvIVYjWRh0l9H7gHEt1z4Gh2rLGFMekWdsm4s94rvwpR7gkg==", + "version": "10.6.5", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-10.6.5.tgz", + "integrity": "sha512-qurC38Nx4PDF9YIq6GO95dpUx8a3B9AZwlcHBo4cOI9At09ifjQRsqcwcdOf2YX0cpVhFKmHkI20SWCrxqYQrg==", "dev": true, "license": "MIT", "dependencies": { @@ -9993,7 +10001,7 @@ "@storybook/icons": "^2.0.2", "@testing-library/dom": "^10.4.1", "@testing-library/jest-dom": "6.9.1", - "@testing-library/user-event": "^14.6.1", + "@testing-library/user-event": "^14.6.3", "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "@webcontainer/env": "^1.1.1", @@ -10001,7 +10009,7 @@ "jsonc-parser": "^3.3.1", "open": "^10.2.0", "oxc-parser": "^0.127.0", - "oxc-resolver": "^11.19.1", + "oxc-resolver": "11.21.2", "recast": "^0.23.5", "semver": "^7.7.3", "use-sync-external-store": "^1.5.0", @@ -10739,15 +10747,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "8.9.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz", - "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true - }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -10838,9 +10837,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.4.tgz", + "integrity": "sha512-t8wonIOdQyOjtPd2VktlBu6QjTVTks6v8bSi7kd0r2Vll8TK1JYDZtRRdbmCHOAMphkZgrzK+L+vXK4pyZ8t4A==", "dev": true, "funding": [ { @@ -10916,13 +10915,13 @@ } }, "node_modules/vite": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz", - "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==", + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.7.tgz", + "integrity": "sha512-AHEzTORMbi7/7aXp7w7KZ5+DCUdSeLsJz0grY8xHpc9DHdYb0vQu6DqJfm2tOw3gDExNgPgnJTXxM6syYFHaCA==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.27.0", + "esbuild": "^0.27.0 || ^0.28.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", diff --git a/cda-gui/playwright.api-keys.config.js b/cda-gui/playwright.api-keys.config.js index 175cc8cb8..00293c94b 100644 --- a/cda-gui/playwright.api-keys.config.js +++ b/cda-gui/playwright.api-keys.config.js @@ -7,7 +7,7 @@ export default defineConfig({ webServer: { command: "npx vite --mode dev-cda-compose --host 127.0.0.1 --port 5178 --strictPort", - url: "http://127.0.0.1:5178/cwms-data/", + url: "http://127.0.0.1:5178", timeout: 120000, env: { VITE_CDA_API_ROOT: "/cwms-data", diff --git a/cda-gui/playwright.auth.config.js b/cda-gui/playwright.auth.config.js index f9cc0b71c..afb44e1ac 100644 --- a/cda-gui/playwright.auth.config.js +++ b/cda-gui/playwright.auth.config.js @@ -5,6 +5,6 @@ export default defineConfig({ use: { baseURL: "http://127.0.0.1:18741", headless: true }, webServer: { command: "npx vite --mode test --host 127.0.0.1 --port 18741 --strictPort", - url: "http://127.0.0.1:18741/cwms-data/", + url: "http://127.0.0.1:18741/", }, }); diff --git a/cda-gui/playwright.data-query.config.js b/cda-gui/playwright.data-query.config.js index 2c6e6feca..a8640e773 100644 --- a/cda-gui/playwright.data-query.config.js +++ b/cda-gui/playwright.data-query.config.js @@ -7,7 +7,7 @@ export default defineConfig({ webServer: { command: "npx vite --mode dev-cda-compose --host 127.0.0.1 --port 5184 --strictPort", - url: "http://127.0.0.1:5184/cwms-data/", + url: "http://127.0.0.1:5184", timeout: 120000, env: { VITE_CDA_API_ROOT: "/cwms-data" }, }, diff --git a/cda-gui/playwright.user-roles.config.js b/cda-gui/playwright.user-roles.config.js index 7fc4bbaa0..16af7a697 100644 --- a/cda-gui/playwright.user-roles.config.js +++ b/cda-gui/playwright.user-roles.config.js @@ -6,7 +6,8 @@ export default defineConfig({ workers: 1, webServer: { command: "npm run dev:onboarding", - url: "http://127.0.0.1:18742/cwms-data/", - reuseExistingServer: true, + url: "http://127.0.0.1:18742", + //reuseExistingServer: true, + env: { VITE_CDA_API_ROOT: "/cwms-data" }, }, }); diff --git a/cda-gui/public/robots.txt b/cda-gui/public/robots.txt new file mode 100644 index 000000000..b78d0b4ae --- /dev/null +++ b/cda-gui/public/robots.txt @@ -0,0 +1,8 @@ +User-agent: * +Allow: / +Disallow: /auth/ +Disallow: /cwms-data/auth/ +Disallow: /cwms-data/catalog/ +Disallow: /cwms-data/timeseries/ +Disallow: /cwms-data/swagger-docs +Sitemap: https://cwms-data.usace.army.mil/sitemap.xml \ No newline at end of file diff --git a/cda-gui/scripts/generate-sitemap.mjs b/cda-gui/scripts/generate-sitemap.mjs index a1e09a708..a8bfc122a 100644 --- a/cda-gui/scripts/generate-sitemap.mjs +++ b/cda-gui/scripts/generate-sitemap.mjs @@ -12,7 +12,7 @@ const outputPath = path.join(projectDir, "dist", "sitemap.xml"); const siteOrigin = ( process.env.SITE_ORIGIN ?? "https://cwms-data.usace.army.mil" ).replace(/\/+$/, ""); -const siteBasePath = (process.env.SITE_BASE_PATH ?? "/cwms-data").replace(/\/+$/, ""); +const siteBasePath = (process.env.SITE_BASE_PATH ?? "").replace(/\/+$/, ""); const urls = sitemapPaths.map((routePath) => { const normalizedPath = routePath ? `/${routePath}` : ""; diff --git a/cda-gui/src/components/GlobalErrorBoundary.jsx b/cda-gui/src/components/GlobalErrorBoundary.jsx index cf8398bbc..a399bbfc7 100644 --- a/cda-gui/src/components/GlobalErrorBoundary.jsx +++ b/cda-gui/src/components/GlobalErrorBoundary.jsx @@ -23,7 +23,7 @@ export default class GlobalErrorBoundary extends Component {

{this.state.error?.message ?? "An unexpected error occurred."}

- + Return to CDA diff --git a/cda-gui/src/links/header-links.js b/cda-gui/src/links/header-links.js index 4bd053313..2f1773a35 100644 --- a/cda-gui/src/links/header-links.js +++ b/cda-gui/src/links/header-links.js @@ -1,3 +1,5 @@ +import { getBasePath } from "../utils/base"; + export default [ { id: "home", @@ -17,7 +19,7 @@ export default [ { id: "swagger-schema", text: "Swagger Docs Schema", - href: "/swagger-docs", + href: `${getBasePath()}/swagger-docs`, }, ], }, diff --git a/cda-gui/src/main.jsx b/cda-gui/src/main.jsx index 0badef7fd..527a9c2e1 100644 --- a/cda-gui/src/main.jsx +++ b/cda-gui/src/main.jsx @@ -66,7 +66,7 @@ const router = createBrowserRouter( ], }, ], - { basename: "/cwms-data" }, + { basename: "/" }, ); ReactDOM.createRoot(document.getElementById("root")).render( diff --git a/cwms-data-api/src/main/java/cwms/cda/servlet/SpaErrorStatusFilter.java b/cda-gui/src/main/java/cwms/cda/ui/SpaErrorStatusFilter.java similarity index 84% rename from cwms-data-api/src/main/java/cwms/cda/servlet/SpaErrorStatusFilter.java rename to cda-gui/src/main/java/cwms/cda/ui/SpaErrorStatusFilter.java index 5d575e4d2..ecfd8827c 100644 --- a/cwms-data-api/src/main/java/cwms/cda/servlet/SpaErrorStatusFilter.java +++ b/cda-gui/src/main/java/cwms/cda/ui/SpaErrorStatusFilter.java @@ -1,17 +1,17 @@ -package cwms.cda.servlet; +package cwms.cda.ui; import java.io.IOException; import java.util.Set; -import javax.servlet.DispatcherType; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * Converts the error dispatch used to load known client-side routes into a successful response. diff --git a/cwms-data-api/src/test/java/cwms/cda/servlet/SpaErrorStatusFilterTest.java b/cda-gui/src/main/test/java/cwms/cda/ui/SpaErrorStatusFilterTest.java similarity index 85% rename from cwms-data-api/src/test/java/cwms/cda/servlet/SpaErrorStatusFilterTest.java rename to cda-gui/src/main/test/java/cwms/cda/ui/SpaErrorStatusFilterTest.java index 0b40f1a7c..5c1d5f8e3 100644 --- a/cwms-data-api/src/test/java/cwms/cda/servlet/SpaErrorStatusFilterTest.java +++ b/cda-gui/src/main/test/java/cwms/cda/ui/SpaErrorStatusFilterTest.java @@ -1,4 +1,4 @@ -package cwms.cda.servlet; +package cwms.cda.ui; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.mockito.Mockito.mock; @@ -7,13 +7,13 @@ import static org.mockito.Mockito.when; import java.io.IOException; -import javax.servlet.DispatcherType; -import javax.servlet.FilterChain; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.FilterChain; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -51,7 +51,7 @@ void registersForIndexErrorDispatches() { "/user-roles/mvsc/" }) void returnsOkForClientRoutes(String route) throws ServletException, IOException { - HttpServletRequest request = buildRequest("GET", "/cwms-data" + route); + HttpServletRequest request = buildRequest("GET", route); HttpServletResponse response = mock(HttpServletResponse.class); FilterChain chain = mock(FilterChain.class); @@ -63,7 +63,7 @@ void returnsOkForClientRoutes(String route) throws ServletException, IOException @Test void returnsOkForHeadRequest() throws ServletException, IOException { - HttpServletRequest request = buildRequest("HEAD", "/cwms-data/swagger-ui"); + HttpServletRequest request = buildRequest("HEAD", "/swagger-ui"); HttpServletResponse response = mock(HttpServletResponse.class); FilterChain chain = mock(FilterChain.class); @@ -75,7 +75,7 @@ void returnsOkForHeadRequest() throws ServletException, IOException { @Test void returnsOkForAlternateContextPath() throws ServletException, IOException { - HttpServletRequest request = buildRequest("GET", "/spk-data/swagger-ui", "/spk-data"); + HttpServletRequest request = buildRequest("GET", "/cwms-data-ui/swagger-ui", "/cwms-data"); HttpServletResponse response = mock(HttpServletResponse.class); FilterChain chain = mock(FilterChain.class); @@ -87,7 +87,7 @@ void returnsOkForAlternateContextPath() throws ServletException, IOException { @Test void preservesNotFoundStatusForUnknownRoutes() throws ServletException, IOException { - HttpServletRequest request = buildRequest("GET", "/cwms-data/not-a-client-route"); + HttpServletRequest request = buildRequest("GET", "not-a-client-route"); HttpServletResponse response = mock(HttpServletResponse.class); FilterChain chain = mock(FilterChain.class); @@ -99,7 +99,7 @@ void preservesNotFoundStatusForUnknownRoutes() throws ServletException, IOExcept @Test void preservesNotFoundStatusForNonPageRequests() throws ServletException, IOException { - HttpServletRequest request = buildRequest("POST", "/cwms-data/swagger-ui"); + HttpServletRequest request = buildRequest("POST", "/swagger-ui"); HttpServletResponse response = mock(HttpServletResponse.class); FilterChain chain = mock(FilterChain.class); diff --git a/cda-gui/src/main/webapp/WEB-INF/web.xml b/cda-gui/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..7b2a86eb0 --- /dev/null +++ b/cda-gui/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,13 @@ + + CWMS Data API UI + + + index.html + + + + + 404 + /index.html + + \ No newline at end of file diff --git a/cda-gui/src/pages/decide/index.jsx b/cda-gui/src/pages/decide/index.jsx deleted file mode 100644 index c78aa3b56..000000000 --- a/cda-gui/src/pages/decide/index.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useEffect } from "react"; - -function Decide() { - useEffect(() => { - document.title = "CWMS Public Services"; - }); - return ( -
-

- Hello, you've successfully reach the Corps Water Management System (CWMS) - public data system. Multiple sites are available please follow one of the links - below for access to our data: -

- -
- ); -} - -export default Decide; diff --git a/cda-gui/src/utils/base.js b/cda-gui/src/utils/base.js index 2386fa954..c42e09543 100644 --- a/cda-gui/src/utils/base.js +++ b/cda-gui/src/utils/base.js @@ -1,8 +1,7 @@ // base.js export function getBasePath() { - const { pathname } = window.location; - const basePath = "/" + pathname.split("/")[1]; - return basePath; + const configuredRoot = import.meta.env.VITE_CDA_API_ROOT || "/cwms-data"; + return new URL(configuredRoot, window.location.origin).pathname.replace(/\/$/, ""); } export function getOrigin() { diff --git a/cda-gui/tests/auth/cwms-login.spec.js b/cda-gui/tests/auth/cwms-login.spec.js index 29bcfd17a..b1caf6b7f 100644 --- a/cda-gui/tests/auth/cwms-login.spec.js +++ b/cda-gui/tests/auth/cwms-login.spec.js @@ -10,7 +10,7 @@ async function mockDeployment(page, schemes = { CwmsAAACacAuth: cwmsScheme }) { await page.route("**/swagger-docs", (route) => route.fulfill({ json: { - openapi: "3.0.3", + openapi: "3.1.0", info: { title: "CWMS authentication test", version: "1" }, paths: {}, components: { securitySchemes: schemes }, @@ -46,7 +46,7 @@ async function mockDeployment(page, schemes = { CwmsAAACacAuth: cwmsScheme }) { test("header CWMS login and logout return to the current page", async ({ page }) => { await mockDeployment(page); - await page.goto("/cwms-data/regexp/?office=SWT#login"); + await page.goto("/regexp/?office=SWT#login"); const originalLocation = page.url(); const loginRequest = page.waitForRequest("**/CWMSLogin/login?*"); @@ -71,18 +71,18 @@ test("header CWMS login and logout return to the current page", async ({ page }) test("Swagger CWMS login also establishes the header session", async ({ page }) => { await mockDeployment(page); - await page.goto("/cwms-data/swagger-ui"); + await page.goto("/swagger-ui"); await page.getByRole("button", { name: "Sign in", exact: true }).click(); await expect( - page.getByRole("button", { name: "Log out", exact: true }), + page.getByRole("button", { name: "Sign out", exact: true }), ).toBeVisible(); - await expect(page).toHaveURL(/\/cwms-data\/swagger-ui$/); + await expect(page).toHaveURL(/\/swagger-ui$/); }); test("unsupported authentication still reports sign-in unavailable", async ({ page, }) => { await mockDeployment(page, {}); - await page.goto("/cwms-data/"); + await page.goto("/"); await expect(page.getByText("Sign-in unavailable", { exact: true })).toBeVisible(); }); diff --git a/cda-gui/tests/auth/token-refresh.spec.js b/cda-gui/tests/auth/token-refresh.spec.js index d828bf48f..71549518e 100644 --- a/cda-gui/tests/auth/token-refresh.spec.js +++ b/cda-gui/tests/auth/token-refresh.spec.js @@ -37,7 +37,7 @@ test("published user hooks search across offices, assign membership, and save a user.roles.SWT = [...new Set([...(user.roles.SWT ?? []), ...roles])]; return route.fulfill({ status: 204 }); }); - await page.goto("/cwms-data/user-roles"); + await page.goto("/user-roles"); await page.getByRole("button", { name: "Assign office", exact: true }).click(); const dialog = page.getByRole("dialog"); await dialog @@ -134,7 +134,7 @@ async function mockDeployment(page, flow) { specRequests += 1; return route.fulfill({ json: { - openapi: "3.0.3", + openapi: "3.1.0", info: { title: "Refresh test", version: "1" }, servers: [{ url: `${origin}/cwms-data` }], components: { @@ -193,7 +193,7 @@ for (const flow of ["direct-grant", "pkce"]) { page.on("framenavigated", (frame) => { if (frame === page.mainFrame()) navigations += 1; }); - await page.goto("/cwms-data/swagger-ui"); + await page.goto("/swagger-ui"); await expect( page.getByRole("button", { name: "Log out", exact: true }), ).toBeVisible(); @@ -257,7 +257,7 @@ test("the application preserves a user-list form during background refresh", asy }); return route.fulfill({ json: {} }); }); - await page.goto("/cwms-data/user-lists"); + await page.goto("/user-lists"); await page.getByRole("button", { name: "New list", exact: true }).click(); await page.getByRole("textbox", { name: "List ID", exact: true }).fill("DRAFT-LIST"); await page @@ -282,7 +282,7 @@ test("an expired OpenID session leaves the Swagger draft available", async ({ page, }) => { const deployment = await mockDeployment(page, "pkce"); - await page.goto("/cwms-data/swagger-ui"); + await page.goto("/swagger-ui"); await expect( page.getByRole("button", { name: "Log out", exact: true }), ).toBeVisible(); diff --git a/cda-gui/tests/data-query/location-pagination.spec.js b/cda-gui/tests/data-query/location-pagination.spec.js index 07c713f9b..32195f019 100644 --- a/cda-gui/tests/data-query/location-pagination.spec.js +++ b/cda-gui/tests/data-query/location-pagination.spec.js @@ -19,7 +19,7 @@ async function searchLocations(page, pageCount) { }, }); }); - await page.goto("/cwms-data/data-query"); + await page.goto("/data-query"); await page.getByRole("button", { name: "Guided", exact: true }).click(); await page .locator("select") diff --git a/cda-gui/tests/user-roles/office-url.spec.js b/cda-gui/tests/user-roles/office-url.spec.js index 5dc958401..0ac6bd10e 100644 --- a/cda-gui/tests/user-roles/office-url.spec.js +++ b/cda-gui/tests/user-roles/office-url.spec.js @@ -15,7 +15,7 @@ test("office links override storage; dropdown labels are sorted and include HQ", JSON.stringify({ office: "SPK", userName: "gray.sacramento" }), ), ); - await login(page, "/cwms-data/user-roles/swt"); + await login(page, "/user-roles/swt"); await expect(page.locator("#role-office")).toHaveValue("SWT"); await expect(page.locator("#role-office option")).toHaveText([ "HQ - Headquarters", @@ -31,7 +31,7 @@ test("office links override storage; dropdown labels are sorted and include HQ", }); test("HQ is viewable without granting HQ edit permissions", async ({ page }) => { - await login(page, "/cwms-data/user-roles/hq"); + await login(page, "/user-roles/hq"); await expect(page.locator("#role-office")).toHaveValue("HQ"); await expect( page.getByText( @@ -58,14 +58,14 @@ test("HQ administrators retain edit access and HQ occurs only once", async ({ }, }), ); - await login(page, "/cwms-data/user-roles/HQ"); + await login(page, "/user-roles/HQ"); await expect(page).toHaveURL(/\/user-roles\/hq$/); await expect(page.locator('#role-office option[value="HQ"]')).toHaveCount(1); await expect(page.locator("#role-mode-custom")).toBeEnabled(); }); test("unknown office URLs fall back to the default office", async ({ page }) => { - await login(page, "/cwms-data/user-roles/unknown"); + await login(page, "/user-roles/unknown"); await expect(page).toHaveURL(/\/user-roles\/spk$/); await expect(page.locator("#role-office")).toHaveValue("SPK"); }); diff --git a/cda-gui/tests/user-roles/onboarding.spec.js b/cda-gui/tests/user-roles/onboarding.spec.js index 59c85cd04..d420c6b30 100644 --- a/cda-gui/tests/user-roles/onboarding.spec.js +++ b/cda-gui/tests/user-roles/onboarding.spec.js @@ -6,7 +6,7 @@ test.beforeEach(async ({ request }) => { }); async function openRoles(page) { - await page.goto("/cwms-data/user-roles"); + await page.goto("/user-roles"); const login = page.getByRole("button", { name: "Log in", exact: true }); await login.last().click(); await expect( @@ -130,7 +130,7 @@ test("missing PD hides office assignment while retaining the office role editor" await page.route("**/demo-api/user/profile*", (route) => route.fulfill({ json: { ...demoProfile, roles: { SWT: ["CWMS User Admins"] } } }), ); - await page.goto("/cwms-data/user-roles"); + await page.goto("/user-roles"); await page.getByRole("button", { name: "Log in", exact: true }).last().click(); await expect(page.getByText("Office users", { exact: true })).toBeVisible(); await expect( diff --git a/cda-gui/tests/user-roles/selection.spec.js b/cda-gui/tests/user-roles/selection.spec.js index a825b008f..32e95d5fc 100644 --- a/cda-gui/tests/user-roles/selection.spec.js +++ b/cda-gui/tests/user-roles/selection.spec.js @@ -2,7 +2,7 @@ import { expect, test } from "@playwright/test"; import { demoProfile, demoRoles } from "./demo-data"; async function openRoles(page) { - await page.goto("/cwms-data/user-roles"); + await page.goto("/user-roles"); await page.getByRole("button", { name: "Log in", exact: true }).last().click(); } diff --git a/cda-gui/vite.config.js b/cda-gui/vite.config.js index 3b1dcfd19..a6112a396 100644 --- a/cda-gui/vite.config.js +++ b/cda-gui/vite.config.js @@ -15,9 +15,8 @@ export default defineConfig(({ mode }) => { env.VITE_CDA_API_ROOT || env.CDA_API_ROOT || "http://localhost:8081", "http://localhost:8081", ).origin; - // const BASE_PATH = env?.BASE_PATH ?? "/cwms-data"; return { - base: "/cwms-data", + base: "/", plugins: [react()], optimizeDeps: { include: ["react-dom/client", "react-router-dom"], diff --git a/clients/typescript/build.gradle b/clients/typescript/build.gradle index 245340aa6..3a54d4ac3 100644 --- a/clients/typescript/build.gradle +++ b/clients/typescript/build.gradle @@ -6,7 +6,7 @@ import org.openapitools.generator.gradle.plugin.tasks.ValidateTask plugins { id 'base' id 'com.github.node-gradle.node' version '7.1.0' - id 'org.openapi.generator' version '7.15.0' + id 'org.openapi.generator' version '7.25.0' } def npmCacheDir = layout.buildDirectory.dir("npm-cache") @@ -40,11 +40,12 @@ clean.dependsOn cleanGeneration tasks.register('copyOpenApiSpec') { group 'openapi' description 'Copy the locally generated CDA OpenAPI spec into the TypeScript client workspace.' - dependsOn ':cwms-data-api:executeOpenAPIConversion' + dependsOn ':cwms-data-api:compileJava' + inputs.file "$rootDir/cwms-data-api/build/classes/java/main/openapi-plugin/openapi-default.json" outputs.file rawSpecFile doLast { copy { - from "$rootDir/cwms-data-api/build/openapi.json" + from "$rootDir/cwms-data-api/build/classes/java/main/openapi-plugin/openapi-default.json" into projectDir rename { 'cwms-swagger-raw.json' } } @@ -68,7 +69,7 @@ tasks.register('validateOpenApiSpec', ValidateTask) { group 'openapi' description 'Validate the adjusted TypeScript client OpenAPI spec.' dependsOn modSpec - inputSpec.set(modifiedSpecFile.asFile.absolutePath) + inputSpec.set(modifiedSpecFile.asFile) } tasks.register('generateTypeScriptClient', GenerateTask) { @@ -76,9 +77,9 @@ tasks.register('generateTypeScriptClient', GenerateTask) { description 'Generate the cwmsjs TypeScript client with the Gradle OpenAPI plugin.' dependsOn validateOpenApiSpec validateSpec = true - inputSpec = modifiedSpecFile.asFile.absolutePath - outputDir = generatedClientDir.asFile.absolutePath - configFile = layout.projectDirectory.file('openapi.config.json').asFile.absolutePath + inputSpec = modifiedSpecFile.asFile + outputDir = generatedClientDir.asFile + configFile = layout.projectDirectory.file('openapi.config.json').asFile generatorName = 'typescript-fetch' globalProperties.set([ modelDocs : 'true', @@ -87,7 +88,7 @@ tasks.register('generateTypeScriptClient', GenerateTask) { apiTests : 'false', enabledPostProcessFile: 'false' ]) - ignoreFileOverride = layout.projectDirectory.file('.openapi-generator-ignore').asFile.absolutePath + ignoreFileOverride = layout.projectDirectory.file('.openapi-generator-ignore').asFile } tasks.register('modPackage', NpxTask) { diff --git a/clients/typescript/openapitools.json b/clients/typescript/openapitools.json index 9cbc6d5d6..8dd0d7455 100644 --- a/clients/typescript/openapitools.json +++ b/clients/typescript/openapitools.json @@ -2,6 +2,6 @@ "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json", "spaces": 2, "generator-cli": { - "version": "5.4.0" + "version": "7.25.0" } } diff --git a/clients/typescript/package-lock.json b/clients/typescript/package-lock.json index 50bf84662..bafdba66e 100644 --- a/clients/typescript/package-lock.json +++ b/clients/typescript/package-lock.json @@ -327,6 +327,7 @@ "integrity": "sha512-kEGSzqM2lWr4whh4Ubflw+oPZSEzxvRMu9WL+LveZploJWTjec5bBlCiRVlVzTPg2kIwBiLwWSvCCW7Wnin1gg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "file-type": "21.3.4", "iterare": "1.2.1", @@ -931,6 +932,7 @@ "integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", @@ -3992,7 +3994,8 @@ "resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz", "integrity": "sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/randomatic": { "version": "3.1.1", @@ -4336,7 +4339,8 @@ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", "dev": true, - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/regenerator-runtime": { "version": "0.10.5", @@ -4524,6 +4528,7 @@ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -5368,6 +5373,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/clients/typescript/scripts/spec-updates/BaseRatingMetadata.json b/clients/typescript/scripts/spec-updates/BaseRatingMetadata.json index 1af7eaf76..c1bf5a3dc 100644 --- a/clients/typescript/scripts/spec-updates/BaseRatingMetadata.json +++ b/clients/typescript/scripts/spec-updates/BaseRatingMetadata.json @@ -30,7 +30,7 @@ "type": "string" }, "vertical-datum-info": { - "$ref": "#/components/schemas/vertical-datum-info" + "$ref": "#/components/schemas/VerticalDatumInfo" } } } diff --git a/compose_files/api_entry.sh b/compose_files/api_entry.sh index 97c9a818c..726ab368a 100755 --- a/compose_files/api_entry.sh +++ b/compose_files/api_entry.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh nohup ./proxy_auth.sh 2>&1 > /dev/null & echo "auth proxy started now executing $*" diff --git a/compose_files/proxy_auth.sh b/compose_files/proxy_auth.sh index e57c30aa8..a32265515 100755 --- a/compose_files/proxy_auth.sh +++ b/compose_files/proxy_auth.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh mkfifo backpipe #while true; do nc -lk -p 7100 0backpipe; done diff --git a/cwms-data-api/build.gradle b/cwms-data-api/build.gradle index c927f61dc..31ac91140 100644 --- a/cwms-data-api/build.gradle +++ b/cwms-data-api/build.gradle @@ -1,25 +1,19 @@ plugins { id 'cda.deps-conventions' id 'cda.java-conventions' - id 'war' id 'com.gradleup.shadow' version '8.3.10' + id 'application' } configurations { info - webjars + ui docker baseLibs - tomcatLibs - testImplementation.extendsFrom(tomcatLibs) jooqCodegenLatest jooqCodegenLegacy } -configurations.implementation { - exclude group: 'com.oracle.database.jdbc' -} - configurations.all { exclude group: 'dom4j' exclude group: 'org.apache.xmlbeans' @@ -30,6 +24,7 @@ configurations.all { dependencies { annotationProcessor(libs.com.google.auto.service) + annotationProcessor(libs.javalin.openapi.annotation.processor) compileOnly(libs.com.google.auto.service.annotations) implementation(libs.jaxb.api) implementation(libs.jaxb.core) @@ -79,6 +74,8 @@ dependencies { //exclude group: "org.python", module: "jython-standalone" //exclude group: "mil.army.usace.hec.swingx" exclude group: "*" + exclude group: "com.oracle", module: "*" + exclude group: "com.oracle.database.jdbc", module: "*" } implementation(libs.google.flogger.api) @@ -88,18 +85,24 @@ dependencies { implementation(libs.nucleus.data) { exclude group: "org.jdom" + exclude group: "com.oracle", module: "*" + exclude group: "com.oracle.database.jdbc", module: "*" } implementation(libs.nucleus.metadata) implementation(libs.cwms.ratings.core) { //exclude group: "mil.army.usace.hec.swingx" exclude group: "*" + exclude group: "com.oracle", module: "*" + exclude group: "com.oracle.database.jdbc", module: "*" } implementation(libs.cwms.ratings.io.xml) implementation(libs.cwms.ratings.io.jdbc) { exclude group: "mil.army.usace.hec", module: "cwms-db-jooq-codegen" exclude group: "org.jooq.pro-java-11", module: "jooq" + exclude group: "com.oracle", module: "*" + exclude group: "com.oracle.database.jdbc", module: "*" } implementation(libs.jooq) { @@ -113,23 +116,17 @@ dependencies { implementation(libs.geojson.jackson) implementation(libs.jackson.datatype.jdk8) + + implementation(libs.com.zaxxer.hikaricp) + implementation(libs.javalin.core) + implementation(libs.bundles.javalin.openapi) - implementation(libs.javalin.core) { - exclude group: "org.eclipse.jetty" - exclude group: "org.eclipse.jetty.websocket" - } - implementation(libs.javalin.openapi) { - //exclude group: "org.eclipse.jetty" - exclude group: "org.eclipse.jetty.websocket" - exclude group: "jakarta.xml.bind", module: "*" - } implementation(libs.swagger.core) { exclude group: "jakarta.xml.bind", module: "*" } implementation(libs.password4j) implementation 'cz.jirutka.rsql:rsql-parser:2.1.0' - compileOnly(libs.javaee.web.api) compileOnly(libs.cwms.tomcat.auth) @@ -154,27 +151,24 @@ dependencies { testImplementation(libs.mockito.core) testRuntimeOnly(libs.jaxb.impl) testImplementation(libs.openapi.spec.validation) + testImplementation(libs.javalin.test.tools) + testImplementation(libs.javalin.context.mock) { + exclude group: "org.eclipse.jetty.toolchain", module: "jetty-jakarta-servlet-api" + } - baseLibs(libs.oracle.jdbc.driver) - - compileOnly(libs.oracle.jdbc.driver) - testRuntimeOnly(libs.oracle.jdbc.driver) + implementation(libs.oracle.jdbc.driver) testImplementation(libs.bundles.jackson) testImplementation(libs.rest.assured) testImplementation(libs.hamcrest.all) testImplementation(libs.slf4j.jul) - tomcatLibs(libs.bundles.tomcat.embedded) - tomcatLibs(libs.bundles.tomcat.support) - tomcatLibs(libs.google.flogger.api) - tomcatLibs(libs.google.flogger.system.backend) - baseLibs(libs.google.flogger.slf4j.backend) { exclude group: "org.slf4j" } - baseLibs(libs.ch.qos.logback) + implementation(libs.ch.qos.logback) + //baseLibs(libs.ch.qos.logback) baseLibs(libs.io.opentelemetry.instrumentation.logback.mdc) testImplementation(libs.bundles.testcontainers) @@ -183,7 +177,7 @@ dependencies { testImplementation(libs.cwms.tomcat.auth) testImplementation(libs.apache.freemarker) - webjars(project(":cda-gui")) + ui(project(path: ":cda-gui", configuration: "warOutput")) // override versions @@ -194,95 +188,61 @@ dependencies { implementation(libs.minio) } -task extractWebJars(type: Copy) { - dependsOn configurations.webjars - from zipTree(configurations.webjars.singleFile) - into file("$buildDir/extra") - includeEmptyDirs false - includeEmptyDirs = false -} - -war { - dependsOn extractWebJars - from "$buildDir/extra" - from "src/resources/" - - manifest { - attributes "build-version": project.version - } - - doLast { - println(war.archiveFileName.toString()) - println("::set-output name=WARFILE::${project.name}-${project.version}.war") - } -} - -compileTestJava.classpath += configurations.tomcatLibs - -sourceSets { - formatList { - output.resourcesDir = layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main") - java.destinationDirectory = layout.buildDirectory.dir("generated/sources/annotationProcessor/java/main") - } - main { - runtimeClasspath += formatList.runtimeClasspath - } - test { - runtimeClasspath += formatList.runtimeClasspath - } -} - test { useJUnitPlatform() { excludeTags "integration" } - classpath += configurations.tomcatLibs + classpath += configurations.baseLibs + jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback-test.xml" } description = 'CWMS-Data-API' -task generateConfig(type: Copy) { +application { + mainClass = 'cwms.cda.CwmsDataApi' + applicationDefaultJvmArgs += "-Dlogback.configurationFile=logback.xml" +} + +jar { + manifest { + attributes "build-version": project.version + attributes "Main-Class": 'cwms.cda.CwmsDataApi' // duplicating this here because doing this appears to interfere + // with the application setup aove. + } doFirst { - project.delete "$buildDir/tomcat/" - project.mkdir "$buildDir/tomcat/logs" + def manifestDir = layout.buildDirectory.dir("resources/main/META-INF").get() + manifestDir.asFile.mkdirs() + manifest.writeTo(manifestDir.file(("MANIFEST.MF"))) } - from 'src/test/resources/tomcat' - into "$buildDir/tomcat" - - //rename "context.xml", "context.xml.template" - rename "tomcat-server.xml", "server.xml" - - inputs.dir "src/test/resources" - outputs.dir "$buildDir/tomcat/conf" } -task run(type: JavaExec) { - group "application" - dependsOn generateConfig - dependsOn war +distributions { + main { + contents { + into ('wars') { + from configurations.ui + rename '.*', 'ui.war' + } + } + } +} - classpath += configurations.baseLibs - classpath += configurations.tomcatLibs - classpath += sourceSets.test.output // to get the fixture +run() { + dependsOn configurations.ui + dependsOn jar // to make sure the /META-INF/MANIFEST.MF is build to render the version + classpath sourceSets.main.runtimeClasspath + + configurations.baseLibs - mainClass = "fixtures.TomcatServer" - systemProperties += project.properties.findAll { k, v -> k.startsWith("RADAR") } systemProperties += project.properties.findAll { k, v -> k.startsWith("CDA") } systemProperties += project.properties.findAll { k, v -> k.startsWith("cwms") } environment("TS_USE_DMZ_INCLUDE", "true") - def context = project.findProperty("cda.war.context") ?: "spk-data" + def context = project.findProperty("cda.war.context") ?: "/cwms-data" - args "$buildDir/tomcat", "$buildDir/libs/${project.name}-${project.version}.war", context - jvmArgs += "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" - jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties" - jvmArgs += "-DTOMCAT_RESOURCES=$buildDir/tomcat/conf/context.xml" - jvmArgs += "-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" + args context, configurations.ui.asPath, 7010 jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback.xml" - jvmArgs += "-Dcatalina.base=$buildDir/tomcat" - jvmArgs += "-DwarContext=/" + context - jvmArgs += "-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true" jvmArgs += "-DAUTH_RE_ENABLE_NON_HASH_KEY_SUPPORT=true" jvmArgs += "-Duser.timezone=UTC" + // If you have the docker-compose environment up and are trying to run // CDA from run to debug uncomment the following lines. //jvmArgs += "-Dcwms.dataapi.access.providers=KeyAccessManager,CwmsAccessManager,OpenID" @@ -297,18 +257,15 @@ tasks.register('seedDevApiKeys', JavaExec) { classpath = sourceSets.test.runtimeClasspath classpath += configurations.baseLibs - classpath += configurations.tomcatLibs mainClass = "fixtures.SeedDevApiKeys" systemProperties += project.properties.findAll { k, v -> k.startsWith("CDA") } -// jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties" } task integrationTests(type: Test) { -// dependsOn test - dependsOn generateConfig - dependsOn war + dependsOn test + dependsOn configurations.ui useJUnitPlatform() { includeTags "integration" @@ -316,36 +273,28 @@ task integrationTests(type: Test) { shouldRunAfter test classpath += configurations.baseLibs // The before all extension will take care of these properties - systemProperties += project.properties.findAll { k, v -> k.startsWith("RADAR") && !k.startsWith("RADAR_JDBC") } systemProperties += project.properties.findAll { k, v -> k.startsWith("CDA") && !k.startsWith("CDA_JDBC") } systemProperties += project.properties.findAll { k, v -> k.startsWith("testcontainer") } environment("TS_USE_DMZ_INCLUDE", "true") - jvmArgs += "-DwarFile=$buildDir/libs/${project.name}-${project.version}.war" - jvmArgs += "-DwarContext=/cwms-data" - jvmArgs += "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" - jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties" + jvmArgs += "-DuiWarFile=${configurations.ui.asPath}" + jvmArgs += "-DwarContext=/cwms-data" jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback.xml" - jvmArgs += "-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" + jvmArgs += "-Dcwms.dataapi.access.provider=MultipleAccessManager" jvmArgs += "-Dcwms.dataapi.access.providers=KeyAccessManager,CwmsAccessManager" jvmArgs += "-Dproperties.file=$projectDir/src/test/resources/features-integration.properties" - jvmArgs += "-Dcatalina.base=$buildDir/tomcat" - //jvmArgs += "-Dflogger.backend_factory=com.google.common.flogger.backend.slf4j.Slf4jBackendFactory#getInstance" } task timeseriesReadBenchmark(type: JavaExec) { group "verification" description = "Run the local time-series read benchmark harness" - dependsOn generateConfig - dependsOn war dependsOn testClasses workingDir = projectDir classpath = sourceSets.test.runtimeClasspath - classpath += configurations.baseLibs - classpath += configurations.tomcatLibs + classpath += configurations.baseLibs mainClass = "helpers.TimeSeriesReadBenchmark" @@ -355,41 +304,9 @@ task timeseriesReadBenchmark(type: JavaExec) { jvmArgs += "-DwarFile=$buildDir/libs/${project.name}-${project.version}.war" jvmArgs += "-DwarContext=/cwms-data" - jvmArgs += "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" - jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties" - jvmArgs += "-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" + jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback.xml" jvmArgs += "-Dcwms.dataapi.access.provider=MultipleAccessManager" jvmArgs += "-Dcwms.dataapi.access.providers=KeyAccessManager,CwmsAccessManager" - jvmArgs += "-Dcatalina.base=$buildDir/tomcat" -} - -task prepareDockerBuild(type: Copy, dependsOn: war) { - doFirst { - project.mkdir("$buildDir/docker") - } - from "src/docker" - into "$buildDir/docker" - - from(configurations.docker) - - from(configurations.baseLibs) { - into "libs" - } - - from(sourceSets.test.resources) { - - include "**/conf/context.xml" - eachFile { - path = name - } - includeEmptyDirs = false - } - - from(war.outputs.files.singleFile) { - //include "${project.name}-${project.version}.jar" - into "cda/webapps" - rename(".*\\.war", "cwms-data.war") - } } task generateTimeSeriesSamples(type: JavaExec) { @@ -410,8 +327,6 @@ task generateTimeSeriesSamples(type: JavaExec) { tasks.register("executeOpenAPIConversion", Test) { group 'documentation' - dependsOn generateConfig - dependsOn war useJUnitPlatform() { includeTags "openapi" @@ -422,14 +337,9 @@ tasks.register("executeOpenAPIConversion", Test) { systemProperties += project.properties.findAll { k, v -> k.startsWith("RADAR") && !k.startsWith("RADAR_JDBC") } systemProperties += project.properties.findAll { k, v -> k.startsWith("CDA") && !k.startsWith("CDA_JDBC") } systemProperties += project.properties.findAll { k, v -> k.startsWith("testcontainer") } - jvmArgs += "-DwarFile=$buildDir/libs/${project.name}-${project.version}.war" - jvmArgs += "-DwarContext=/cwms-data" - jvmArgs += "-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager" - jvmArgs += "-Djava.util.logging.config.file=$projectDir/logging.properties" - jvmArgs += "-Dorg.apache.tomcat.util.digester.PROPERTY_SOURCE=org.apache.tomcat.util.digester.EnvironmentPropertySource" + jvmArgs += "-Dlogback.configurationFile=${projectDir}/logback.xml" jvmArgs += "-Dcwms.dataapi.access.provider=MultipleAccessManager" jvmArgs += "-Dcwms.dataapi.access.providers=KeyAccessManager,CwmsAccessManager" - jvmArgs += "-Dcatalina.base=$buildDir/tomcat" } tasks.register('shadeCodegenLegacy', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) { diff --git a/cwms-data-api/logback-test.xml b/cwms-data-api/logback-test.xml new file mode 100644 index 000000000..e10ac442d --- /dev/null +++ b/cwms-data-api/logback-test.xml @@ -0,0 +1,53 @@ + + + + + + + + + CWMS-Data-API + + + System.err + + ERROR + + + + + + + + + + + false + true + build/cda-test.jsonl + + + + + + + + + + %d [%thread] %-5level - %X{traceId:-none} - %logger - %msg %ex %n + + false + true + build/cda-plain-test.log + + + + + + + + + + + + diff --git a/cwms-data-api/logback.xml b/cwms-data-api/logback.xml index 3771148fb..c5121d9eb 100644 --- a/cwms-data-api/logback.xml +++ b/cwms-data-api/logback.xml @@ -42,7 +42,9 @@ - + + + diff --git a/cwms-data-api/src/docker/logback-juli.xml b/cwms-data-api/src/docker/logback-juli.xml index e6add50cb..5a98c6b5d 100644 --- a/cwms-data-api/src/docker/logback-juli.xml +++ b/cwms-data-api/src/docker/logback-juli.xml @@ -19,14 +19,6 @@ - - - - - - - - diff --git a/cwms-data-api/src/docker/logback.xml b/cwms-data-api/src/docker/logback.xml index 848857300..aa9a7b209 100644 --- a/cwms-data-api/src/docker/logback.xml +++ b/cwms-data-api/src/docker/logback.xml @@ -4,7 +4,6 @@ - CWMS-Data-API @@ -12,25 +11,16 @@ System.err - + - + - - - - - - - - - - + \ No newline at end of file diff --git a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java b/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java deleted file mode 100644 index c33958408..000000000 --- a/cwms-data-api/src/main/java/cwms/cda/ApiServlet.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2026 Hydrologic Engineering Center - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package cwms.cda; - -import static cwms.cda.openapi.ExampleUtils.addEndpointExamples; - -import com.codahale.metrics.Meter; -import com.codahale.metrics.MetricRegistry; -import com.codahale.metrics.servlets.MetricsServlet; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; -import com.google.common.flogger.FluentLogger; -import cwms.cda.api.Controllers; -import cwms.cda.api.auth.userlists.UserListController; -import cwms.cda.api.enums.UnitSystem; -import cwms.cda.api.errors.ApplicationException; -import cwms.cda.api.errors.CdaError; -import cwms.cda.api.errors.ExceptionTraceSupport; -import cwms.cda.data.dao.JooqDao; -import cwms.cda.data.dao.rss.QueueManager; -import cwms.cda.data.dto.csv.CwmsCsvDTO; -import cwms.cda.formatters.Formats; -import cwms.cda.formatters.csv.CsvExampleGenerator; -import cwms.cda.openapi.OpenApiSchemeProcessor; -import cwms.cda.security.Authenticator; -import cwms.cda.security.CdaAccessManager; -import cwms.cda.security.Role; -import io.github.classgraph.ClassGraph; -import io.github.classgraph.ScanResult; -import io.javalin.Javalin; -import io.javalin.core.JavalinConfig; -import io.javalin.core.security.RouteRole; -import io.javalin.core.util.Header; -import io.javalin.core.validation.JavalinValidation; -import io.javalin.http.BadRequestResponse; -import io.javalin.http.JavalinServlet; -import io.javalin.plugin.openapi.OpenApiOptions; -import io.javalin.plugin.openapi.OpenApiPlugin; -import io.opentelemetry.api.trace.Span; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.Operation; -import io.swagger.v3.oas.models.PathItem; -import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.media.MediaType; -import io.swagger.v3.oas.models.responses.ApiResponse; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.servers.Server; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.time.DateTimeException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.jar.Manifest; -import javax.annotation.Resource; -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.sql.DataSource; -import org.apache.http.entity.ContentType; -import org.jooq.exception.DataAccessException; -import org.owasp.html.HtmlPolicyBuilder; -import org.owasp.html.PolicyFactory; - - -/** - * Setup all the information required so we can serve the request. - * - */ -@WebServlet(urlPatterns = { "/catalog/*", - "/auth/*", - "/swagger-docs", - "/timeseries/*", - "/offices/*", - "/states/*", - "/counties/*", - "/location/*", - "/locations/*", - "/entity/*", - "/parameters/*", - "/timezones/*", - "/units/*", - "/ratings/*", - "/levels/*", - "/level-refs/*", - "/basins/*", - "/streams/*", - "/stream-locations/*", - "/stream-reaches/*", - "/measurements/*", - "/published/*", - "/blobs/*", - "/clobs/*", - "/pools/*", - "/specified-levels/*", - "/forecast-spec/*", - "/forecast-instance/*", - "/standard-text-id/*", - "/projects/*", - "/project-locks/*", - "/project-lock-rights/*", - "/properties/*", - "/lookup-types/*", - "/embankments/*", - "/user/*", - "/users/*", - "/roles/*", - "/version/*", - "/rss/*", - "/v2/*" -}) -public class ApiServlet extends HttpServlet { - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - - // based on https://bitbucket.hecdev.net/projects/CWMS/repos/cwms_aaa/browse/IntegrationTests/src/test/resources/sql/load_testusers.sql - public static final String CWMS_USERS_ROLE = "CWMS Users"; - public static final String CAC_USER = "cac_auth"; - /** Default OFFICE where needed. Based on context. e.g. /cwms-data -> HQ, /spk-data -> SPK */ - public static final String OFFICE_ID = "office_id"; - public static final String DATA_SOURCE = "data_source"; - public static final String RAW_DATA_SOURCE = "data_source"; - public static final String DATABASE = "database"; - public static final String IS_NEW_LRTS = "X-CWMS-LRTS-Formatting"; - - // The VERSION should match the gradle version but not contain the patch version. - // For example 2.4 not 2.4.13 - private static String VERSION; - - public static final String APPLICATION_TITLE = "CWMS Data API"; - public static final String PROVIDER_KEY_OLD = "radar.access.provider"; - public static final String PROVIDER_KEY = "cwms.dataapi.access.provider"; - public static final String DEFAULT_OFFICE_KEY = "cwms.dataapi.default.office"; - public static final String DEFAULT_PROVIDER = "MultipleAccessManager"; - - private MetricRegistry metrics; - private Meter totalRequests; - - private static final long serialVersionUID = 1L; - - JavalinServlet javalin = null; - private final Authenticator authenticator = new Authenticator(); - private final OpenApiSchemeProcessor schemeProcessor = new OpenApiSchemeProcessor(authenticator); - private String appContext; - - @Resource(name = "jdbc/CWMS3") - DataSource cwms; - private CdaAccessManager cdaAccessManager; - - public static String getApiVersion() { - return VERSION != null ? VERSION : "Not Yet Known"; - } - - - @Override - public void destroy() { - javalin.destroy(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - if (VERSION == null) { - ApiServlet.VERSION = obtainFullVersion(config); - } - logger.atInfo().log("Initializing CWMS Data API Version: " + VERSION); - metrics = (MetricRegistry)config.getServletContext() - .getAttribute(MetricsServlet.METRICS_REGISTRY); - totalRequests = metrics.meter("cwms.dataapi.total_requests"); - - super.init(config); - } - - @SuppressWarnings({"java:S125","java:S2095"}) // closed in destroy handler - @Override - public void init() { - logger.atInfo().log("Initializing Javalin."); - JavalinValidation.register(UnitSystem.class, UnitSystem::systemFor); - JavalinValidation.register(JooqDao.DeleteMethod.class, Controllers::getDeleteMethod); - - ObjectMapper om = new ObjectMapper(); - om.setPropertyNamingStrategy(PropertyNamingStrategies.KEBAB_CASE); - om.registerModule(new JavaTimeModule()); - - PolicyFactory sanitizer = new HtmlPolicyBuilder().disallowElements("