diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml
new file mode 120000
index 0000000..3a192db
--- /dev/null
+++ b/.gitea/workflows/build.yml
@@ -0,0 +1 @@
+../../.github/workflows/build.yml
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..9b72f34
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,67 @@
+name: Build and Push Docker Image
+
+on:
+ push:
+ branches:
+ - main
+ - master
+ tags:
+ - 'v*'
+ pull_request:
+ branches:
+ - main
+ - master
+ workflow_dispatch:
+
+env:
+ IMAGE_NAME: pi-mta-sign
+
+jobs:
+ build:
+ runs-on: ${{ vars.RUNNER || 'ubuntu-latest' }}
+ permissions:
+ contents: read
+ packages: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Log in to Container Registry
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v3
+ with:
+ registry: ${{ vars.REGISTRY || 'ghcr.io' }}
+ username: ${{ vars.REGISTRY_USERNAME || github.actor }}
+ password: ${{ secrets.REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata (tags, labels)
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ vars.REGISTRY || 'ghcr.io' }}/${{ vars.IMAGE_OWNER || github.repository_owner }}/${{ env.IMAGE_NAME }}
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=sha,prefix=
+ type=raw,value=latest,enable={{is_default_branch}}
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v6
+ with:
+ context: .
+ file: ./docker/Dockerfile
+ platforms: linux/amd64,linux/arm64
+ push: ${{ github.event_name != 'pull_request' }}
+ tags: ${{ steps.meta.outputs.tags }}
+ labels: ${{ steps.meta.outputs.labels }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
diff --git a/.gitignore b/.gitignore
index 2ed8492..317af95 100644
--- a/.gitignore
+++ b/.gitignore
@@ -124,4 +124,8 @@ venv.bak/
.dmypy.json
dmypy.jsons
-.ruff_cache
\ No newline at end of file
+.ruff_cache
+
+# Frontend build output
+static/
+mta-sign-ui/out/
\ No newline at end of file
diff --git a/.node-version b/.node-version
new file mode 100644
index 0000000..0fc49f5
--- /dev/null
+++ b/.node-version
@@ -0,0 +1 @@
+v25.4.0
diff --git a/docker/Dockerfile b/docker/Dockerfile
new file mode 100644
index 0000000..c5e8cad
--- /dev/null
+++ b/docker/Dockerfile
@@ -0,0 +1,45 @@
+# Stage 1: Build the Next.js frontend
+FROM docker.io/library/node:24-alpine AS frontend-builder
+LABEL authors="lucasoskorep"
+
+WORKDIR /build/mta-sign-ui
+
+# Enable corepack for pnpm
+RUN corepack enable && corepack prepare pnpm@10.28.1 --activate
+
+# Copy package files first for better caching
+COPY mta-sign-ui/package.json mta-sign-ui/pnpm-lock.yaml* ./
+
+# Install dependencies (use frozen-lockfile if lock exists, otherwise generate)
+RUN pnpm install
+
+# Copy the rest of the frontend source
+COPY mta-sign-ui/ ./
+
+# Build the static export (outputs to 'out' directory)
+RUN pnpm build
+
+# Stage 2: Python backend with frontend static files
+FROM ghcr.io/astral-sh/uv:python3.13-bookworm
+LABEL authors="lucasoskorep"
+
+WORKDIR /app
+
+# Copy dependency files and install dependencies only (not the project itself)
+COPY pyproject.toml uv.lock README.md ./
+RUN uv sync --frozen --no-dev --no-install-project
+
+# Copy source code
+COPY mta_api_client ./mta_api_client
+COPY mta_sign_server ./mta_sign_server
+COPY main.py stops.txt ./
+
+# Copy the built frontend from the first stage
+COPY --from=frontend-builder /build/mta-sign-ui/out ./static
+
+# Now install the project
+RUN uv sync --frozen --no-dev
+
+EXPOSE 8000
+
+ENTRYPOINT ["uv", "run", "python", "main.py"]
diff --git a/endpoints.json b/endpoints.json
deleted file mode 100644
index 0c351d1..0000000
--- a/endpoints.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ACE": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-ace",
- "BDFM": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-bdfm",
- "G": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-g",
- "JZ": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-jz",
- "NQRW": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw",
- "L": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-l",
- "SIR": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-si",
- "1234567": "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs"
-}
\ No newline at end of file
diff --git a/example-json-outputs/mta_status_alerts.json b/example-json-outputs/mta_status_alerts.json
deleted file mode 100644
index 4fd5521..0000000
--- a/example-json-outputs/mta_status_alerts.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lastUpdated": "2021-05-10T13:39:00-0400", "routeDetails": [{"route": "2", "color": "EE352E", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_2", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73533", "statusSummary": "Weekday Service", "statusDescription": "
[2] trains run between Wakefield-241 St and Flatbush Av-Brooklyn College .
", "priority": 3, "direction": "0", "creationDate": "2021-04-24T07:50:19-0400", "startDate": "2021-05-10T04:01:12-0400", "endDate": null}, {"id": "lmm:alert:73533", "statusSummary": "Weekday Service", "statusDescription": "[2] trains run between Wakefield-241 St and Flatbush Av-Brooklyn College .
", "priority": 3, "direction": "1", "creationDate": "2021-04-24T07:50:19-0400", "startDate": "2021-05-10T04:01:12-0400", "endDate": null}]}, {"route": "3", "color": "EE352E", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_3", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73541", "statusSummary": "Weekday Service", "statusDescription": "[3] trains run between Harlem-148 St and New Lots Av .
", "priority": 3, "direction": "0", "creationDate": "2021-04-24T07:51:06-0400", "startDate": "2021-05-10T04:03:11-0400", "endDate": null}, {"id": "lmm:alert:73541", "statusSummary": "Weekday Service", "statusDescription": "[3] trains run between Harlem-148 St and New Lots Av .
", "priority": 3, "direction": "1", "creationDate": "2021-04-24T07:51:06-0400", "startDate": "2021-05-10T04:03:11-0400", "endDate": null}]}, {"route": "6X", "color": "00A65C", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_6X", "inService": "true", "routeType": "1", "statusDetails": null}, {"route": "1", "color": "EE352E", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_1", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73532", "statusSummary": "Weekday Service", "statusDescription": "[1] trains run between \u200c\u200cVan Cortlandt Park-242 St and South Ferry .
", "priority": 3, "direction": "1", "creationDate": "2020-12-10T00:59:42-0500", "startDate": "2021-05-10T04:00:51-0400", "endDate": null}, {"id": "lmm:alert:73532", "statusSummary": "Weekday Service", "statusDescription": "[1] trains run between \u200c\u200cVan Cortlandt Park-242 St and South Ferry .
", "priority": 3, "direction": "0", "creationDate": "2020-12-10T00:59:42-0500", "startDate": "2021-05-10T04:00:51-0400", "endDate": null}]}, {"route": "S", "color": null, "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_FS", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73543", "statusSummary": "Weekday Service", "statusDescription": "[FS] trains run between Franklin Av and Prospect Park .
", "priority": 3, "direction": "0", "creationDate": "2020-12-08T01:07:08-0500", "startDate": "2021-05-10T04:03:37-0400", "endDate": null}, {"id": "lmm:alert:73543", "statusSummary": "Weekday Service", "statusDescription": "[FS] trains run between Franklin Av and Prospect Park .
", "priority": 3, "direction": "1", "creationDate": "2020-12-08T01:07:08-0500", "startDate": "2021-05-10T04:03:37-0400", "endDate": null}]}, {"route": "FX", "color": "FF6319", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_FX", "inService": "true", "routeType": "1", "statusDetails": null}, {"route": "W", "color": "FCCC0A", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_W", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73555", "statusSummary": "Weekday Service", "statusDescription": "[W] trains run between Astoria-Ditmars Blvd and Whitehall St-South Ferry .
Departing Astoria-Ditmars Blvd from 6:13 AM to 9:26 PM
Departing Whitehall St-South Ferry from 7:06 AM to 10:14 PM.
[W] trains do not operate late nights and weekends, take [N] or [R] service instead.
", "priority": 3, "direction": "0", "creationDate": "2021-04-21T08:17:11-0400", "startDate": "2021-05-10T04:58:38-0400", "endDate": null}, {"id": "lmm:alert:73555", "statusSummary": "Weekday Service", "statusDescription": "[W] trains run between Astoria-Ditmars Blvd and Whitehall St-South Ferry .
Departing Astoria-Ditmars Blvd from 6:13 AM to 9:26 PM
Departing Whitehall St-South Ferry from 7:06 AM to 10:14 PM.
[W] trains do not operate late nights and weekends, take [N] or [R] service instead.
", "priority": 3, "direction": "1", "creationDate": "2021-04-21T08:17:11-0400", "startDate": "2021-05-10T04:58:38-0400", "endDate": null}]}, {"route": "SIR", "color": null, "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_SI", "inService": "true", "routeType": "1", "statusDetails": [{"id": "MTA NYCT_277781", "statusSummary": "Planned Work", "statusDescription": "SCHEDULED MAINTENANCE May 10 - 12, Mon to Wed, 9 AM to 3 PM [SIR] Trains board at the Tottenville-bound platform at Arthur Kill and Richmond Valley Stations
", "priority": 9, "direction": "0", "creationDate": "2021-05-10T00:00:00-0400", "startDate": "2021-05-10T00:00:00-0400", "endDate": "2021-05-12T23:59:00-0400"}, {"id": "lmm:alert:73523", "statusSummary": "Weekday Service", "statusDescription": "On weekdays, [SIR] trains will operate to meet the S.I. Ferry, scheduled:
Every 20 minutes during the rush hour periods
Every 30 minutes during the midday/off-peak period
Every hour from 10 PM (from St George)/12 AM (from Tottenville) to 5 AM
On weekends, SIR trains will operate to meet the S.I. Ferry, scheduled:
Every 30 minutes from 7 AM to 11 PM
Every hour from 11 PM to 7 AM
", "priority": 3, "direction": "0", "creationDate": "2020-07-18T05:06:17-0400", "startDate": "2021-05-10T03:57:50-0400", "endDate": null}, {"id": "lmm:alert:73523", "statusSummary": "Weekday Service", "statusDescription": "On weekdays, [SIR] trains will operate to meet the S.I. Ferry, scheduled:
Every 20 minutes during the rush hour periods
Every 30 minutes during the midday/off-peak period
Every hour from 10 PM (from St George)/12 AM (from Tottenville) to 5 AM
On weekends, SIR trains will operate to meet the S.I. Ferry, scheduled:
Every 30 minutes from 7 AM to 11 PM
Every hour from 11 PM to 7 AM
", "priority": 3, "direction": "1", "creationDate": "2020-07-18T05:06:17-0400", "startDate": "2021-05-10T03:57:50-0400", "endDate": null}]}, {"route": "Z", "color": "996633", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_Z", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73527", "statusSummary": "Weekday Service", "statusDescription": "[Z] trains run between Jamaica Center-Parsons/Archer and Broad St AM and PM Rush hours.
Departing Jamaica Center-Parsons/Archer from 7:21 AM to 8:13 AM.
Departing Broad St from 4:55 PM to 5:45 PM.
[Z] trains do not operate evenings, late nights, and weekends; take [J] service instead.
", "priority": 3, "direction": "0", "creationDate": "2020-09-04T22:18:39-0400", "startDate": "2021-05-10T03:59:10-0400", "endDate": null}, {"id": "lmm:alert:73527", "statusSummary": "Weekday Service", "statusDescription": "[Z] trains run between Jamaica Center-Parsons/Archer and Broad St AM and PM Rush hours.
Departing Jamaica Center-Parsons/Archer from 7:21 AM to 8:13 AM.
Departing Broad St from 4:55 PM to 5:45 PM.
[Z] trains do not operate evenings, late nights, and weekends; take [J] service instead.
", "priority": 3, "direction": "1", "creationDate": "2020-09-04T22:18:39-0400", "startDate": "2021-05-10T03:59:10-0400", "endDate": null}]}, {"route": "N", "color": "FCCC0A", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_N", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73536", "statusSummary": "Weekday Service", "statusDescription": "[N] trains run between Astoria-Ditmars Blvd and Coney Island-Stillwell Av .
", "priority": 3, "direction": "1", "creationDate": "2021-02-01T19:42:07-0500", "startDate": "2021-05-10T04:02:19-0400", "endDate": null}, {"id": "lmm:alert:73536", "statusSummary": "Weekday Service", "statusDescription": "[N] trains run between Astoria-Ditmars Blvd and Coney Island-Stillwell Av .
", "priority": 3, "direction": "0", "creationDate": "2021-02-01T19:42:07-0500", "startDate": "2021-05-10T04:02:19-0400", "endDate": null}]}, {"route": "L", "color": "A7A9AC", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_L", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73524", "statusSummary": "Weekday Service", "statusDescription": "[L] trains run between 8 Av and Canarsie-Rockaway Pkwy .
", "priority": 3, "direction": "1", "creationDate": "2020-12-14T00:58:44-0500", "startDate": "2021-05-10T03:58:07-0400", "endDate": null}, {"id": "lmm:alert:73524", "statusSummary": "Weekday Service", "statusDescription": "[L] trains run between 8 Av and Canarsie-Rockaway Pkwy .
", "priority": 3, "direction": "0", "creationDate": "2020-12-14T00:58:44-0500", "startDate": "2021-05-10T03:58:07-0400", "endDate": null}]}, {"route": "M", "color": "FF6319", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_M", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73553", "statusSummary": "Weekday Service", "statusDescription": "[M] trains run between Forest Hills-71 Av and Middle Village-Metropolitan Av .
", "priority": 3, "direction": "0", "creationDate": "2020-12-06T01:12:29-0500", "startDate": "2021-05-10T04:57:10-0400", "endDate": null}, {"id": "lmm:alert:73553", "statusSummary": "Weekday Service", "statusDescription": "[M] trains run between Forest Hills-71 Av and Middle Village-Metropolitan Av .
", "priority": 3, "direction": "1", "creationDate": "2020-12-06T01:12:29-0500", "startDate": "2021-05-10T04:57:10-0400", "endDate": null}]}, {"route": "R", "color": "FCCC0A", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_R", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73552", "statusSummary": "Weekday Service", "statusDescription": "[R] trains run between Forest Hills-71 Av and Bay Ridge-95 St .
", "priority": 3, "direction": "1", "creationDate": "2021-04-11T01:58:40-0400", "startDate": "2021-05-10T04:56:42-0400", "endDate": null}, {"id": "lmm:alert:73552", "statusSummary": "Weekday Service", "statusDescription": "[R] trains run between Forest Hills-71 Av and Bay Ridge-95 St .
", "priority": 3, "direction": "0", "creationDate": "2021-04-11T01:58:40-0400", "startDate": "2021-05-10T04:56:42-0400", "endDate": null}]}, {"route": "7X", "color": "B933AD", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_7X", "inService": "true", "routeType": "1", "statusDetails": null}, {"route": "Q", "color": "FCCC0A", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_Q", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73530", "statusSummary": "Weekday Service", "statusDescription": "[Q] trains run between 96 St and Coney Island-Stillwell Av .
", "priority": 3, "direction": "0", "creationDate": "2020-12-08T01:06:24-0500", "startDate": "2021-05-10T04:00:14-0400", "endDate": null}, {"id": "lmm:alert:73530", "statusSummary": "Weekday Service", "statusDescription": "[Q] trains run between 96 St and Coney Island-Stillwell Av .
", "priority": 3, "direction": "1", "creationDate": "2020-12-08T01:06:24-0500", "startDate": "2021-05-10T04:00:14-0400", "endDate": null}]}, {"route": "F", "color": "FF6319", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_F", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73610", "statusSummary": "Some Reroutes", "statusDescription": "Some southbound [F] trains are running on the [A] line from W 4 St-Wash Sq to Jay St-MetroTech while we work to correct a signal malfunction at Delancey St-Essex St .
Expect delays in southbound [F] [A] service.
", "priority": 21, "direction": "0", "creationDate": "2021-05-10T12:30:54-0400", "startDate": "2021-05-10T12:30:54-0400", "endDate": null}, {"id": "lmm:alert:73558", "statusSummary": "Weekday Service", "statusDescription": "[F] trains run between Jamaica-179 St and Coney Island-Stillwell Av .
", "priority": 3, "direction": "0", "creationDate": "2020-12-08T01:01:03-0500", "startDate": "2021-05-10T05:02:30-0400", "endDate": null}, {"id": "lmm:alert:73610", "statusSummary": "Some Reroutes", "statusDescription": "Some southbound [F] trains are running on the [A] line from W 4 St-Wash Sq to Jay St-MetroTech while we work to correct a signal malfunction at Delancey St-Essex St .
Expect delays in southbound [F] [A] service.
", "priority": 21, "direction": "1", "creationDate": "2021-05-10T12:30:54-0400", "startDate": "2021-05-10T12:30:54-0400", "endDate": null}, {"id": "lmm:alert:73558", "statusSummary": "Weekday Service", "statusDescription": "[F] trains run between Jamaica-179 St and Coney Island-Stillwell Av .
", "priority": 3, "direction": "1", "creationDate": "2020-12-08T01:01:03-0500", "startDate": "2021-05-10T05:02:30-0400", "endDate": null}]}, {"route": "G", "color": "6CBE45", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_G", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73526", "statusSummary": "Weekday Service", "statusDescription": "[G] trains run between Church Av and Court Sq .
", "priority": 3, "direction": "0", "creationDate": "2020-12-10T01:00:39-0500", "startDate": "2021-05-10T03:58:44-0400", "endDate": null}, {"id": "lmm:alert:73526", "statusSummary": "Weekday Service", "statusDescription": "[G] trains run between Church Av and Court Sq .
", "priority": 3, "direction": "1", "creationDate": "2020-12-10T01:00:39-0500", "startDate": "2021-05-10T03:58:44-0400", "endDate": null}]}, {"route": "D", "color": "FF6319", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_D", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73535", "statusSummary": "Weekday Service", "statusDescription": "[D] trains run between Norwood-205 St and Coney Island-Stillwell Av .
", "priority": 3, "direction": "0", "creationDate": "2021-02-02T14:30:31-0500", "startDate": "2021-05-10T04:01:56-0400", "endDate": null}, {"id": "lmm:alert:73535", "statusSummary": "Weekday Service", "statusDescription": "[D] trains run between Norwood-205 St and Coney Island-Stillwell Av .
", "priority": 3, "direction": "1", "creationDate": "2021-02-02T14:30:31-0500", "startDate": "2021-05-10T04:01:56-0400", "endDate": null}]}, {"route": "E", "color": "2850AD", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_E", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73528", "statusSummary": "Weekday Service", "statusDescription": "[E] trains run between Jamaica Center-Parsons/Archer and World Trade Center .
", "priority": 3, "direction": "1", "creationDate": "2020-10-31T04:54:57-0400", "startDate": "2021-05-10T03:59:32-0400", "endDate": null}, {"id": "lmm:alert:73528", "statusSummary": "Weekday Service", "statusDescription": "[E] trains run between Jamaica Center-Parsons/Archer and World Trade Center .
", "priority": 3, "direction": "0", "creationDate": "2020-10-31T04:54:57-0400", "startDate": "2021-05-10T03:59:32-0400", "endDate": null}]}, {"route": "J", "color": "996633", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_J", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73537", "statusSummary": "Weekday Service", "statusDescription": "[J] trains run between Jamaica Center-Parsons/Archer and Broad St .
", "priority": 3, "direction": "1", "creationDate": "2020-12-08T01:02:39-0500", "startDate": "2021-05-10T04:02:42-0400", "endDate": null}, {"id": "lmm:alert:73537", "statusSummary": "Weekday Service", "statusDescription": "[J] trains run between Jamaica Center-Parsons/Archer and Broad St .
", "priority": 3, "direction": "0", "creationDate": "2020-12-08T01:02:39-0500", "startDate": "2021-05-10T04:02:42-0400", "endDate": null}]}, {"route": "S", "color": null, "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_H", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73556", "statusSummary": "Weekday Service", "statusDescription": "[H] trains run between Broad Channel and Rockaway Park-Beach 116 St .
", "priority": 3, "direction": "1", "creationDate": "2021-05-05T16:34:46-0400", "startDate": "2021-05-10T04:59:18-0400", "endDate": null}, {"id": "lmm:alert:73556", "statusSummary": "Weekday Service", "statusDescription": "[H] trains run between Broad Channel and Rockaway Park-Beach 116 St .
", "priority": 3, "direction": "0", "creationDate": "2021-05-05T16:34:46-0400", "startDate": "2021-05-10T04:59:18-0400", "endDate": null}]}, {"route": "S", "color": "6D6E71", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_GS", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73550", "statusSummary": "Weekday Service", "statusDescription": "[S] trains run between Times Sq-42 St and Grand Central-42 St .
Trains run between 6:00 AM and 12:00 AM Daily.
The [S] does not operate late nights, take [7] service instead.
", "priority": 3, "direction": "0", "creationDate": "2020-11-03T01:01:32-0500", "startDate": "2021-05-10T04:07:36-0400", "endDate": null}, {"id": "lmm:alert:73550", "statusSummary": "Weekday Service", "statusDescription": "[S] trains run between Times Sq-42 St and Grand Central-42 St .
Trains run between 6:00 AM and 12:00 AM Daily.
The [S] does not operate late nights, take [7] service instead.
", "priority": 3, "direction": "1", "creationDate": "2020-11-03T01:01:32-0500", "startDate": "2021-05-10T04:07:36-0400", "endDate": null}]}, {"route": "B", "color": "FF6319", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_B", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73596", "statusSummary": "Weekday Service", "statusDescription": "[B] trains run between 145 St and Brighton Beach .
", "priority": 3, "direction": "0", "creationDate": "2021-02-01T12:35:30-0500", "startDate": "2021-05-10T09:26:05-0400", "endDate": null}, {"id": "lmm:alert:73596", "statusSummary": "Weekday Service", "statusDescription": "[B] trains run between 145 St and Brighton Beach .
", "priority": 3, "direction": "1", "creationDate": "2021-02-01T12:35:30-0500", "startDate": "2021-05-10T09:26:05-0400", "endDate": null}]}, {"route": "C", "color": "2850AD", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_C", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73557", "statusSummary": "Weekday Service", "statusDescription": "[C] trains run between 168 St and Euclid Av .
", "priority": 3, "direction": "0", "creationDate": "2020-12-25T22:44:32-0500", "startDate": "2021-05-10T05:00:05-0400", "endDate": null}, {"id": "lmm:alert:73557", "statusSummary": "Weekday Service", "statusDescription": "[C] trains run between 168 St and Euclid Av .
", "priority": 3, "direction": "1", "creationDate": "2020-12-25T22:44:32-0500", "startDate": "2021-05-10T05:00:05-0400", "endDate": null}]}, {"route": "A", "color": "2850AD", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_A", "inService": "true", "routeType": "1", "statusDetails": [{"id": "MTA NYCT_277833", "statusSummary": "Planned Work", "statusDescription": "TRACK WORK Mon to Fri, 9 AM to 5 PM until Jun 18 (except May 31) [A] Downtown trains stop at 163 St and 155 St
", "priority": 9, "direction": "1", "creationDate": "2021-05-10T00:00:00-0400", "startDate": "2021-05-10T00:00:00-0400", "endDate": "2021-06-18T23:59:00-0400"}, {"id": "lmm:alert:73547", "statusSummary": "Weekday Service", "statusDescription": "[A] trains run between Inwood-207 St and Far Rockaway-Mott Av / Ozone Park-Lefferts Blvd .
", "priority": 3, "direction": "1", "creationDate": "2020-12-08T01:06:03-0500", "startDate": "2021-05-10T04:04:05-0400", "endDate": null}, {"id": "lmm:alert:73547", "statusSummary": "Weekday Service", "statusDescription": "[A] trains run between Inwood-207 St and Far Rockaway-Mott Av / Ozone Park-Lefferts Blvd .
", "priority": 3, "direction": "0", "creationDate": "2020-12-08T01:06:03-0500", "startDate": "2021-05-10T04:04:05-0400", "endDate": null}, {"id": "lmm:alert:73611", "statusSummary": "Delays", "statusDescription": "Some southbound [F] trains are running on the [A] line from W 4 St-Wash Sq to Jay St-MetroTech while we work to correct a signal malfunction at Delancey St-Essex St .
Expect delays in southbound [F] [A] service.
", "priority": 18, "direction": "0", "creationDate": "2021-05-10T12:30:54-0400", "startDate": "2021-05-10T12:30:54-0400", "endDate": null}, {"id": "lmm:alert:73611", "statusSummary": "Delays", "statusDescription": "Some southbound [F] trains are running on the [A] line from W 4 St-Wash Sq to Jay St-MetroTech while we work to correct a signal malfunction at Delancey St-Essex St .
Expect delays in southbound [F] [A] service.
", "priority": 18, "direction": "1", "creationDate": "2021-05-10T12:30:54-0400", "startDate": "2021-05-10T12:30:54-0400", "endDate": null}]}, {"route": "6", "color": "00933C", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_6", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73567", "statusSummary": "Weekday Service", "statusDescription": "[6] trains run between Pelham Bay Park and Brooklyn Bridge-City Hall .
[6X] trains run from Pelham Bay Park to Brooklyn Bridge-City Hall .
", "priority": 3, "direction": "0", "creationDate": "2020-12-08T01:00:26-0500", "startDate": "2021-05-10T06:11:32-0400", "endDate": null}, {"id": "lmm:alert:73567", "statusSummary": "Weekday Service", "statusDescription": "[6] trains run between Pelham Bay Park and Brooklyn Bridge-City Hall .
[6X] trains run from Pelham Bay Park to Brooklyn Bridge-City Hall .
", "priority": 3, "direction": "1", "creationDate": "2020-12-08T01:00:26-0500", "startDate": "2021-05-10T06:11:32-0400", "endDate": null}]}, {"route": "7", "color": "B933AD", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_7", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73603", "statusSummary": "Weekday Service", "statusDescription": "[7] trains run between 34 St-Hudson Yards and Flushing-Main St .
", "priority": 3, "direction": "0", "creationDate": "2020-12-10T01:01:10-0500", "startDate": "2021-05-10T10:30:42-0400", "endDate": null}, {"id": "lmm:alert:73603", "statusSummary": "Weekday Service", "statusDescription": "[7] trains run between 34 St-Hudson Yards and Flushing-Main St .
", "priority": 3, "direction": "1", "creationDate": "2020-12-10T01:01:10-0500", "startDate": "2021-05-10T10:30:42-0400", "endDate": null}]}, {"route": "4", "color": "00933C", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_4", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73560", "statusSummary": "Weekday Service", "statusDescription": "[4] trains run between Woodlawn and Crown Hts-Utica Av .
", "priority": 3, "direction": "0", "creationDate": "2020-12-10T01:02:13-0500", "startDate": "2021-05-10T05:10:52-0400", "endDate": null}, {"id": "lmm:alert:73560", "statusSummary": "Weekday Service", "statusDescription": "[4] trains run between Woodlawn and Crown Hts-Utica Av .
", "priority": 3, "direction": "1", "creationDate": "2020-12-10T01:02:13-0500", "startDate": "2021-05-10T05:10:52-0400", "endDate": null}]}, {"route": "5", "color": "00933C", "mode": "subway", "agency": "MTASBWY", "routeId": "MTASBWY_5", "inService": "true", "routeType": "1", "statusDetails": [{"id": "lmm:alert:73559", "statusSummary": "Weekday Service", "statusDescription": "[5] trains run between Eastchester-Dyre Av and Flatbush Av-Brooklyn College .
", "priority": 3, "direction": "0", "creationDate": "2021-04-24T07:52:11-0400", "startDate": "2021-05-10T05:07:18-0400", "endDate": null}, {"id": "lmm:alert:73559", "statusSummary": "Weekday Service", "statusDescription": "[5] trains run between Eastchester-Dyre Av and Flatbush Av-Brooklyn College .
", "priority": 3, "direction": "1", "creationDate": "2021-04-24T07:52:11-0400", "startDate": "2021-05-10T05:07:18-0400", "endDate": null}]}]}
\ No newline at end of file
diff --git a/example-json-outputs/subway_timing_sample.json b/example-json-outputs/subway_timing_sample.json
deleted file mode 100644
index b8f41d4..0000000
--- a/example-json-outputs/subway_timing_sample.json
+++ /dev/null
@@ -1,12439 +0,0 @@
-[
- {
- "id": "000001A",
- "trip_update": {
- "trip": {
- "trip_id": "132700_A..S",
- "start_time": "22:07:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "H06S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "H07S"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "H08S"
- },
- {
- "arrival": {
- "time": 1620705728
- },
- "departure": {
- "time": 1620705728
- },
- "stop_id": "H09S"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "H10S"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "H11S"
- }
- ]
- }
- },
- {
- "id": "000002A",
- "vehicle": {
- "trip": {
- "trip_id": "132700_A..S",
- "start_time": "22:07:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 37,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "H06S"
- }
- },
- {
- "id": "000003A",
- "trip_update": {
- "trip": {
- "trip_id": "134250_A..N",
- "start_time": "22:22:30",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A07N"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A06N"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "A05N"
- },
- {
- "arrival": {
- "time": 1620705863
- },
- "departure": {
- "time": 1620705863
- },
- "stop_id": "A03N"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "A02N"
- }
- ]
- }
- },
- {
- "id": "000004A",
- "vehicle": {
- "trip": {
- "trip_id": "134250_A..N",
- "start_time": "22:22:30",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 54,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A07N"
- }
- },
- {
- "id": "000005A",
- "trip_update": {
- "trip": {
- "trip_id": "135100_A..S",
- "start_time": "22:31:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705452
- },
- "departure": {
- "time": 1620705452
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620705616
- },
- "departure": {
- "time": 1620705616
- },
- "stop_id": "H02S"
- },
- {
- "arrival": {
- "time": 1620705736
- },
- "departure": {
- "time": 1620705736
- },
- "stop_id": "H03S"
- },
- {
- "arrival": {
- "time": 1620706126
- },
- "departure": {
- "time": 1620706126
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620706471
- },
- "departure": {
- "time": 1620706471
- },
- "stop_id": "H06S"
- },
- {
- "arrival": {
- "time": 1620706771
- },
- "departure": {
- "time": 1620706771
- },
- "stop_id": "H07S"
- },
- {
- "arrival": {
- "time": 1620706996
- },
- "departure": {
- "time": 1620706996
- },
- "stop_id": "H08S"
- },
- {
- "arrival": {
- "time": 1620707086
- },
- "departure": {
- "time": 1620707086
- },
- "stop_id": "H09S"
- },
- {
- "arrival": {
- "time": 1620707206
- },
- "departure": {
- "time": 1620707206
- },
- "stop_id": "H10S"
- },
- {
- "arrival": {
- "time": 1620707296
- },
- "departure": {
- "time": 1620707296
- },
- "stop_id": "H11S"
- }
- ]
- }
- },
- {
- "id": "000006A",
- "vehicle": {
- "trip": {
- "trip_id": "135100_A..S",
- "start_time": "22:31:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 48,
- "current_status": 1,
- "timestamp": 1620705452,
- "stop_id": "A61S"
- }
- },
- {
- "id": "000007A",
- "trip_update": {
- "trip": {
- "trip_id": "133978_A..N",
- "start_time": "22:19:47",
- "start_date": "20210510",
- "route_id": "A"
- }
- }
- },
- {
- "id": "000008A",
- "vehicle": {
- "trip": {
- "trip_id": "133978_A..N",
- "start_time": "22:19:47",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 51,
- "current_status": 1,
- "timestamp": 1620705101,
- "stop_id": "A02N"
- }
- },
- {
- "id": "000009A",
- "trip_update": {
- "trip": {
- "trip_id": "136300_A..S",
- "start_time": "22:43:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620705608
- },
- "departure": {
- "time": 1620705608
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620705878
- },
- "departure": {
- "time": 1620705878
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620705968
- },
- "departure": {
- "time": 1620705968
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620706058
- },
- "departure": {
- "time": 1620706058
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620706298
- },
- "departure": {
- "time": 1620706298
- },
- "stop_id": "A63S"
- },
- {
- "arrival": {
- "time": 1620706508
- },
- "departure": {
- "time": 1620706508
- },
- "stop_id": "A64S"
- },
- {
- "arrival": {
- "time": 1620706568
- },
- "departure": {
- "time": 1620706568
- },
- "stop_id": "A65S"
- }
- ]
- }
- },
- {
- "id": "000010A",
- "vehicle": {
- "trip": {
- "trip_id": "136300_A..S",
- "start_time": "22:43:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 41,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A52S"
- }
- },
- {
- "id": "000011A",
- "trip_update": {
- "trip": {
- "trip_id": "136500_A..N",
- "start_time": "22:45:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620705452
- },
- "departure": {
- "time": 1620705452
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620705542
- },
- "departure": {
- "time": 1620705542
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620705632
- },
- "departure": {
- "time": 1620705632
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620705722
- },
- "departure": {
- "time": 1620705722
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000012A",
- "vehicle": {
- "trip": {
- "trip_id": "136500_A..N",
- "start_time": "22:45:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 43,
- "current_status": 1,
- "timestamp": 1620705452,
- "stop_id": "A12N"
- }
- },
- {
- "id": "000013A",
- "trip_update": {
- "trip": {
- "trip_id": "137793_A..N",
- "start_time": "22:57:56",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620705536
- },
- "departure": {
- "time": 1620705536
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620705656
- },
- "departure": {
- "time": 1620705656
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620705746
- },
- "departure": {
- "time": 1620705746
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620705836
- },
- "departure": {
- "time": 1620705836
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620705956
- },
- "departure": {
- "time": 1620705956
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620706076
- },
- "departure": {
- "time": 1620706076
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620706166
- },
- "departure": {
- "time": 1620706166
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620706286
- },
- "departure": {
- "time": 1620706286
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620706346
- },
- "departure": {
- "time": 1620706346
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620706436
- },
- "departure": {
- "time": 1620706436
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620706601
- },
- "departure": {
- "time": 1620706601
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620706736
- },
- "departure": {
- "time": 1620706736
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620706826
- },
- "departure": {
- "time": 1620706826
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620706916
- },
- "departure": {
- "time": 1620706916
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620707006
- },
- "departure": {
- "time": 1620707006
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620707096
- },
- "departure": {
- "time": 1620707096
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620707156
- },
- "departure": {
- "time": 1620707156
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620707246
- },
- "departure": {
- "time": 1620707246
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620707381
- },
- "departure": {
- "time": 1620707381
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620707516
- },
- "departure": {
- "time": 1620707516
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620707606
- },
- "departure": {
- "time": 1620707606
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620707696
- },
- "departure": {
- "time": 1620707696
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620707786
- },
- "departure": {
- "time": 1620707786
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620707876
- },
- "departure": {
- "time": 1620707876
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000014A",
- "vehicle": {
- "trip": {
- "trip_id": "137793_A..N",
- "start_time": "22:57:56",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 29,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A40N"
- }
- },
- {
- "id": "000015A",
- "trip_update": {
- "trip": {
- "trip_id": "137500_A..S",
- "start_time": "22:55:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620705728
- },
- "departure": {
- "time": 1620705728
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620706148
- },
- "departure": {
- "time": 1620706148
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620706328
- },
- "departure": {
- "time": 1620706328
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620706418
- },
- "departure": {
- "time": 1620706418
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620706508
- },
- "departure": {
- "time": 1620706508
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620706598
- },
- "departure": {
- "time": 1620706598
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620706688
- },
- "departure": {
- "time": 1620706688
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620706778
- },
- "departure": {
- "time": 1620706778
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620707063
- },
- "departure": {
- "time": 1620707063
- },
- "stop_id": "A63S"
- },
- {
- "arrival": {
- "time": 1620707318
- },
- "departure": {
- "time": 1620707318
- },
- "stop_id": "A64S"
- },
- {
- "arrival": {
- "time": 1620707378
- },
- "departure": {
- "time": 1620707378
- },
- "stop_id": "A65S"
- }
- ]
- }
- },
- {
- "id": "000016A",
- "vehicle": {
- "trip": {
- "trip_id": "137500_A..S",
- "start_time": "22:55:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 34,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A45S"
- }
- },
- {
- "id": "000017A",
- "trip_update": {
- "trip": {
- "trip_id": "139835_A..N",
- "start_time": "23:18:21",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620705608
- },
- "departure": {
- "time": 1620705608
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620705728
- },
- "departure": {
- "time": 1620705728
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620705878
- },
- "departure": {
- "time": 1620705878
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620706148
- },
- "departure": {
- "time": 1620706148
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620706328
- },
- "departure": {
- "time": 1620706328
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620706418
- },
- "departure": {
- "time": 1620706418
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620706508
- },
- "departure": {
- "time": 1620706508
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620706568
- },
- "departure": {
- "time": 1620706568
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620706658
- },
- "departure": {
- "time": 1620706658
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620706793
- },
- "departure": {
- "time": 1620706793
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620706928
- },
- "departure": {
- "time": 1620706928
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620707018
- },
- "departure": {
- "time": 1620707018
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620707108
- },
- "departure": {
- "time": 1620707108
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620707198
- },
- "departure": {
- "time": 1620707198
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620707288
- },
- "departure": {
- "time": 1620707288
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000018A",
- "vehicle": {
- "trip": {
- "trip_id": "139835_A..N",
- "start_time": "23:18:21",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 27,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A32N"
- }
- },
- {
- "id": "000019A",
- "trip_update": {
- "trip": {
- "trip_id": "139050_A..S",
- "start_time": "23:10:30",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A36S"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "A38S"
- },
- {
- "arrival": {
- "time": 1620705818
- },
- "departure": {
- "time": 1620705818
- },
- "stop_id": "A40S"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "A41S"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "A42S"
- },
- {
- "arrival": {
- "time": 1620706148
- },
- "departure": {
- "time": 1620706148
- },
- "stop_id": "A43S"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620706328
- },
- "departure": {
- "time": 1620706328
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620706388
- },
- "departure": {
- "time": 1620706388
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620706508
- },
- "departure": {
- "time": 1620706508
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620706598
- },
- "departure": {
- "time": 1620706598
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620706718
- },
- "departure": {
- "time": 1620706718
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620706808
- },
- "departure": {
- "time": 1620706808
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620706898
- },
- "departure": {
- "time": 1620706898
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620707018
- },
- "departure": {
- "time": 1620707018
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620707108
- },
- "departure": {
- "time": 1620707108
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620707198
- },
- "departure": {
- "time": 1620707198
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620707288
- },
- "departure": {
- "time": 1620707288
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620707378
- },
- "departure": {
- "time": 1620707378
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620707468
- },
- "departure": {
- "time": 1620707468
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620707558
- },
- "departure": {
- "time": 1620707558
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620707648
- },
- "departure": {
- "time": 1620707648
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620707888
- },
- "departure": {
- "time": 1620707888
- },
- "stop_id": "H02S"
- },
- {
- "arrival": {
- "time": 1620708008
- },
- "departure": {
- "time": 1620708008
- },
- "stop_id": "H03S"
- },
- {
- "arrival": {
- "time": 1620708398
- },
- "departure": {
- "time": 1620708398
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620708743
- },
- "departure": {
- "time": 1620708743
- },
- "stop_id": "H06S"
- },
- {
- "arrival": {
- "time": 1620709043
- },
- "departure": {
- "time": 1620709043
- },
- "stop_id": "H07S"
- },
- {
- "arrival": {
- "time": 1620709268
- },
- "departure": {
- "time": 1620709268
- },
- "stop_id": "H08S"
- },
- {
- "arrival": {
- "time": 1620709358
- },
- "departure": {
- "time": 1620709358
- },
- "stop_id": "H09S"
- },
- {
- "arrival": {
- "time": 1620709478
- },
- "departure": {
- "time": 1620709478
- },
- "stop_id": "H10S"
- },
- {
- "arrival": {
- "time": 1620709568
- },
- "departure": {
- "time": 1620709568
- },
- "stop_id": "H11S"
- }
- ]
- }
- },
- {
- "id": "000020A",
- "vehicle": {
- "trip": {
- "trip_id": "139050_A..S",
- "start_time": "23:10:30",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 26,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A34S"
- }
- },
- {
- "id": "000021A",
- "trip_update": {
- "trip": {
- "trip_id": "141275_A..N",
- "start_time": "23:32:45",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705452
- },
- "departure": {
- "time": 1620705452
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620705608
- },
- "departure": {
- "time": 1620705608
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "A55N"
- },
- {
- "arrival": {
- "time": 1620705878
- },
- "departure": {
- "time": 1620705878
- },
- "stop_id": "A54N"
- },
- {
- "arrival": {
- "time": 1620705968
- },
- "departure": {
- "time": 1620705968
- },
- "stop_id": "A53N"
- },
- {
- "arrival": {
- "time": 1620706058
- },
- "departure": {
- "time": 1620706058
- },
- "stop_id": "A52N"
- },
- {
- "arrival": {
- "time": 1620706178
- },
- "departure": {
- "time": 1620706178
- },
- "stop_id": "A51N"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "A50N"
- },
- {
- "arrival": {
- "time": 1620706358
- },
- "departure": {
- "time": 1620706358
- },
- "stop_id": "A49N"
- },
- {
- "arrival": {
- "time": 1620706448
- },
- "departure": {
- "time": 1620706448
- },
- "stop_id": "A48N"
- },
- {
- "arrival": {
- "time": 1620706538
- },
- "departure": {
- "time": 1620706538
- },
- "stop_id": "A47N"
- },
- {
- "arrival": {
- "time": 1620706628
- },
- "departure": {
- "time": 1620706628
- },
- "stop_id": "A46N"
- },
- {
- "arrival": {
- "time": 1620706688
- },
- "departure": {
- "time": 1620706688
- },
- "stop_id": "A45N"
- },
- {
- "arrival": {
- "time": 1620706778
- },
- "departure": {
- "time": 1620706778
- },
- "stop_id": "A44N"
- },
- {
- "arrival": {
- "time": 1620706868
- },
- "departure": {
- "time": 1620706868
- },
- "stop_id": "A43N"
- },
- {
- "arrival": {
- "time": 1620706958
- },
- "departure": {
- "time": 1620706958
- },
- "stop_id": "A42N"
- },
- {
- "arrival": {
- "time": 1620707048
- },
- "departure": {
- "time": 1620707048
- },
- "stop_id": "A41N"
- },
- {
- "arrival": {
- "time": 1620707168
- },
- "departure": {
- "time": 1620707168
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620707348
- },
- "departure": {
- "time": 1620707348
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620707468
- },
- "departure": {
- "time": 1620707468
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620707558
- },
- "departure": {
- "time": 1620707558
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620707648
- },
- "departure": {
- "time": 1620707648
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620707768
- },
- "departure": {
- "time": 1620707768
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620707888
- },
- "departure": {
- "time": 1620707888
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620707978
- },
- "departure": {
- "time": 1620707978
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620708098
- },
- "departure": {
- "time": 1620708098
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620708158
- },
- "departure": {
- "time": 1620708158
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620708248
- },
- "departure": {
- "time": 1620708248
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620708398
- },
- "departure": {
- "time": 1620708398
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620708518
- },
- "departure": {
- "time": 1620708518
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620708608
- },
- "departure": {
- "time": 1620708608
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620708698
- },
- "departure": {
- "time": 1620708698
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620708788
- },
- "departure": {
- "time": 1620708788
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620708878
- },
- "departure": {
- "time": 1620708878
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620708938
- },
- "departure": {
- "time": 1620708938
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620709028
- },
- "departure": {
- "time": 1620709028
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620709163
- },
- "departure": {
- "time": 1620709163
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620709298
- },
- "departure": {
- "time": 1620709298
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620709388
- },
- "departure": {
- "time": 1620709388
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620709478
- },
- "departure": {
- "time": 1620709478
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620709568
- },
- "departure": {
- "time": 1620709568
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620709658
- },
- "departure": {
- "time": 1620709658
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000022A",
- "vehicle": {
- "trip": {
- "trip_id": "141275_A..N",
- "start_time": "23:32:45",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 10,
- "current_status": 1,
- "timestamp": 1620705452,
- "stop_id": "A61N"
- }
- },
- {
- "id": "000023A",
- "trip_update": {
- "trip": {
- "trip_id": "140600_A..S",
- "start_time": "23:26:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A24S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620705878
- },
- "departure": {
- "time": 1620705878
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620705998
- },
- "departure": {
- "time": 1620705998
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620706088
- },
- "departure": {
- "time": 1620706088
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620706178
- },
- "departure": {
- "time": 1620706178
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620706298
- },
- "departure": {
- "time": 1620706298
- },
- "stop_id": "A36S"
- },
- {
- "arrival": {
- "time": 1620706418
- },
- "departure": {
- "time": 1620706418
- },
- "stop_id": "A38S"
- },
- {
- "arrival": {
- "time": 1620706598
- },
- "departure": {
- "time": 1620706598
- },
- "stop_id": "A40S"
- },
- {
- "arrival": {
- "time": 1620706718
- },
- "departure": {
- "time": 1620706718
- },
- "stop_id": "A41S"
- },
- {
- "arrival": {
- "time": 1620706808
- },
- "departure": {
- "time": 1620706808
- },
- "stop_id": "A42S"
- },
- {
- "arrival": {
- "time": 1620706928
- },
- "departure": {
- "time": 1620706928
- },
- "stop_id": "A43S"
- },
- {
- "arrival": {
- "time": 1620707018
- },
- "departure": {
- "time": 1620707018
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620707108
- },
- "departure": {
- "time": 1620707108
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620707168
- },
- "departure": {
- "time": 1620707168
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620707288
- },
- "departure": {
- "time": 1620707288
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620707378
- },
- "departure": {
- "time": 1620707378
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620707498
- },
- "departure": {
- "time": 1620707498
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620707588
- },
- "departure": {
- "time": 1620707588
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620707678
- },
- "departure": {
- "time": 1620707678
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620707798
- },
- "departure": {
- "time": 1620707798
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620707888
- },
- "departure": {
- "time": 1620707888
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620707978
- },
- "departure": {
- "time": 1620707978
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620708068
- },
- "departure": {
- "time": 1620708068
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620708158
- },
- "departure": {
- "time": 1620708158
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620708248
- },
- "departure": {
- "time": 1620708248
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620708338
- },
- "departure": {
- "time": 1620708338
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620708428
- },
- "departure": {
- "time": 1620708428
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620708728
- },
- "departure": {
- "time": 1620708728
- },
- "stop_id": "A63S"
- },
- {
- "arrival": {
- "time": 1620708998
- },
- "departure": {
- "time": 1620708998
- },
- "stop_id": "A64S"
- },
- {
- "arrival": {
- "time": 1620709058
- },
- "departure": {
- "time": 1620709058
- },
- "stop_id": "A65S"
- }
- ]
- }
- },
- {
- "id": "000024A",
- "vehicle": {
- "trip": {
- "trip_id": "140600_A..S",
- "start_time": "23:26:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 18,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A24S"
- }
- },
- {
- "id": "000025A",
- "trip_update": {
- "trip": {
- "trip_id": "141780_A..N",
- "start_time": "23:37:48",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A49N"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A48N"
- },
- {
- "arrival": {
- "time": 1620705608
- },
- "departure": {
- "time": 1620705608
- },
- "stop_id": "A47N"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A46N"
- },
- {
- "arrival": {
- "time": 1620705758
- },
- "departure": {
- "time": 1620705758
- },
- "stop_id": "A45N"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "A44N"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "A43N"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "A42N"
- },
- {
- "arrival": {
- "time": 1620706118
- },
- "departure": {
- "time": 1620706118
- },
- "stop_id": "A41N"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620706418
- },
- "departure": {
- "time": 1620706418
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620706538
- },
- "departure": {
- "time": 1620706538
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620706628
- },
- "departure": {
- "time": 1620706628
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620706718
- },
- "departure": {
- "time": 1620706718
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620706838
- },
- "departure": {
- "time": 1620706838
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620706958
- },
- "departure": {
- "time": 1620706958
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620707048
- },
- "departure": {
- "time": 1620707048
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620707168
- },
- "departure": {
- "time": 1620707168
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620707228
- },
- "departure": {
- "time": 1620707228
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620707318
- },
- "departure": {
- "time": 1620707318
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620707468
- },
- "departure": {
- "time": 1620707468
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620707588
- },
- "departure": {
- "time": 1620707588
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620707678
- },
- "departure": {
- "time": 1620707678
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620707768
- },
- "departure": {
- "time": 1620707768
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620707858
- },
- "departure": {
- "time": 1620707858
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620707948
- },
- "departure": {
- "time": 1620707948
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620708008
- },
- "departure": {
- "time": 1620708008
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620708098
- },
- "departure": {
- "time": 1620708098
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620708233
- },
- "departure": {
- "time": 1620708233
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620708368
- },
- "departure": {
- "time": 1620708368
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620708458
- },
- "departure": {
- "time": 1620708458
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620708548
- },
- "departure": {
- "time": 1620708548
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620708638
- },
- "departure": {
- "time": 1620708638
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620708728
- },
- "departure": {
- "time": 1620708728
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000026A",
- "vehicle": {
- "trip": {
- "trip_id": "141780_A..N",
- "start_time": "23:37:48",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 13,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A49N"
- }
- },
- {
- "id": "000027A",
- "trip_update": {
- "trip": {
- "trip_id": "142200_A..S",
- "start_time": "23:42:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A12S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A14S"
- },
- {
- "arrival": {
- "time": 1620705608
- },
- "departure": {
- "time": 1620705608
- },
- "stop_id": "A15S"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A16S"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "A17S"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "A18S"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "A19S"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "A20S"
- },
- {
- "arrival": {
- "time": 1620706118
- },
- "departure": {
- "time": 1620706118
- },
- "stop_id": "A21S"
- },
- {
- "arrival": {
- "time": 1620706208
- },
- "departure": {
- "time": 1620706208
- },
- "stop_id": "A22S"
- },
- {
- "arrival": {
- "time": 1620706298
- },
- "departure": {
- "time": 1620706298
- },
- "stop_id": "A24S"
- },
- {
- "arrival": {
- "time": 1620706388
- },
- "departure": {
- "time": 1620706388
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620706508
- },
- "departure": {
- "time": 1620706508
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620706568
- },
- "departure": {
- "time": 1620706568
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620706658
- },
- "departure": {
- "time": 1620706658
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620706748
- },
- "departure": {
- "time": 1620706748
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620706868
- },
- "departure": {
- "time": 1620706868
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620706958
- },
- "departure": {
- "time": 1620706958
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620707048
- },
- "departure": {
- "time": 1620707048
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620707168
- },
- "departure": {
- "time": 1620707168
- },
- "stop_id": "A36S"
- },
- {
- "arrival": {
- "time": 1620707288
- },
- "departure": {
- "time": 1620707288
- },
- "stop_id": "A38S"
- },
- {
- "arrival": {
- "time": 1620707468
- },
- "departure": {
- "time": 1620707468
- },
- "stop_id": "A40S"
- },
- {
- "arrival": {
- "time": 1620707588
- },
- "departure": {
- "time": 1620707588
- },
- "stop_id": "A41S"
- },
- {
- "arrival": {
- "time": 1620707678
- },
- "departure": {
- "time": 1620707678
- },
- "stop_id": "A42S"
- },
- {
- "arrival": {
- "time": 1620707798
- },
- "departure": {
- "time": 1620707798
- },
- "stop_id": "A43S"
- },
- {
- "arrival": {
- "time": 1620707888
- },
- "departure": {
- "time": 1620707888
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620707978
- },
- "departure": {
- "time": 1620707978
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620708038
- },
- "departure": {
- "time": 1620708038
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620708158
- },
- "departure": {
- "time": 1620708158
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620708248
- },
- "departure": {
- "time": 1620708248
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620708368
- },
- "departure": {
- "time": 1620708368
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620708458
- },
- "departure": {
- "time": 1620708458
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620708548
- },
- "departure": {
- "time": 1620708548
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620708668
- },
- "departure": {
- "time": 1620708668
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620708758
- },
- "departure": {
- "time": 1620708758
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620708848
- },
- "departure": {
- "time": 1620708848
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620708938
- },
- "departure": {
- "time": 1620708938
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620709028
- },
- "departure": {
- "time": 1620709028
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620709118
- },
- "departure": {
- "time": 1620709118
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620709208
- },
- "departure": {
- "time": 1620709208
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620709298
- },
- "departure": {
- "time": 1620709298
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620709583
- },
- "departure": {
- "time": 1620709583
- },
- "stop_id": "A63S"
- },
- {
- "arrival": {
- "time": 1620709838
- },
- "departure": {
- "time": 1620709838
- },
- "stop_id": "A64S"
- },
- {
- "arrival": {
- "time": 1620709898
- },
- "departure": {
- "time": 1620709898
- },
- "stop_id": "A65S"
- }
- ]
- }
- },
- {
- "id": "000028A",
- "vehicle": {
- "trip": {
- "trip_id": "142200_A..S",
- "start_time": "23:42:00",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 8,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A12S"
- }
- },
- {
- "id": "000029A",
- "trip_update": {
- "trip": {
- "trip_id": "143150_A..S",
- "start_time": "23:51:30",
- "start_date": "20210510",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A03S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A05S"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "A06S"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A07S"
- },
- {
- "arrival": {
- "time": 1620705818
- },
- "departure": {
- "time": 1620705818
- },
- "stop_id": "A09S"
- },
- {
- "arrival": {
- "time": 1620705908
- },
- "departure": {
- "time": 1620705908
- },
- "stop_id": "A10S"
- },
- {
- "arrival": {
- "time": 1620705998
- },
- "departure": {
- "time": 1620705998
- },
- "stop_id": "A11S"
- },
- {
- "arrival": {
- "time": 1620706088
- },
- "departure": {
- "time": 1620706088
- },
- "stop_id": "A12S"
- },
- {
- "arrival": {
- "time": 1620706208
- },
- "departure": {
- "time": 1620706208
- },
- "stop_id": "A14S"
- },
- {
- "arrival": {
- "time": 1620706373
- },
- "departure": {
- "time": 1620706373
- },
- "stop_id": "A15S"
- },
- {
- "arrival": {
- "time": 1620706538
- },
- "departure": {
- "time": 1620706538
- },
- "stop_id": "A16S"
- },
- {
- "arrival": {
- "time": 1620706628
- },
- "departure": {
- "time": 1620706628
- },
- "stop_id": "A17S"
- },
- {
- "arrival": {
- "time": 1620706688
- },
- "departure": {
- "time": 1620706688
- },
- "stop_id": "A18S"
- },
- {
- "arrival": {
- "time": 1620706778
- },
- "departure": {
- "time": 1620706778
- },
- "stop_id": "A19S"
- },
- {
- "arrival": {
- "time": 1620706868
- },
- "departure": {
- "time": 1620706868
- },
- "stop_id": "A20S"
- },
- {
- "arrival": {
- "time": 1620706958
- },
- "departure": {
- "time": 1620706958
- },
- "stop_id": "A21S"
- },
- {
- "arrival": {
- "time": 1620707048
- },
- "departure": {
- "time": 1620707048
- },
- "stop_id": "A22S"
- },
- {
- "arrival": {
- "time": 1620707228
- },
- "departure": {
- "time": 1620707228
- },
- "stop_id": "A24S"
- },
- {
- "arrival": {
- "time": 1620707408
- },
- "departure": {
- "time": 1620707408
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620707528
- },
- "departure": {
- "time": 1620707528
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620707588
- },
- "departure": {
- "time": 1620707588
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620707678
- },
- "departure": {
- "time": 1620707678
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620707768
- },
- "departure": {
- "time": 1620707768
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620707888
- },
- "departure": {
- "time": 1620707888
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620707978
- },
- "departure": {
- "time": 1620707978
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620708068
- },
- "departure": {
- "time": 1620708068
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620708188
- },
- "departure": {
- "time": 1620708188
- },
- "stop_id": "A36S"
- },
- {
- "arrival": {
- "time": 1620708308
- },
- "departure": {
- "time": 1620708308
- },
- "stop_id": "A38S"
- },
- {
- "arrival": {
- "time": 1620708488
- },
- "departure": {
- "time": 1620708488
- },
- "stop_id": "A40S"
- },
- {
- "arrival": {
- "time": 1620708608
- },
- "departure": {
- "time": 1620708608
- },
- "stop_id": "A41S"
- },
- {
- "arrival": {
- "time": 1620708698
- },
- "departure": {
- "time": 1620708698
- },
- "stop_id": "A42S"
- },
- {
- "arrival": {
- "time": 1620708818
- },
- "departure": {
- "time": 1620708818
- },
- "stop_id": "A43S"
- },
- {
- "arrival": {
- "time": 1620708908
- },
- "departure": {
- "time": 1620708908
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620708998
- },
- "departure": {
- "time": 1620708998
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620709058
- },
- "departure": {
- "time": 1620709058
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620709178
- },
- "departure": {
- "time": 1620709178
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620709268
- },
- "departure": {
- "time": 1620709268
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620709388
- },
- "departure": {
- "time": 1620709388
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620709478
- },
- "departure": {
- "time": 1620709478
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620709568
- },
- "departure": {
- "time": 1620709568
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620709688
- },
- "departure": {
- "time": 1620709688
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620709778
- },
- "departure": {
- "time": 1620709778
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620709868
- },
- "departure": {
- "time": 1620709868
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620709958
- },
- "departure": {
- "time": 1620709958
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620710048
- },
- "departure": {
- "time": 1620710048
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620710138
- },
- "departure": {
- "time": 1620710138
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620710228
- },
- "departure": {
- "time": 1620710228
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620710318
- },
- "departure": {
- "time": 1620710318
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620710558
- },
- "departure": {
- "time": 1620710558
- },
- "stop_id": "H02S"
- },
- {
- "arrival": {
- "time": 1620710678
- },
- "departure": {
- "time": 1620710678
- },
- "stop_id": "H03S"
- },
- {
- "arrival": {
- "time": 1620711068
- },
- "departure": {
- "time": 1620711068
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620711338
- },
- "departure": {
- "time": 1620711338
- },
- "stop_id": "H06S"
- },
- {
- "arrival": {
- "time": 1620711488
- },
- "departure": {
- "time": 1620711488
- },
- "stop_id": "H07S"
- },
- {
- "arrival": {
- "time": 1620711638
- },
- "departure": {
- "time": 1620711638
- },
- "stop_id": "H08S"
- },
- {
- "arrival": {
- "time": 1620711728
- },
- "departure": {
- "time": 1620711728
- },
- "stop_id": "H09S"
- },
- {
- "arrival": {
- "time": 1620711848
- },
- "departure": {
- "time": 1620711848
- },
- "stop_id": "H10S"
- },
- {
- "arrival": {
- "time": 1620711938
- },
- "departure": {
- "time": 1620711938
- },
- "stop_id": "H11S"
- }
- ]
- }
- },
- {
- "id": "000030A",
- "vehicle": {
- "trip": {
- "trip_id": "143150_A..S",
- "start_time": "23:51:30",
- "start_date": "20210510",
- "route_id": "A"
- },
- "current_stop_sequence": 1,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A03S"
- }
- },
- {
- "id": "000031A",
- "trip_update": {
- "trip": {
- "trip_id": "000800_A..N",
- "start_time": "00:08:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706080
- },
- "departure": {
- "time": 1620706080
- },
- "stop_id": "A65N"
- },
- {
- "arrival": {
- "time": 1620706170
- },
- "departure": {
- "time": 1620706170
- },
- "stop_id": "A64N"
- },
- {
- "arrival": {
- "time": 1620706230
- },
- "departure": {
- "time": 1620706230
- },
- "stop_id": "A63N"
- },
- {
- "arrival": {
- "time": 1620706320
- },
- "departure": {
- "time": 1620706320
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620706410
- },
- "departure": {
- "time": 1620706410
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620706500
- },
- "departure": {
- "time": 1620706500
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620706590
- },
- "departure": {
- "time": 1620706590
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620706680
- },
- "departure": {
- "time": 1620706680
- },
- "stop_id": "A55N"
- },
- {
- "arrival": {
- "time": 1620706770
- },
- "departure": {
- "time": 1620706770
- },
- "stop_id": "A54N"
- },
- {
- "arrival": {
- "time": 1620706860
- },
- "departure": {
- "time": 1620706860
- },
- "stop_id": "A53N"
- },
- {
- "arrival": {
- "time": 1620706950
- },
- "departure": {
- "time": 1620706950
- },
- "stop_id": "A52N"
- },
- {
- "arrival": {
- "time": 1620707070
- },
- "departure": {
- "time": 1620707070
- },
- "stop_id": "A51N"
- },
- {
- "arrival": {
- "time": 1620707130
- },
- "departure": {
- "time": 1620707130
- },
- "stop_id": "A50N"
- },
- {
- "arrival": {
- "time": 1620707250
- },
- "departure": {
- "time": 1620707250
- },
- "stop_id": "A49N"
- },
- {
- "arrival": {
- "time": 1620707340
- },
- "departure": {
- "time": 1620707340
- },
- "stop_id": "A48N"
- },
- {
- "arrival": {
- "time": 1620707430
- },
- "departure": {
- "time": 1620707430
- },
- "stop_id": "A47N"
- },
- {
- "arrival": {
- "time": 1620707520
- },
- "departure": {
- "time": 1620707520
- },
- "stop_id": "A46N"
- },
- {
- "arrival": {
- "time": 1620707580
- },
- "departure": {
- "time": 1620707580
- },
- "stop_id": "A45N"
- },
- {
- "arrival": {
- "time": 1620707670
- },
- "departure": {
- "time": 1620707670
- },
- "stop_id": "A44N"
- },
- {
- "arrival": {
- "time": 1620707760
- },
- "departure": {
- "time": 1620707760
- },
- "stop_id": "A43N"
- },
- {
- "arrival": {
- "time": 1620707850
- },
- "departure": {
- "time": 1620707850
- },
- "stop_id": "A42N"
- },
- {
- "arrival": {
- "time": 1620707955
- },
- "departure": {
- "time": 1620707955
- },
- "stop_id": "A41N"
- },
- {
- "arrival": {
- "time": 1620708090
- },
- "departure": {
- "time": 1620708090
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620708270
- },
- "departure": {
- "time": 1620708270
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620708570
- },
- "departure": {
- "time": 1620708570
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620708690
- },
- "departure": {
- "time": 1620708690
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620708810
- },
- "departure": {
- "time": 1620708810
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620708900
- },
- "departure": {
- "time": 1620708900
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620709020
- },
- "departure": {
- "time": 1620709020
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620709080
- },
- "departure": {
- "time": 1620709080
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620709170
- },
- "departure": {
- "time": 1620709170
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620709335
- },
- "departure": {
- "time": 1620709335
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620709470
- },
- "departure": {
- "time": 1620709470
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620709560
- },
- "departure": {
- "time": 1620709560
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620709650
- },
- "departure": {
- "time": 1620709650
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620709740
- },
- "departure": {
- "time": 1620709740
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620709830
- },
- "departure": {
- "time": 1620709830
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620709890
- },
- "departure": {
- "time": 1620709890
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620709980
- },
- "departure": {
- "time": 1620709980
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620710130
- },
- "departure": {
- "time": 1620710130
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620710280
- },
- "departure": {
- "time": 1620710280
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620710370
- },
- "departure": {
- "time": 1620710370
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620710460
- },
- "departure": {
- "time": 1620710460
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620710550
- },
- "departure": {
- "time": 1620710550
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620710640
- },
- "departure": {
- "time": 1620710640
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000032A",
- "vehicle": {
- "trip": {
- "trip_id": "000800_A..N",
- "start_time": "00:08:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620706080,
- "stop_id": "A65N"
- }
- },
- {
- "id": "000033A",
- "trip_update": {
- "trip": {
- "trip_id": "000900_A..S",
- "start_time": "00:09:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706140
- },
- "departure": {
- "time": 1620706140
- },
- "stop_id": "A02S"
- },
- {
- "arrival": {
- "time": 1620706230
- },
- "departure": {
- "time": 1620706230
- },
- "stop_id": "A03S"
- },
- {
- "arrival": {
- "time": 1620706350
- },
- "departure": {
- "time": 1620706350
- },
- "stop_id": "A05S"
- },
- {
- "arrival": {
- "time": 1620706470
- },
- "departure": {
- "time": 1620706470
- },
- "stop_id": "A06S"
- },
- {
- "arrival": {
- "time": 1620706530
- },
- "departure": {
- "time": 1620706530
- },
- "stop_id": "A07S"
- },
- {
- "arrival": {
- "time": 1620706650
- },
- "departure": {
- "time": 1620706650
- },
- "stop_id": "A09S"
- }
- ]
- }
- },
- {
- "id": "000034A",
- "vehicle": {
- "trip": {
- "trip_id": "000900_A..S",
- "start_time": "00:09:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620706140,
- "stop_id": "A02S"
- }
- },
- {
- "id": "000035A",
- "trip_update": {
- "trip": {
- "trip_id": "000200_A..N",
- "start_time": "00:02:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705720
- },
- "departure": {
- "time": 1620705720
- },
- "stop_id": "H11N"
- },
- {
- "arrival": {
- "time": 1620705810
- },
- "departure": {
- "time": 1620705810
- },
- "stop_id": "H10N"
- },
- {
- "arrival": {
- "time": 1620705930
- },
- "departure": {
- "time": 1620705930
- },
- "stop_id": "H09N"
- },
- {
- "arrival": {
- "time": 1620706020
- },
- "departure": {
- "time": 1620706020
- },
- "stop_id": "H08N"
- },
- {
- "arrival": {
- "time": 1620706140
- },
- "departure": {
- "time": 1620706140
- },
- "stop_id": "H07N"
- },
- {
- "arrival": {
- "time": 1620706230
- },
- "departure": {
- "time": 1620706230
- },
- "stop_id": "H06N"
- },
- {
- "arrival": {
- "time": 1620706470
- },
- "departure": {
- "time": 1620706470
- },
- "stop_id": "H04N"
- },
- {
- "arrival": {
- "time": 1620706860
- },
- "departure": {
- "time": 1620706860
- },
- "stop_id": "H03N"
- },
- {
- "arrival": {
- "time": 1620706980
- },
- "departure": {
- "time": 1620706980
- },
- "stop_id": "H02N"
- },
- {
- "arrival": {
- "time": 1620707040
- },
- "departure": {
- "time": 1620707040
- },
- "stop_id": "H01N"
- },
- {
- "arrival": {
- "time": 1620707220
- },
- "departure": {
- "time": 1620707220
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620707310
- },
- "departure": {
- "time": 1620707310
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620707400
- },
- "departure": {
- "time": 1620707400
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620707490
- },
- "departure": {
- "time": 1620707490
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620707580
- },
- "departure": {
- "time": 1620707580
- },
- "stop_id": "A55N"
- },
- {
- "arrival": {
- "time": 1620707670
- },
- "departure": {
- "time": 1620707670
- },
- "stop_id": "A54N"
- },
- {
- "arrival": {
- "time": 1620707760
- },
- "departure": {
- "time": 1620707760
- },
- "stop_id": "A53N"
- },
- {
- "arrival": {
- "time": 1620707850
- },
- "departure": {
- "time": 1620707850
- },
- "stop_id": "A52N"
- },
- {
- "arrival": {
- "time": 1620707970
- },
- "departure": {
- "time": 1620707970
- },
- "stop_id": "A51N"
- },
- {
- "arrival": {
- "time": 1620708030
- },
- "departure": {
- "time": 1620708030
- },
- "stop_id": "A50N"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "A49N"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "A48N"
- },
- {
- "arrival": {
- "time": 1620708330
- },
- "departure": {
- "time": 1620708330
- },
- "stop_id": "A47N"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "A46N"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "A45N"
- },
- {
- "arrival": {
- "time": 1620708570
- },
- "departure": {
- "time": 1620708570
- },
- "stop_id": "A44N"
- },
- {
- "arrival": {
- "time": 1620708660
- },
- "departure": {
- "time": 1620708660
- },
- "stop_id": "A43N"
- },
- {
- "arrival": {
- "time": 1620708750
- },
- "departure": {
- "time": 1620708750
- },
- "stop_id": "A42N"
- },
- {
- "arrival": {
- "time": 1620708855
- },
- "departure": {
- "time": 1620708855
- },
- "stop_id": "A41N"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620709170
- },
- "departure": {
- "time": 1620709170
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620709290
- },
- "departure": {
- "time": 1620709290
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620709380
- },
- "departure": {
- "time": 1620709380
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620709470
- },
- "departure": {
- "time": 1620709470
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620709590
- },
- "departure": {
- "time": 1620709590
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620709710
- },
- "departure": {
- "time": 1620709710
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620709800
- },
- "departure": {
- "time": 1620709800
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620709920
- },
- "departure": {
- "time": 1620709920
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620709980
- },
- "departure": {
- "time": 1620709980
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620710070
- },
- "departure": {
- "time": 1620710070
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620710235
- },
- "departure": {
- "time": 1620710235
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620710370
- },
- "departure": {
- "time": 1620710370
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620710460
- },
- "departure": {
- "time": 1620710460
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620710550
- },
- "departure": {
- "time": 1620710550
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620710640
- },
- "departure": {
- "time": 1620710640
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620710730
- },
- "departure": {
- "time": 1620710730
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620710790
- },
- "departure": {
- "time": 1620710790
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620711030
- },
- "departure": {
- "time": 1620711030
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620711180
- },
- "departure": {
- "time": 1620711180
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620711270
- },
- "departure": {
- "time": 1620711270
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620711360
- },
- "departure": {
- "time": 1620711360
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620711450
- },
- "departure": {
- "time": 1620711450
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620711540
- },
- "departure": {
- "time": 1620711540
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000036A",
- "vehicle": {
- "trip": {
- "trip_id": "000200_A..N",
- "start_time": "00:02:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620705720,
- "stop_id": "H11N"
- }
- },
- {
- "id": "000037A",
- "trip_update": {
- "trip": {
- "trip_id": "002000_A..N",
- "start_time": "00:20:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706800
- },
- "departure": {
- "time": 1620706800
- },
- "stop_id": "A65N"
- },
- {
- "arrival": {
- "time": 1620706890
- },
- "departure": {
- "time": 1620706890
- },
- "stop_id": "A64N"
- },
- {
- "arrival": {
- "time": 1620706950
- },
- "departure": {
- "time": 1620706950
- },
- "stop_id": "A63N"
- },
- {
- "arrival": {
- "time": 1620707040
- },
- "departure": {
- "time": 1620707040
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620707130
- },
- "departure": {
- "time": 1620707130
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620707220
- },
- "departure": {
- "time": 1620707220
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620707310
- },
- "departure": {
- "time": 1620707310
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620707400
- },
- "departure": {
- "time": 1620707400
- },
- "stop_id": "A55N"
- }
- ]
- }
- },
- {
- "id": "000038A",
- "vehicle": {
- "trip": {
- "trip_id": "002000_A..N",
- "start_time": "00:20:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620706800,
- "stop_id": "A65N"
- }
- },
- {
- "id": "000039A",
- "trip_update": {
- "trip": {
- "trip_id": "001900_A..S",
- "start_time": "00:19:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706740
- },
- "departure": {
- "time": 1620706740
- },
- "stop_id": "A09S"
- },
- {
- "arrival": {
- "time": 1620706800
- },
- "departure": {
- "time": 1620706800
- },
- "stop_id": "A10S"
- },
- {
- "arrival": {
- "time": 1620706860
- },
- "departure": {
- "time": 1620706860
- },
- "stop_id": "A11S"
- },
- {
- "arrival": {
- "time": 1620706950
- },
- "departure": {
- "time": 1620706950
- },
- "stop_id": "A12S"
- },
- {
- "arrival": {
- "time": 1620707070
- },
- "departure": {
- "time": 1620707070
- },
- "stop_id": "A14S"
- },
- {
- "arrival": {
- "time": 1620707160
- },
- "departure": {
- "time": 1620707160
- },
- "stop_id": "A15S"
- },
- {
- "arrival": {
- "time": 1620707250
- },
- "departure": {
- "time": 1620707250
- },
- "stop_id": "A16S"
- },
- {
- "arrival": {
- "time": 1620707340
- },
- "departure": {
- "time": 1620707340
- },
- "stop_id": "A17S"
- },
- {
- "arrival": {
- "time": 1620707400
- },
- "departure": {
- "time": 1620707400
- },
- "stop_id": "A18S"
- },
- {
- "arrival": {
- "time": 1620707490
- },
- "departure": {
- "time": 1620707490
- },
- "stop_id": "A19S"
- },
- {
- "arrival": {
- "time": 1620707580
- },
- "departure": {
- "time": 1620707580
- },
- "stop_id": "A20S"
- },
- {
- "arrival": {
- "time": 1620707670
- },
- "departure": {
- "time": 1620707670
- },
- "stop_id": "A21S"
- },
- {
- "arrival": {
- "time": 1620707760
- },
- "departure": {
- "time": 1620707760
- },
- "stop_id": "A22S"
- },
- {
- "arrival": {
- "time": 1620707910
- },
- "departure": {
- "time": 1620707910
- },
- "stop_id": "A24S"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620708180
- },
- "departure": {
- "time": 1620708180
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620708330
- },
- "departure": {
- "time": 1620708330
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620708630
- },
- "departure": {
- "time": 1620708630
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620708720
- },
- "departure": {
- "time": 1620708720
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620708840
- },
- "departure": {
- "time": 1620708840
- },
- "stop_id": "A36S"
- },
- {
- "arrival": {
- "time": 1620708960
- },
- "departure": {
- "time": 1620708960
- },
- "stop_id": "A38S"
- },
- {
- "arrival": {
- "time": 1620709140
- },
- "departure": {
- "time": 1620709140
- },
- "stop_id": "A40S"
- },
- {
- "arrival": {
- "time": 1620709260
- },
- "departure": {
- "time": 1620709260
- },
- "stop_id": "A41S"
- },
- {
- "arrival": {
- "time": 1620709350
- },
- "departure": {
- "time": 1620709350
- },
- "stop_id": "A42S"
- },
- {
- "arrival": {
- "time": 1620709470
- },
- "departure": {
- "time": 1620709470
- },
- "stop_id": "A43S"
- },
- {
- "arrival": {
- "time": 1620709560
- },
- "departure": {
- "time": 1620709560
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620709650
- },
- "departure": {
- "time": 1620709650
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620709710
- },
- "departure": {
- "time": 1620709710
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620709830
- },
- "departure": {
- "time": 1620709830
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620709920
- },
- "departure": {
- "time": 1620709920
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620710040
- },
- "departure": {
- "time": 1620710040
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620710130
- },
- "departure": {
- "time": 1620710130
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620710220
- },
- "departure": {
- "time": 1620710220
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620710340
- },
- "departure": {
- "time": 1620710340
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620710430
- },
- "departure": {
- "time": 1620710430
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620710520
- },
- "departure": {
- "time": 1620710520
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620710610
- },
- "departure": {
- "time": 1620710610
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620710700
- },
- "departure": {
- "time": 1620710700
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620710790
- },
- "departure": {
- "time": 1620710790
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620710970
- },
- "departure": {
- "time": 1620710970
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620711210
- },
- "departure": {
- "time": 1620711210
- },
- "stop_id": "H02S"
- },
- {
- "arrival": {
- "time": 1620711330
- },
- "departure": {
- "time": 1620711330
- },
- "stop_id": "H03S"
- },
- {
- "arrival": {
- "time": 1620711720
- },
- "departure": {
- "time": 1620711720
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620712080
- },
- "departure": {
- "time": 1620712080
- },
- "stop_id": "H06S"
- },
- {
- "arrival": {
- "time": 1620712395
- },
- "departure": {
- "time": 1620712395
- },
- "stop_id": "H07S"
- },
- {
- "arrival": {
- "time": 1620712620
- },
- "departure": {
- "time": 1620712620
- },
- "stop_id": "H08S"
- },
- {
- "arrival": {
- "time": 1620712710
- },
- "departure": {
- "time": 1620712710
- },
- "stop_id": "H09S"
- },
- {
- "arrival": {
- "time": 1620712830
- },
- "departure": {
- "time": 1620712830
- },
- "stop_id": "H10S"
- },
- {
- "arrival": {
- "time": 1620712920
- },
- "departure": {
- "time": 1620712920
- },
- "stop_id": "H11S"
- }
- ]
- }
- },
- {
- "id": "000040A",
- "vehicle": {
- "trip": {
- "trip_id": "001900_A..S",
- "start_time": "00:19:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620706740,
- "stop_id": "A09S"
- }
- },
- {
- "id": "000041A",
- "trip_update": {
- "trip": {
- "trip_id": "002200_A..N",
- "start_time": "00:22:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706920
- },
- "departure": {
- "time": 1620706920
- },
- "stop_id": "A09N"
- },
- {
- "arrival": {
- "time": 1620707100
- },
- "departure": {
- "time": 1620707100
- },
- "stop_id": "A07N"
- },
- {
- "arrival": {
- "time": 1620707220
- },
- "departure": {
- "time": 1620707220
- },
- "stop_id": "A06N"
- },
- {
- "arrival": {
- "time": 1620707400
- },
- "departure": {
- "time": 1620707400
- },
- "stop_id": "A05N"
- },
- {
- "arrival": {
- "time": 1620707610
- },
- "departure": {
- "time": 1620707610
- },
- "stop_id": "A03N"
- },
- {
- "arrival": {
- "time": 1620707760
- },
- "departure": {
- "time": 1620707760
- },
- "stop_id": "A02N"
- }
- ]
- }
- },
- {
- "id": "000042A",
- "vehicle": {
- "trip": {
- "trip_id": "002200_A..N",
- "start_time": "00:22:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620706920,
- "stop_id": "A09N"
- }
- },
- {
- "id": "000043A",
- "trip_update": {
- "trip": {
- "trip_id": "002200_A..N",
- "start_time": "00:22:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706920
- },
- "departure": {
- "time": 1620706920
- },
- "stop_id": "H11N"
- },
- {
- "arrival": {
- "time": 1620707010
- },
- "departure": {
- "time": 1620707010
- },
- "stop_id": "H10N"
- },
- {
- "arrival": {
- "time": 1620707130
- },
- "departure": {
- "time": 1620707130
- },
- "stop_id": "H09N"
- },
- {
- "arrival": {
- "time": 1620707220
- },
- "departure": {
- "time": 1620707220
- },
- "stop_id": "H08N"
- },
- {
- "arrival": {
- "time": 1620707340
- },
- "departure": {
- "time": 1620707340
- },
- "stop_id": "H07N"
- },
- {
- "arrival": {
- "time": 1620707430
- },
- "departure": {
- "time": 1620707430
- },
- "stop_id": "H06N"
- },
- {
- "arrival": {
- "time": 1620707670
- },
- "departure": {
- "time": 1620707670
- },
- "stop_id": "H04N"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "H03N"
- },
- {
- "arrival": {
- "time": 1620708180
- },
- "departure": {
- "time": 1620708180
- },
- "stop_id": "H02N"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "H01N"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620708510
- },
- "departure": {
- "time": 1620708510
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620708600
- },
- "departure": {
- "time": 1620708600
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620708690
- },
- "departure": {
- "time": 1620708690
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620708780
- },
- "departure": {
- "time": 1620708780
- },
- "stop_id": "A55N"
- },
- {
- "arrival": {
- "time": 1620708870
- },
- "departure": {
- "time": 1620708870
- },
- "stop_id": "A54N"
- },
- {
- "arrival": {
- "time": 1620708960
- },
- "departure": {
- "time": 1620708960
- },
- "stop_id": "A53N"
- },
- {
- "arrival": {
- "time": 1620709050
- },
- "departure": {
- "time": 1620709050
- },
- "stop_id": "A52N"
- },
- {
- "arrival": {
- "time": 1620709170
- },
- "departure": {
- "time": 1620709170
- },
- "stop_id": "A51N"
- },
- {
- "arrival": {
- "time": 1620709230
- },
- "departure": {
- "time": 1620709230
- },
- "stop_id": "A50N"
- },
- {
- "arrival": {
- "time": 1620709350
- },
- "departure": {
- "time": 1620709350
- },
- "stop_id": "A49N"
- },
- {
- "arrival": {
- "time": 1620709440
- },
- "departure": {
- "time": 1620709440
- },
- "stop_id": "A48N"
- },
- {
- "arrival": {
- "time": 1620709530
- },
- "departure": {
- "time": 1620709530
- },
- "stop_id": "A47N"
- },
- {
- "arrival": {
- "time": 1620709620
- },
- "departure": {
- "time": 1620709620
- },
- "stop_id": "A46N"
- },
- {
- "arrival": {
- "time": 1620709680
- },
- "departure": {
- "time": 1620709680
- },
- "stop_id": "A45N"
- },
- {
- "arrival": {
- "time": 1620709770
- },
- "departure": {
- "time": 1620709770
- },
- "stop_id": "A44N"
- },
- {
- "arrival": {
- "time": 1620709860
- },
- "departure": {
- "time": 1620709860
- },
- "stop_id": "A43N"
- },
- {
- "arrival": {
- "time": 1620709950
- },
- "departure": {
- "time": 1620709950
- },
- "stop_id": "A42N"
- },
- {
- "arrival": {
- "time": 1620710040
- },
- "departure": {
- "time": 1620710040
- },
- "stop_id": "A41N"
- },
- {
- "arrival": {
- "time": 1620710160
- },
- "departure": {
- "time": 1620710160
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620710340
- },
- "departure": {
- "time": 1620710340
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620710460
- },
- "departure": {
- "time": 1620710460
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620710550
- },
- "departure": {
- "time": 1620710550
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620710640
- },
- "departure": {
- "time": 1620710640
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620710760
- },
- "departure": {
- "time": 1620710760
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620710970
- },
- "departure": {
- "time": 1620710970
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620711090
- },
- "departure": {
- "time": 1620711090
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620711150
- },
- "departure": {
- "time": 1620711150
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620711240
- },
- "departure": {
- "time": 1620711240
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620711405
- },
- "departure": {
- "time": 1620711405
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620711540
- },
- "departure": {
- "time": 1620711540
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620711630
- },
- "departure": {
- "time": 1620711630
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620711720
- },
- "departure": {
- "time": 1620711720
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620711810
- },
- "departure": {
- "time": 1620711810
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620711900
- },
- "departure": {
- "time": 1620711900
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620711960
- },
- "departure": {
- "time": 1620711960
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620712050
- },
- "departure": {
- "time": 1620712050
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620712200
- },
- "departure": {
- "time": 1620712200
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620712350
- },
- "departure": {
- "time": 1620712350
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620712440
- },
- "departure": {
- "time": 1620712440
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620712530
- },
- "departure": {
- "time": 1620712530
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620712620
- },
- "departure": {
- "time": 1620712620
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620712710
- },
- "departure": {
- "time": 1620712710
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000044A",
- "vehicle": {
- "trip": {
- "trip_id": "002200_A..N",
- "start_time": "00:22:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620706920,
- "stop_id": "H11N"
- }
- },
- {
- "id": "000045A",
- "trip_update": {
- "trip": {
- "trip_id": "003900_A..S",
- "start_time": "00:39:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620707940
- },
- "departure": {
- "time": 1620707940
- },
- "stop_id": "A02S"
- },
- {
- "arrival": {
- "time": 1620708030
- },
- "departure": {
- "time": 1620708030
- },
- "stop_id": "A03S"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "A05S"
- },
- {
- "arrival": {
- "time": 1620708270
- },
- "departure": {
- "time": 1620708270
- },
- "stop_id": "A06S"
- },
- {
- "arrival": {
- "time": 1620708330
- },
- "departure": {
- "time": 1620708330
- },
- "stop_id": "A07S"
- },
- {
- "arrival": {
- "time": 1620708450
- },
- "departure": {
- "time": 1620708450
- },
- "stop_id": "A09S"
- }
- ]
- }
- },
- {
- "id": "000046A",
- "vehicle": {
- "trip": {
- "trip_id": "003900_A..S",
- "start_time": "00:39:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620707940,
- "stop_id": "A02S"
- }
- },
- {
- "id": "000047A",
- "trip_update": {
- "trip": {
- "trip_id": "004000_A..N",
- "start_time": "00:40:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "A65N"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "A64N"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "A63N"
- },
- {
- "arrival": {
- "time": 1620708270
- },
- "departure": {
- "time": 1620708270
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620708330
- },
- "departure": {
- "time": 1620708330
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620708450
- },
- "departure": {
- "time": 1620708450
- },
- "stop_id": "A58N"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620708660
- },
- "departure": {
- "time": 1620708660
- },
- "stop_id": "A55N"
- }
- ]
- }
- },
- {
- "id": "000048A",
- "vehicle": {
- "trip": {
- "trip_id": "004000_A..N",
- "start_time": "00:40:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620708000,
- "stop_id": "A65N"
- }
- },
- {
- "id": "000049A",
- "trip_update": {
- "trip": {
- "trip_id": "003900_A..S",
- "start_time": "00:39:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620707940
- },
- "departure": {
- "time": 1620707940
- },
- "stop_id": "A09S"
- },
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "A10S"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "A11S"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "A12S"
- },
- {
- "arrival": {
- "time": 1620708270
- },
- "departure": {
- "time": 1620708270
- },
- "stop_id": "A14S"
- },
- {
- "arrival": {
- "time": 1620708360
- },
- "departure": {
- "time": 1620708360
- },
- "stop_id": "A15S"
- },
- {
- "arrival": {
- "time": 1620708450
- },
- "departure": {
- "time": 1620708450
- },
- "stop_id": "A16S"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "A17S"
- },
- {
- "arrival": {
- "time": 1620708600
- },
- "departure": {
- "time": 1620708600
- },
- "stop_id": "A18S"
- },
- {
- "arrival": {
- "time": 1620708690
- },
- "departure": {
- "time": 1620708690
- },
- "stop_id": "A19S"
- },
- {
- "arrival": {
- "time": 1620708780
- },
- "departure": {
- "time": 1620708780
- },
- "stop_id": "A20S"
- },
- {
- "arrival": {
- "time": 1620708870
- },
- "departure": {
- "time": 1620708870
- },
- "stop_id": "A21S"
- },
- {
- "arrival": {
- "time": 1620708960
- },
- "departure": {
- "time": 1620708960
- },
- "stop_id": "A22S"
- },
- {
- "arrival": {
- "time": 1620709095
- },
- "departure": {
- "time": 1620709095
- },
- "stop_id": "A24S"
- },
- {
- "arrival": {
- "time": 1620709230
- },
- "departure": {
- "time": 1620709230
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620709350
- },
- "departure": {
- "time": 1620709350
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620709410
- },
- "departure": {
- "time": 1620709410
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620709500
- },
- "departure": {
- "time": 1620709500
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620709590
- },
- "departure": {
- "time": 1620709590
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620709710
- },
- "departure": {
- "time": 1620709710
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620709800
- },
- "departure": {
- "time": 1620709800
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620709890
- },
- "departure": {
- "time": 1620709890
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620710010
- },
- "departure": {
- "time": 1620710010
- },
- "stop_id": "A36S"
- },
- {
- "arrival": {
- "time": 1620710130
- },
- "departure": {
- "time": 1620710130
- },
- "stop_id": "A38S"
- },
- {
- "arrival": {
- "time": 1620710310
- },
- "departure": {
- "time": 1620710310
- },
- "stop_id": "A40S"
- },
- {
- "arrival": {
- "time": 1620710445
- },
- "departure": {
- "time": 1620710445
- },
- "stop_id": "A41S"
- },
- {
- "arrival": {
- "time": 1620710550
- },
- "departure": {
- "time": 1620710550
- },
- "stop_id": "A42S"
- },
- {
- "arrival": {
- "time": 1620710670
- },
- "departure": {
- "time": 1620710670
- },
- "stop_id": "A43S"
- },
- {
- "arrival": {
- "time": 1620710760
- },
- "departure": {
- "time": 1620710760
- },
- "stop_id": "A44S"
- },
- {
- "arrival": {
- "time": 1620710850
- },
- "departure": {
- "time": 1620710850
- },
- "stop_id": "A45S"
- },
- {
- "arrival": {
- "time": 1620710910
- },
- "departure": {
- "time": 1620710910
- },
- "stop_id": "A46S"
- },
- {
- "arrival": {
- "time": 1620711030
- },
- "departure": {
- "time": 1620711030
- },
- "stop_id": "A47S"
- },
- {
- "arrival": {
- "time": 1620711120
- },
- "departure": {
- "time": 1620711120
- },
- "stop_id": "A48S"
- },
- {
- "arrival": {
- "time": 1620711240
- },
- "departure": {
- "time": 1620711240
- },
- "stop_id": "A49S"
- },
- {
- "arrival": {
- "time": 1620711330
- },
- "departure": {
- "time": 1620711330
- },
- "stop_id": "A50S"
- },
- {
- "arrival": {
- "time": 1620711420
- },
- "departure": {
- "time": 1620711420
- },
- "stop_id": "A51S"
- },
- {
- "arrival": {
- "time": 1620711540
- },
- "departure": {
- "time": 1620711540
- },
- "stop_id": "A52S"
- },
- {
- "arrival": {
- "time": 1620711630
- },
- "departure": {
- "time": 1620711630
- },
- "stop_id": "A53S"
- },
- {
- "arrival": {
- "time": 1620711720
- },
- "departure": {
- "time": 1620711720
- },
- "stop_id": "A54S"
- },
- {
- "arrival": {
- "time": 1620711810
- },
- "departure": {
- "time": 1620711810
- },
- "stop_id": "A55S"
- },
- {
- "arrival": {
- "time": 1620711900
- },
- "departure": {
- "time": 1620711900
- },
- "stop_id": "A57S"
- },
- {
- "arrival": {
- "time": 1620711990
- },
- "departure": {
- "time": 1620711990
- },
- "stop_id": "A59S"
- },
- {
- "arrival": {
- "time": 1620712080
- },
- "departure": {
- "time": 1620712080
- },
- "stop_id": "A60S"
- },
- {
- "arrival": {
- "time": 1620712170
- },
- "departure": {
- "time": 1620712170
- },
- "stop_id": "A61S"
- },
- {
- "arrival": {
- "time": 1620712410
- },
- "departure": {
- "time": 1620712410
- },
- "stop_id": "H02S"
- },
- {
- "arrival": {
- "time": 1620712530
- },
- "departure": {
- "time": 1620712530
- },
- "stop_id": "H03S"
- },
- {
- "arrival": {
- "time": 1620712920
- },
- "departure": {
- "time": 1620712920
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620713280
- },
- "departure": {
- "time": 1620713280
- },
- "stop_id": "H06S"
- },
- {
- "arrival": {
- "time": 1620713595
- },
- "departure": {
- "time": 1620713595
- },
- "stop_id": "H07S"
- },
- {
- "arrival": {
- "time": 1620713820
- },
- "departure": {
- "time": 1620713820
- },
- "stop_id": "H08S"
- },
- {
- "arrival": {
- "time": 1620713910
- },
- "departure": {
- "time": 1620713910
- },
- "stop_id": "H09S"
- },
- {
- "arrival": {
- "time": 1620714030
- },
- "departure": {
- "time": 1620714030
- },
- "stop_id": "H10S"
- },
- {
- "arrival": {
- "time": 1620714120
- },
- "departure": {
- "time": 1620714120
- },
- "stop_id": "H11S"
- }
- ]
- }
- },
- {
- "id": "000050A",
- "vehicle": {
- "trip": {
- "trip_id": "003900_A..S",
- "start_time": "00:39:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620707940,
- "stop_id": "A09S"
- }
- },
- {
- "id": "000051A",
- "trip_update": {
- "trip": {
- "trip_id": "005200_A..N",
- "start_time": "00:52:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708720
- },
- "departure": {
- "time": 1620708720
- },
- "stop_id": "A09N"
- },
- {
- "arrival": {
- "time": 1620708900
- },
- "departure": {
- "time": 1620708900
- },
- "stop_id": "A07N"
- },
- {
- "arrival": {
- "time": 1620709020
- },
- "departure": {
- "time": 1620709020
- },
- "stop_id": "A06N"
- },
- {
- "arrival": {
- "time": 1620709200
- },
- "departure": {
- "time": 1620709200
- },
- "stop_id": "A05N"
- },
- {
- "arrival": {
- "time": 1620709410
- },
- "departure": {
- "time": 1620709410
- },
- "stop_id": "A03N"
- },
- {
- "arrival": {
- "time": 1620709560
- },
- "departure": {
- "time": 1620709560
- },
- "stop_id": "A02N"
- }
- ]
- }
- },
- {
- "id": "000052A",
- "vehicle": {
- "trip": {
- "trip_id": "005200_A..N",
- "start_time": "00:52:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620708720,
- "stop_id": "A09N"
- }
- },
- {
- "id": "000053A",
- "trip_update": {
- "trip": {
- "trip_id": "004200_A..N",
- "start_time": "00:42:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708120
- },
- "departure": {
- "time": 1620708120
- },
- "stop_id": "H11N"
- },
- {
- "arrival": {
- "time": 1620708210
- },
- "departure": {
- "time": 1620708210
- },
- "stop_id": "H10N"
- },
- {
- "arrival": {
- "time": 1620708330
- },
- "departure": {
- "time": 1620708330
- },
- "stop_id": "H09N"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "H08N"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "H07N"
- },
- {
- "arrival": {
- "time": 1620708630
- },
- "departure": {
- "time": 1620708630
- },
- "stop_id": "H06N"
- },
- {
- "arrival": {
- "time": 1620708870
- },
- "departure": {
- "time": 1620708870
- },
- "stop_id": "H04N"
- },
- {
- "arrival": {
- "time": 1620709260
- },
- "departure": {
- "time": 1620709260
- },
- "stop_id": "H03N"
- },
- {
- "arrival": {
- "time": 1620709380
- },
- "departure": {
- "time": 1620709380
- },
- "stop_id": "H02N"
- },
- {
- "arrival": {
- "time": 1620709440
- },
- "departure": {
- "time": 1620709440
- },
- "stop_id": "H01N"
- },
- {
- "arrival": {
- "time": 1620709620
- },
- "departure": {
- "time": 1620709620
- },
- "stop_id": "A61N"
- },
- {
- "arrival": {
- "time": 1620709710
- },
- "departure": {
- "time": 1620709710
- },
- "stop_id": "A60N"
- },
- {
- "arrival": {
- "time": 1620709800
- },
- "departure": {
- "time": 1620709800
- },
- "stop_id": "A59N"
- },
- {
- "arrival": {
- "time": 1620709890
- },
- "departure": {
- "time": 1620709890
- },
- "stop_id": "A57N"
- },
- {
- "arrival": {
- "time": 1620709980
- },
- "departure": {
- "time": 1620709980
- },
- "stop_id": "A55N"
- },
- {
- "arrival": {
- "time": 1620710070
- },
- "departure": {
- "time": 1620710070
- },
- "stop_id": "A54N"
- },
- {
- "arrival": {
- "time": 1620710160
- },
- "departure": {
- "time": 1620710160
- },
- "stop_id": "A53N"
- },
- {
- "arrival": {
- "time": 1620710250
- },
- "departure": {
- "time": 1620710250
- },
- "stop_id": "A52N"
- },
- {
- "arrival": {
- "time": 1620710370
- },
- "departure": {
- "time": 1620710370
- },
- "stop_id": "A51N"
- },
- {
- "arrival": {
- "time": 1620710430
- },
- "departure": {
- "time": 1620710430
- },
- "stop_id": "A50N"
- },
- {
- "arrival": {
- "time": 1620710550
- },
- "departure": {
- "time": 1620710550
- },
- "stop_id": "A49N"
- },
- {
- "arrival": {
- "time": 1620710640
- },
- "departure": {
- "time": 1620710640
- },
- "stop_id": "A48N"
- },
- {
- "arrival": {
- "time": 1620710730
- },
- "departure": {
- "time": 1620710730
- },
- "stop_id": "A47N"
- },
- {
- "arrival": {
- "time": 1620710820
- },
- "departure": {
- "time": 1620710820
- },
- "stop_id": "A46N"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "A45N"
- },
- {
- "arrival": {
- "time": 1620710970
- },
- "departure": {
- "time": 1620710970
- },
- "stop_id": "A44N"
- },
- {
- "arrival": {
- "time": 1620711060
- },
- "departure": {
- "time": 1620711060
- },
- "stop_id": "A43N"
- },
- {
- "arrival": {
- "time": 1620711150
- },
- "departure": {
- "time": 1620711150
- },
- "stop_id": "A42N"
- },
- {
- "arrival": {
- "time": 1620711240
- },
- "departure": {
- "time": 1620711240
- },
- "stop_id": "A41N"
- },
- {
- "arrival": {
- "time": 1620711360
- },
- "departure": {
- "time": 1620711360
- },
- "stop_id": "A40N"
- },
- {
- "arrival": {
- "time": 1620711540
- },
- "departure": {
- "time": 1620711540
- },
- "stop_id": "A38N"
- },
- {
- "arrival": {
- "time": 1620711660
- },
- "departure": {
- "time": 1620711660
- },
- "stop_id": "A36N"
- },
- {
- "arrival": {
- "time": 1620711750
- },
- "departure": {
- "time": 1620711750
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620711840
- },
- "departure": {
- "time": 1620711840
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620711960
- },
- "departure": {
- "time": 1620711960
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620712080
- },
- "departure": {
- "time": 1620712080
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620712170
- },
- "departure": {
- "time": 1620712170
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620712290
- },
- "departure": {
- "time": 1620712290
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620712350
- },
- "departure": {
- "time": 1620712350
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620712440
- },
- "departure": {
- "time": 1620712440
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620712605
- },
- "departure": {
- "time": 1620712605
- },
- "stop_id": "A24N"
- },
- {
- "arrival": {
- "time": 1620712740
- },
- "departure": {
- "time": 1620712740
- },
- "stop_id": "A22N"
- },
- {
- "arrival": {
- "time": 1620712830
- },
- "departure": {
- "time": 1620712830
- },
- "stop_id": "A21N"
- },
- {
- "arrival": {
- "time": 1620712920
- },
- "departure": {
- "time": 1620712920
- },
- "stop_id": "A20N"
- },
- {
- "arrival": {
- "time": 1620713010
- },
- "departure": {
- "time": 1620713010
- },
- "stop_id": "A19N"
- },
- {
- "arrival": {
- "time": 1620713100
- },
- "departure": {
- "time": 1620713100
- },
- "stop_id": "A18N"
- },
- {
- "arrival": {
- "time": 1620713160
- },
- "departure": {
- "time": 1620713160
- },
- "stop_id": "A17N"
- },
- {
- "arrival": {
- "time": 1620713250
- },
- "departure": {
- "time": 1620713250
- },
- "stop_id": "A16N"
- },
- {
- "arrival": {
- "time": 1620713400
- },
- "departure": {
- "time": 1620713400
- },
- "stop_id": "A15N"
- },
- {
- "arrival": {
- "time": 1620713550
- },
- "departure": {
- "time": 1620713550
- },
- "stop_id": "A14N"
- },
- {
- "arrival": {
- "time": 1620713640
- },
- "departure": {
- "time": 1620713640
- },
- "stop_id": "A12N"
- },
- {
- "arrival": {
- "time": 1620713730
- },
- "departure": {
- "time": 1620713730
- },
- "stop_id": "A11N"
- },
- {
- "arrival": {
- "time": 1620713820
- },
- "departure": {
- "time": 1620713820
- },
- "stop_id": "A10N"
- },
- {
- "arrival": {
- "time": 1620713910
- },
- "departure": {
- "time": 1620713910
- },
- "stop_id": "A09N"
- }
- ]
- }
- },
- {
- "id": "000054A",
- "vehicle": {
- "trip": {
- "trip_id": "004200_A..N",
- "start_time": "00:42:00",
- "start_date": "20210511",
- "route_id": "A"
- },
- "timestamp": 1620708120,
- "stop_id": "H11N"
- }
- },
- {
- "id": "000001E",
- "trip_update": {
- "trip": {
- "trip_id": "138400_E..N",
- "start_time": "23:04:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620705661
- },
- "departure": {
- "time": 1620705661
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000002E",
- "vehicle": {
- "trip": {
- "trip_id": "138400_E..N",
- "start_time": "23:04:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 25,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "G06N"
- }
- },
- {
- "id": "000003E",
- "trip_update": {
- "trip": {
- "trip_id": "137400_E..S",
- "start_time": "22:54:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705446
- },
- "departure": {
- "time": 1620705446
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000004E",
- "vehicle": {
- "trip": {
- "trip_id": "137400_E..S",
- "start_time": "22:54:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 31,
- "current_status": 1,
- "timestamp": 1620705446,
- "stop_id": "E01S"
- }
- },
- {
- "id": "000005E",
- "trip_update": {
- "trip": {
- "trip_id": "139600_E..N",
- "start_time": "23:16:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620705728
- },
- "departure": {
- "time": 1620705728
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620706223
- },
- "departure": {
- "time": 1620706223
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620706478
- },
- "departure": {
- "time": 1620706478
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000006E",
- "vehicle": {
- "trip": {
- "trip_id": "139600_E..N",
- "start_time": "23:16:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 19,
- "current_status": 1,
- "timestamp": 1620705216,
- "stop_id": "G14N"
- }
- },
- {
- "id": "000007E",
- "trip_update": {
- "trip": {
- "trip_id": "138486_E..S",
- "start_time": "23:04:52",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620705638
- },
- "departure": {
- "time": 1620705638
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000008E",
- "vehicle": {
- "trip": {
- "trip_id": "138486_E..S",
- "start_time": "23:04:52",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 29,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A33S"
- }
- },
- {
- "id": "000009E",
- "trip_update": {
- "trip": {
- "trip_id": "139660_E..S",
- "start_time": "23:16:36",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620705758
- },
- "departure": {
- "time": 1620705758
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620705938
- },
- "departure": {
- "time": 1620705938
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620706058
- },
- "departure": {
- "time": 1620706058
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620706148
- },
- "departure": {
- "time": 1620706148
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620706358
- },
- "departure": {
- "time": 1620706358
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000010E",
- "vehicle": {
- "trip": {
- "trip_id": "139660_E..S",
- "start_time": "23:16:36",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 22,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "D14S"
- }
- },
- {
- "id": "000011E",
- "trip_update": {
- "trip": {
- "trip_id": "140800_E..N",
- "start_time": "23:28:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620705578
- },
- "departure": {
- "time": 1620705578
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620705668
- },
- "departure": {
- "time": 1620705668
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620705758
- },
- "departure": {
- "time": 1620705758
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620705848
- },
- "departure": {
- "time": 1620705848
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620705968
- },
- "departure": {
- "time": 1620705968
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620706148
- },
- "departure": {
- "time": 1620706148
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620706238
- },
- "departure": {
- "time": 1620706238
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620706358
- },
- "departure": {
- "time": 1620706358
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620706448
- },
- "departure": {
- "time": 1620706448
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620706568
- },
- "departure": {
- "time": 1620706568
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620706658
- },
- "departure": {
- "time": 1620706658
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620706943
- },
- "departure": {
- "time": 1620706943
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620707198
- },
- "departure": {
- "time": 1620707198
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000012E",
- "vehicle": {
- "trip": {
- "trip_id": "140800_E..N",
- "start_time": "23:28:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 16,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "G18N"
- }
- },
- {
- "id": "000013E",
- "trip_update": {
- "trip": {
- "trip_id": "140800_E..S",
- "start_time": "23:28:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "G20S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "G21S"
- },
- {
- "arrival": {
- "time": 1620705623
- },
- "departure": {
- "time": 1620705623
- },
- "stop_id": "F09S"
- },
- {
- "arrival": {
- "time": 1620705803
- },
- "departure": {
- "time": 1620705803
- },
- "stop_id": "F11S"
- },
- {
- "arrival": {
- "time": 1620705893
- },
- "departure": {
- "time": 1620705893
- },
- "stop_id": "F12S"
- },
- {
- "arrival": {
- "time": 1620705983
- },
- "departure": {
- "time": 1620705983
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620706133
- },
- "departure": {
- "time": 1620706133
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620706313
- },
- "departure": {
- "time": 1620706313
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620706373
- },
- "departure": {
- "time": 1620706373
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620706463
- },
- "departure": {
- "time": 1620706463
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620706553
- },
- "departure": {
- "time": 1620706553
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620706673
- },
- "departure": {
- "time": 1620706673
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620706763
- },
- "departure": {
- "time": 1620706763
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620706853
- },
- "departure": {
- "time": 1620706853
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620706973
- },
- "departure": {
- "time": 1620706973
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000014E",
- "vehicle": {
- "trip": {
- "trip_id": "140800_E..S",
- "start_time": "23:28:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 17,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "G20S"
- }
- },
- {
- "id": "000015E",
- "trip_update": {
- "trip": {
- "trip_id": "141800_E..N",
- "start_time": "23:38:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620705908
- },
- "departure": {
- "time": 1620705908
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620706028
- },
- "departure": {
- "time": 1620706028
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620706118
- },
- "departure": {
- "time": 1620706118
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620706208
- },
- "departure": {
- "time": 1620706208
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620706268
- },
- "departure": {
- "time": 1620706268
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620706358
- },
- "departure": {
- "time": 1620706358
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620706448
- },
- "departure": {
- "time": 1620706448
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620706538
- },
- "departure": {
- "time": 1620706538
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620706658
- },
- "departure": {
- "time": 1620706658
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620706718
- },
- "departure": {
- "time": 1620706718
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620706838
- },
- "departure": {
- "time": 1620706838
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620706928
- },
- "departure": {
- "time": 1620706928
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620707048
- },
- "departure": {
- "time": 1620707048
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620707138
- },
- "departure": {
- "time": 1620707138
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620707258
- },
- "departure": {
- "time": 1620707258
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620707348
- },
- "departure": {
- "time": 1620707348
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620707678
- },
- "departure": {
- "time": 1620707678
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620707978
- },
- "departure": {
- "time": 1620707978
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000016E",
- "vehicle": {
- "trip": {
- "trip_id": "141800_E..N",
- "start_time": "23:38:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 10,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "F12N"
- }
- },
- {
- "id": "000017E",
- "trip_update": {
- "trip": {
- "trip_id": "142328_E..S",
- "start_time": "23:43:17",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "G11S"
- },
- {
- "arrival": {
- "time": 1620705518
- },
- "departure": {
- "time": 1620705518
- },
- "stop_id": "G12S"
- },
- {
- "arrival": {
- "time": 1620705608
- },
- "departure": {
- "time": 1620705608
- },
- "stop_id": "G13S"
- },
- {
- "arrival": {
- "time": 1620705698
- },
- "departure": {
- "time": 1620705698
- },
- "stop_id": "G14S"
- },
- {
- "arrival": {
- "time": 1620705788
- },
- "departure": {
- "time": 1620705788
- },
- "stop_id": "G15S"
- },
- {
- "arrival": {
- "time": 1620705878
- },
- "departure": {
- "time": 1620705878
- },
- "stop_id": "G16S"
- },
- {
- "arrival": {
- "time": 1620705968
- },
- "departure": {
- "time": 1620705968
- },
- "stop_id": "G18S"
- },
- {
- "arrival": {
- "time": 1620706058
- },
- "departure": {
- "time": 1620706058
- },
- "stop_id": "G19S"
- },
- {
- "arrival": {
- "time": 1620706178
- },
- "departure": {
- "time": 1620706178
- },
- "stop_id": "G20S"
- },
- {
- "arrival": {
- "time": 1620706298
- },
- "departure": {
- "time": 1620706298
- },
- "stop_id": "G21S"
- },
- {
- "arrival": {
- "time": 1620706388
- },
- "departure": {
- "time": 1620706388
- },
- "stop_id": "F09S"
- },
- {
- "arrival": {
- "time": 1620706568
- },
- "departure": {
- "time": 1620706568
- },
- "stop_id": "F11S"
- },
- {
- "arrival": {
- "time": 1620706658
- },
- "departure": {
- "time": 1620706658
- },
- "stop_id": "F12S"
- },
- {
- "arrival": {
- "time": 1620706748
- },
- "departure": {
- "time": 1620706748
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620706913
- },
- "departure": {
- "time": 1620706913
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620707108
- },
- "departure": {
- "time": 1620707108
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620707168
- },
- "departure": {
- "time": 1620707168
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620707258
- },
- "departure": {
- "time": 1620707258
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620707348
- },
- "departure": {
- "time": 1620707348
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620707468
- },
- "departure": {
- "time": 1620707468
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620707558
- },
- "departure": {
- "time": 1620707558
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620707648
- },
- "departure": {
- "time": 1620707648
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620707768
- },
- "departure": {
- "time": 1620707768
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000018E",
- "vehicle": {
- "trip": {
- "trip_id": "142328_E..S",
- "start_time": "23:43:17",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 9,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "G11S"
- }
- },
- {
- "id": "000019E",
- "trip_update": {
- "trip": {
- "trip_id": "143800_E..S",
- "start_time": "23:58:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705480
- },
- "departure": {
- "time": 1620705480
- },
- "stop_id": "G05S"
- },
- {
- "arrival": {
- "time": 1620705570
- },
- "departure": {
- "time": 1620705570
- },
- "stop_id": "G06S"
- },
- {
- "arrival": {
- "time": 1620705720
- },
- "departure": {
- "time": 1620705720
- },
- "stop_id": "G07S"
- },
- {
- "arrival": {
- "time": 1620705810
- },
- "departure": {
- "time": 1620705810
- },
- "stop_id": "F05S"
- },
- {
- "arrival": {
- "time": 1620705900
- },
- "departure": {
- "time": 1620705900
- },
- "stop_id": "F06S"
- },
- {
- "arrival": {
- "time": 1620705990
- },
- "departure": {
- "time": 1620705990
- },
- "stop_id": "F07S"
- },
- {
- "arrival": {
- "time": 1620706080
- },
- "departure": {
- "time": 1620706080
- },
- "stop_id": "G08S"
- },
- {
- "arrival": {
- "time": 1620706170
- },
- "departure": {
- "time": 1620706170
- },
- "stop_id": "G09S"
- },
- {
- "arrival": {
- "time": 1620706290
- },
- "departure": {
- "time": 1620706290
- },
- "stop_id": "G10S"
- },
- {
- "arrival": {
- "time": 1620706350
- },
- "departure": {
- "time": 1620706350
- },
- "stop_id": "G11S"
- },
- {
- "arrival": {
- "time": 1620706470
- },
- "departure": {
- "time": 1620706470
- },
- "stop_id": "G12S"
- },
- {
- "arrival": {
- "time": 1620706560
- },
- "departure": {
- "time": 1620706560
- },
- "stop_id": "G13S"
- },
- {
- "arrival": {
- "time": 1620706650
- },
- "departure": {
- "time": 1620706650
- },
- "stop_id": "G14S"
- },
- {
- "arrival": {
- "time": 1620706740
- },
- "departure": {
- "time": 1620706740
- },
- "stop_id": "G15S"
- },
- {
- "arrival": {
- "time": 1620706830
- },
- "departure": {
- "time": 1620706830
- },
- "stop_id": "G16S"
- },
- {
- "arrival": {
- "time": 1620706920
- },
- "departure": {
- "time": 1620706920
- },
- "stop_id": "G18S"
- },
- {
- "arrival": {
- "time": 1620707010
- },
- "departure": {
- "time": 1620707010
- },
- "stop_id": "G19S"
- },
- {
- "arrival": {
- "time": 1620707130
- },
- "departure": {
- "time": 1620707130
- },
- "stop_id": "G20S"
- },
- {
- "arrival": {
- "time": 1620707250
- },
- "departure": {
- "time": 1620707250
- },
- "stop_id": "G21S"
- },
- {
- "arrival": {
- "time": 1620707340
- },
- "departure": {
- "time": 1620707340
- },
- "stop_id": "F09S"
- },
- {
- "arrival": {
- "time": 1620707520
- },
- "departure": {
- "time": 1620707520
- },
- "stop_id": "F11S"
- },
- {
- "arrival": {
- "time": 1620707610
- },
- "departure": {
- "time": 1620707610
- },
- "stop_id": "F12S"
- },
- {
- "arrival": {
- "time": 1620707700
- },
- "departure": {
- "time": 1620707700
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620707865
- },
- "departure": {
- "time": 1620707865
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620708120
- },
- "departure": {
- "time": 1620708120
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620708210
- },
- "departure": {
- "time": 1620708210
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620708300
- },
- "departure": {
- "time": 1620708300
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620708510
- },
- "departure": {
- "time": 1620708510
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620708600
- },
- "departure": {
- "time": 1620708600
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620708720
- },
- "departure": {
- "time": 1620708720
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000020E",
- "vehicle": {
- "trip": {
- "trip_id": "143800_E..S",
- "start_time": "23:58:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_status": 0,
- "timestamp": 1620705480,
- "stop_id": "G05S"
- }
- },
- {
- "id": "000021E",
- "trip_update": {
- "trip": {
- "trip_id": "000200_E..N",
- "start_time": "00:02:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705720
- },
- "departure": {
- "time": 1620705720
- },
- "stop_id": "E01N"
- },
- {
- "arrival": {
- "time": 1620705840
- },
- "departure": {
- "time": 1620705840
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620705930
- },
- "departure": {
- "time": 1620705930
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620706050
- },
- "departure": {
- "time": 1620706050
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620706170
- },
- "departure": {
- "time": 1620706170
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620706260
- },
- "departure": {
- "time": 1620706260
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620706380
- },
- "departure": {
- "time": 1620706380
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620706440
- },
- "departure": {
- "time": 1620706440
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620706560
- },
- "departure": {
- "time": 1620706560
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620706650
- },
- "departure": {
- "time": 1620706650
- },
- "stop_id": "D14N"
- },
- {
- "arrival": {
- "time": 1620706710
- },
- "departure": {
- "time": 1620706710
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620706800
- },
- "departure": {
- "time": 1620706800
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620706980
- },
- "departure": {
- "time": 1620706980
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620707070
- },
- "departure": {
- "time": 1620707070
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620707190
- },
- "departure": {
- "time": 1620707190
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620707310
- },
- "departure": {
- "time": 1620707310
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620707400
- },
- "departure": {
- "time": 1620707400
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620707490
- },
- "departure": {
- "time": 1620707490
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620707550
- },
- "departure": {
- "time": 1620707550
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620707640
- },
- "departure": {
- "time": 1620707640
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620707730
- },
- "departure": {
- "time": 1620707730
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620707820
- },
- "departure": {
- "time": 1620707820
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620707940
- },
- "departure": {
- "time": 1620707940
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620708120
- },
- "departure": {
- "time": 1620708120
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620708720
- },
- "departure": {
- "time": 1620708720
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620708930
- },
- "departure": {
- "time": 1620708930
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620709200
- },
- "departure": {
- "time": 1620709200
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620709440
- },
- "departure": {
- "time": 1620709440
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000022E",
- "vehicle": {
- "trip": {
- "trip_id": "000200_E..N",
- "start_time": "00:02:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620705720,
- "stop_id": "E01N"
- }
- },
- {
- "id": "000023E",
- "trip_update": {
- "trip": {
- "trip_id": "001250_E..S",
- "start_time": "00:12:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706350
- },
- "departure": {
- "time": 1620706350
- },
- "stop_id": "G05S"
- },
- {
- "arrival": {
- "time": 1620706440
- },
- "departure": {
- "time": 1620706440
- },
- "stop_id": "G06S"
- },
- {
- "arrival": {
- "time": 1620706590
- },
- "departure": {
- "time": 1620706590
- },
- "stop_id": "G07S"
- },
- {
- "arrival": {
- "time": 1620706680
- },
- "departure": {
- "time": 1620706680
- },
- "stop_id": "F05S"
- },
- {
- "arrival": {
- "time": 1620706770
- },
- "departure": {
- "time": 1620706770
- },
- "stop_id": "F06S"
- },
- {
- "arrival": {
- "time": 1620706860
- },
- "departure": {
- "time": 1620706860
- },
- "stop_id": "F07S"
- },
- {
- "arrival": {
- "time": 1620706950
- },
- "departure": {
- "time": 1620706950
- },
- "stop_id": "G08S"
- },
- {
- "arrival": {
- "time": 1620707040
- },
- "departure": {
- "time": 1620707040
- },
- "stop_id": "G09S"
- },
- {
- "arrival": {
- "time": 1620707160
- },
- "departure": {
- "time": 1620707160
- },
- "stop_id": "G10S"
- },
- {
- "arrival": {
- "time": 1620707220
- },
- "departure": {
- "time": 1620707220
- },
- "stop_id": "G11S"
- },
- {
- "arrival": {
- "time": 1620707340
- },
- "departure": {
- "time": 1620707340
- },
- "stop_id": "G12S"
- },
- {
- "arrival": {
- "time": 1620707430
- },
- "departure": {
- "time": 1620707430
- },
- "stop_id": "G13S"
- },
- {
- "arrival": {
- "time": 1620707520
- },
- "departure": {
- "time": 1620707520
- },
- "stop_id": "G14S"
- },
- {
- "arrival": {
- "time": 1620707610
- },
- "departure": {
- "time": 1620707610
- },
- "stop_id": "G15S"
- },
- {
- "arrival": {
- "time": 1620707700
- },
- "departure": {
- "time": 1620707700
- },
- "stop_id": "G16S"
- },
- {
- "arrival": {
- "time": 1620707790
- },
- "departure": {
- "time": 1620707790
- },
- "stop_id": "G18S"
- },
- {
- "arrival": {
- "time": 1620707880
- },
- "departure": {
- "time": 1620707880
- },
- "stop_id": "G19S"
- },
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "G20S"
- },
- {
- "arrival": {
- "time": 1620708120
- },
- "departure": {
- "time": 1620708120
- },
- "stop_id": "G21S"
- },
- {
- "arrival": {
- "time": 1620708210
- },
- "departure": {
- "time": 1620708210
- },
- "stop_id": "F09S"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "F11S"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "F12S"
- },
- {
- "arrival": {
- "time": 1620708570
- },
- "departure": {
- "time": 1620708570
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620708780
- },
- "departure": {
- "time": 1620708780
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620709020
- },
- "departure": {
- "time": 1620709020
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620709080
- },
- "departure": {
- "time": 1620709080
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620709170
- },
- "departure": {
- "time": 1620709170
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620709260
- },
- "departure": {
- "time": 1620709260
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620709380
- },
- "departure": {
- "time": 1620709380
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620709470
- },
- "departure": {
- "time": 1620709470
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620709665
- },
- "departure": {
- "time": 1620709665
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620709890
- },
- "departure": {
- "time": 1620709890
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000024E",
- "vehicle": {
- "trip": {
- "trip_id": "001250_E..S",
- "start_time": "00:12:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620706350,
- "stop_id": "G05S"
- }
- },
- {
- "id": "000025E",
- "trip_update": {
- "trip": {
- "trip_id": "143000_E..N",
- "start_time": "23:50:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705451
- },
- "departure": {
- "time": 1620705451
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620705561
- },
- "departure": {
- "time": 1620705561
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620705621
- },
- "departure": {
- "time": 1620705621
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620705741
- },
- "departure": {
- "time": 1620705741
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620705831
- },
- "departure": {
- "time": 1620705831
- },
- "stop_id": "D14N"
- },
- {
- "arrival": {
- "time": 1620705891
- },
- "departure": {
- "time": 1620705891
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620705981
- },
- "departure": {
- "time": 1620705981
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620706161
- },
- "departure": {
- "time": 1620706161
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620706251
- },
- "departure": {
- "time": 1620706251
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620706371
- },
- "departure": {
- "time": 1620706371
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620706491
- },
- "departure": {
- "time": 1620706491
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620706581
- },
- "departure": {
- "time": 1620706581
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620706671
- },
- "departure": {
- "time": 1620706671
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620706731
- },
- "departure": {
- "time": 1620706731
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620706821
- },
- "departure": {
- "time": 1620706821
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620706911
- },
- "departure": {
- "time": 1620706911
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620707001
- },
- "departure": {
- "time": 1620707001
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620707121
- },
- "departure": {
- "time": 1620707121
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620707181
- },
- "departure": {
- "time": 1620707181
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620707301
- },
- "departure": {
- "time": 1620707301
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620707421
- },
- "departure": {
- "time": 1620707421
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620707571
- },
- "departure": {
- "time": 1620707571
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620707661
- },
- "departure": {
- "time": 1620707661
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620707781
- },
- "departure": {
- "time": 1620707781
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620707871
- },
- "departure": {
- "time": 1620707871
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620708171
- },
- "departure": {
- "time": 1620708171
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620708441
- },
- "departure": {
- "time": 1620708441
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000026E",
- "vehicle": {
- "trip": {
- "trip_id": "143000_E..N",
- "start_time": "23:50:00",
- "start_date": "20210510",
- "route_id": "E"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620705451,
- "stop_id": "A30N"
- }
- },
- {
- "id": "000027E",
- "trip_update": {
- "trip": {
- "trip_id": "001350_E..N",
- "start_time": "00:13:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706410
- },
- "departure": {
- "time": 1620706410
- },
- "stop_id": "E01N"
- },
- {
- "arrival": {
- "time": 1620706530
- },
- "departure": {
- "time": 1620706530
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620706620
- },
- "departure": {
- "time": 1620706620
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620706740
- },
- "departure": {
- "time": 1620706740
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620706860
- },
- "departure": {
- "time": 1620706860
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620706950
- },
- "departure": {
- "time": 1620706950
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620707070
- },
- "departure": {
- "time": 1620707070
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620707130
- },
- "departure": {
- "time": 1620707130
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620707250
- },
- "departure": {
- "time": 1620707250
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620707340
- },
- "departure": {
- "time": 1620707340
- },
- "stop_id": "D14N"
- },
- {
- "arrival": {
- "time": 1620707400
- },
- "departure": {
- "time": 1620707400
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620707490
- },
- "departure": {
- "time": 1620707490
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620707670
- },
- "departure": {
- "time": 1620707670
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620707790
- },
- "departure": {
- "time": 1620707790
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620707940
- },
- "departure": {
- "time": 1620707940
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620708300
- },
- "departure": {
- "time": 1620708300
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620708570
- },
- "departure": {
- "time": 1620708570
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620708690
- },
- "departure": {
- "time": 1620708690
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620708750
- },
- "departure": {
- "time": 1620708750
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620708870
- },
- "departure": {
- "time": 1620708870
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620709140
- },
- "departure": {
- "time": 1620709140
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620709230
- },
- "departure": {
- "time": 1620709230
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620709470
- },
- "departure": {
- "time": 1620709470
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620709680
- },
- "departure": {
- "time": 1620709680
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620709935
- },
- "departure": {
- "time": 1620709935
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620710160
- },
- "departure": {
- "time": 1620710160
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000028E",
- "vehicle": {
- "trip": {
- "trip_id": "001350_E..N",
- "start_time": "00:13:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620706410,
- "stop_id": "E01N"
- }
- },
- {
- "id": "000029E",
- "trip_update": {
- "trip": {
- "trip_id": "002600_E..N",
- "start_time": "00:26:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620707160
- },
- "departure": {
- "time": 1620707160
- },
- "stop_id": "E01N"
- },
- {
- "arrival": {
- "time": 1620707280
- },
- "departure": {
- "time": 1620707280
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620707370
- },
- "departure": {
- "time": 1620707370
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620707490
- },
- "departure": {
- "time": 1620707490
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620707610
- },
- "departure": {
- "time": 1620707610
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620707700
- },
- "departure": {
- "time": 1620707700
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620707820
- },
- "departure": {
- "time": 1620707820
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620707880
- },
- "departure": {
- "time": 1620707880
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620708090
- },
- "departure": {
- "time": 1620708090
- },
- "stop_id": "D14N"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620708690
- },
- "departure": {
- "time": 1620708690
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620708810
- },
- "departure": {
- "time": 1620708810
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620708900
- },
- "departure": {
- "time": 1620708900
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620709050
- },
- "departure": {
- "time": 1620709050
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620709140
- },
- "departure": {
- "time": 1620709140
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620709230
- },
- "departure": {
- "time": 1620709230
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620709320
- },
- "departure": {
- "time": 1620709320
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620709440
- },
- "departure": {
- "time": 1620709440
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620709500
- },
- "departure": {
- "time": 1620709500
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620709620
- },
- "departure": {
- "time": 1620709620
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620709740
- },
- "departure": {
- "time": 1620709740
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620709890
- },
- "departure": {
- "time": 1620709890
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620709980
- },
- "departure": {
- "time": 1620709980
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620710220
- },
- "departure": {
- "time": 1620710220
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620710430
- },
- "departure": {
- "time": 1620710430
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620710670
- },
- "departure": {
- "time": 1620710670
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000030E",
- "vehicle": {
- "trip": {
- "trip_id": "002600_E..N",
- "start_time": "00:26:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620707160,
- "stop_id": "E01N"
- }
- },
- {
- "id": "000031E",
- "trip_update": {
- "trip": {
- "trip_id": "003250_E..S",
- "start_time": "00:32:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620707550
- },
- "departure": {
- "time": 1620707550
- },
- "stop_id": "G05S"
- },
- {
- "arrival": {
- "time": 1620707640
- },
- "departure": {
- "time": 1620707640
- },
- "stop_id": "G06S"
- },
- {
- "arrival": {
- "time": 1620707790
- },
- "departure": {
- "time": 1620707790
- },
- "stop_id": "G07S"
- },
- {
- "arrival": {
- "time": 1620707880
- },
- "departure": {
- "time": 1620707880
- },
- "stop_id": "F05S"
- },
- {
- "arrival": {
- "time": 1620707970
- },
- "departure": {
- "time": 1620707970
- },
- "stop_id": "F06S"
- },
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "F07S"
- },
- {
- "arrival": {
- "time": 1620708150
- },
- "departure": {
- "time": 1620708150
- },
- "stop_id": "G08S"
- },
- {
- "arrival": {
- "time": 1620708240
- },
- "departure": {
- "time": 1620708240
- },
- "stop_id": "G09S"
- },
- {
- "arrival": {
- "time": 1620708360
- },
- "departure": {
- "time": 1620708360
- },
- "stop_id": "G10S"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "G11S"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "G12S"
- },
- {
- "arrival": {
- "time": 1620708630
- },
- "departure": {
- "time": 1620708630
- },
- "stop_id": "G13S"
- },
- {
- "arrival": {
- "time": 1620708720
- },
- "departure": {
- "time": 1620708720
- },
- "stop_id": "G14S"
- },
- {
- "arrival": {
- "time": 1620708810
- },
- "departure": {
- "time": 1620708810
- },
- "stop_id": "G15S"
- },
- {
- "arrival": {
- "time": 1620708900
- },
- "departure": {
- "time": 1620708900
- },
- "stop_id": "G16S"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "G18S"
- },
- {
- "arrival": {
- "time": 1620709080
- },
- "departure": {
- "time": 1620709080
- },
- "stop_id": "G19S"
- },
- {
- "arrival": {
- "time": 1620709200
- },
- "departure": {
- "time": 1620709200
- },
- "stop_id": "G20S"
- },
- {
- "arrival": {
- "time": 1620709320
- },
- "departure": {
- "time": 1620709320
- },
- "stop_id": "G21S"
- },
- {
- "arrival": {
- "time": 1620709410
- },
- "departure": {
- "time": 1620709410
- },
- "stop_id": "F09S"
- },
- {
- "arrival": {
- "time": 1620709590
- },
- "departure": {
- "time": 1620709590
- },
- "stop_id": "F11S"
- },
- {
- "arrival": {
- "time": 1620709680
- },
- "departure": {
- "time": 1620709680
- },
- "stop_id": "F12S"
- },
- {
- "arrival": {
- "time": 1620709770
- },
- "departure": {
- "time": 1620709770
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620709980
- },
- "departure": {
- "time": 1620709980
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620710220
- },
- "departure": {
- "time": 1620710220
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620710280
- },
- "departure": {
- "time": 1620710280
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620710370
- },
- "departure": {
- "time": 1620710370
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620710460
- },
- "departure": {
- "time": 1620710460
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620710580
- },
- "departure": {
- "time": 1620710580
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620710670
- },
- "departure": {
- "time": 1620710670
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620710865
- },
- "departure": {
- "time": 1620710865
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620711090
- },
- "departure": {
- "time": 1620711090
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000032E",
- "vehicle": {
- "trip": {
- "trip_id": "003250_E..S",
- "start_time": "00:32:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620707550,
- "stop_id": "G05S"
- }
- },
- {
- "id": "000033E",
- "trip_update": {
- "trip": {
- "trip_id": "003800_E..N",
- "start_time": "00:38:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620707880
- },
- "departure": {
- "time": 1620707880
- },
- "stop_id": "E01N"
- },
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620708090
- },
- "departure": {
- "time": 1620708090
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620708210
- },
- "departure": {
- "time": 1620708210
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620708330
- },
- "departure": {
- "time": 1620708330
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620708420
- },
- "departure": {
- "time": 1620708420
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620708600
- },
- "departure": {
- "time": 1620708600
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620708720
- },
- "departure": {
- "time": 1620708720
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620708810
- },
- "departure": {
- "time": 1620708810
- },
- "stop_id": "D14N"
- },
- {
- "arrival": {
- "time": 1620708870
- },
- "departure": {
- "time": 1620708870
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620708960
- },
- "departure": {
- "time": 1620708960
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620709140
- },
- "departure": {
- "time": 1620709140
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620709260
- },
- "departure": {
- "time": 1620709260
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620709410
- },
- "departure": {
- "time": 1620709410
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620709530
- },
- "departure": {
- "time": 1620709530
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620709620
- },
- "departure": {
- "time": 1620709620
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620709710
- },
- "departure": {
- "time": 1620709710
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620709770
- },
- "departure": {
- "time": 1620709770
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620709860
- },
- "departure": {
- "time": 1620709860
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620709950
- },
- "departure": {
- "time": 1620709950
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620710040
- },
- "departure": {
- "time": 1620710040
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620710160
- },
- "departure": {
- "time": 1620710160
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620710220
- },
- "departure": {
- "time": 1620710220
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620710340
- },
- "departure": {
- "time": 1620710340
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620710460
- },
- "departure": {
- "time": 1620710460
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620710610
- },
- "departure": {
- "time": 1620710610
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620710700
- },
- "departure": {
- "time": 1620710700
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620710925
- },
- "departure": {
- "time": 1620710925
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620711120
- },
- "departure": {
- "time": 1620711120
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620711345
- },
- "departure": {
- "time": 1620711345
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620711540
- },
- "departure": {
- "time": 1620711540
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000034E",
- "vehicle": {
- "trip": {
- "trip_id": "003800_E..N",
- "start_time": "00:38:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620707880,
- "stop_id": "E01N"
- }
- },
- {
- "id": "000035E",
- "trip_update": {
- "trip": {
- "trip_id": "005250_E..S",
- "start_time": "00:52:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708750
- },
- "departure": {
- "time": 1620708750
- },
- "stop_id": "G05S"
- },
- {
- "arrival": {
- "time": 1620708840
- },
- "departure": {
- "time": 1620708840
- },
- "stop_id": "G06S"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "G07S"
- },
- {
- "arrival": {
- "time": 1620709080
- },
- "departure": {
- "time": 1620709080
- },
- "stop_id": "F05S"
- },
- {
- "arrival": {
- "time": 1620709170
- },
- "departure": {
- "time": 1620709170
- },
- "stop_id": "F06S"
- },
- {
- "arrival": {
- "time": 1620709260
- },
- "departure": {
- "time": 1620709260
- },
- "stop_id": "F07S"
- },
- {
- "arrival": {
- "time": 1620709350
- },
- "departure": {
- "time": 1620709350
- },
- "stop_id": "G08S"
- },
- {
- "arrival": {
- "time": 1620709440
- },
- "departure": {
- "time": 1620709440
- },
- "stop_id": "G09S"
- },
- {
- "arrival": {
- "time": 1620709560
- },
- "departure": {
- "time": 1620709560
- },
- "stop_id": "G10S"
- },
- {
- "arrival": {
- "time": 1620709620
- },
- "departure": {
- "time": 1620709620
- },
- "stop_id": "G11S"
- },
- {
- "arrival": {
- "time": 1620709740
- },
- "departure": {
- "time": 1620709740
- },
- "stop_id": "G12S"
- },
- {
- "arrival": {
- "time": 1620709830
- },
- "departure": {
- "time": 1620709830
- },
- "stop_id": "G13S"
- },
- {
- "arrival": {
- "time": 1620709920
- },
- "departure": {
- "time": 1620709920
- },
- "stop_id": "G14S"
- },
- {
- "arrival": {
- "time": 1620710010
- },
- "departure": {
- "time": 1620710010
- },
- "stop_id": "G15S"
- },
- {
- "arrival": {
- "time": 1620710100
- },
- "departure": {
- "time": 1620710100
- },
- "stop_id": "G16S"
- },
- {
- "arrival": {
- "time": 1620710190
- },
- "departure": {
- "time": 1620710190
- },
- "stop_id": "G18S"
- },
- {
- "arrival": {
- "time": 1620710280
- },
- "departure": {
- "time": 1620710280
- },
- "stop_id": "G19S"
- },
- {
- "arrival": {
- "time": 1620710400
- },
- "departure": {
- "time": 1620710400
- },
- "stop_id": "G20S"
- },
- {
- "arrival": {
- "time": 1620710520
- },
- "departure": {
- "time": 1620710520
- },
- "stop_id": "G21S"
- },
- {
- "arrival": {
- "time": 1620710610
- },
- "departure": {
- "time": 1620710610
- },
- "stop_id": "F09S"
- },
- {
- "arrival": {
- "time": 1620710790
- },
- "departure": {
- "time": 1620710790
- },
- "stop_id": "F11S"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "F12S"
- },
- {
- "arrival": {
- "time": 1620710970
- },
- "departure": {
- "time": 1620710970
- },
- "stop_id": "D14S"
- },
- {
- "arrival": {
- "time": 1620711180
- },
- "departure": {
- "time": 1620711180
- },
- "stop_id": "A25S"
- },
- {
- "arrival": {
- "time": 1620711420
- },
- "departure": {
- "time": 1620711420
- },
- "stop_id": "A27S"
- },
- {
- "arrival": {
- "time": 1620711480
- },
- "departure": {
- "time": 1620711480
- },
- "stop_id": "A28S"
- },
- {
- "arrival": {
- "time": 1620711570
- },
- "departure": {
- "time": 1620711570
- },
- "stop_id": "A30S"
- },
- {
- "arrival": {
- "time": 1620711660
- },
- "departure": {
- "time": 1620711660
- },
- "stop_id": "A31S"
- },
- {
- "arrival": {
- "time": 1620711780
- },
- "departure": {
- "time": 1620711780
- },
- "stop_id": "A32S"
- },
- {
- "arrival": {
- "time": 1620711870
- },
- "departure": {
- "time": 1620711870
- },
- "stop_id": "A33S"
- },
- {
- "arrival": {
- "time": 1620712065
- },
- "departure": {
- "time": 1620712065
- },
- "stop_id": "A34S"
- },
- {
- "arrival": {
- "time": 1620712290
- },
- "departure": {
- "time": 1620712290
- },
- "stop_id": "E01S"
- }
- ]
- }
- },
- {
- "id": "000036E",
- "vehicle": {
- "trip": {
- "trip_id": "005250_E..S",
- "start_time": "00:52:30",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620708750,
- "stop_id": "G05S"
- }
- },
- {
- "id": "000037E",
- "trip_update": {
- "trip": {
- "trip_id": "005300_E..N",
- "start_time": "00:53:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708780
- },
- "departure": {
- "time": 1620708780
- },
- "stop_id": "E01N"
- },
- {
- "arrival": {
- "time": 1620708900
- },
- "departure": {
- "time": 1620708900
- },
- "stop_id": "A34N"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "A33N"
- },
- {
- "arrival": {
- "time": 1620709110
- },
- "departure": {
- "time": 1620709110
- },
- "stop_id": "A32N"
- },
- {
- "arrival": {
- "time": 1620709230
- },
- "departure": {
- "time": 1620709230
- },
- "stop_id": "A31N"
- },
- {
- "arrival": {
- "time": 1620709320
- },
- "departure": {
- "time": 1620709320
- },
- "stop_id": "A30N"
- },
- {
- "arrival": {
- "time": 1620709440
- },
- "departure": {
- "time": 1620709440
- },
- "stop_id": "A28N"
- },
- {
- "arrival": {
- "time": 1620709500
- },
- "departure": {
- "time": 1620709500
- },
- "stop_id": "A27N"
- },
- {
- "arrival": {
- "time": 1620709620
- },
- "departure": {
- "time": 1620709620
- },
- "stop_id": "A25N"
- },
- {
- "arrival": {
- "time": 1620709710
- },
- "departure": {
- "time": 1620709710
- },
- "stop_id": "D14N"
- },
- {
- "arrival": {
- "time": 1620709770
- },
- "departure": {
- "time": 1620709770
- },
- "stop_id": "F12N"
- },
- {
- "arrival": {
- "time": 1620709860
- },
- "departure": {
- "time": 1620709860
- },
- "stop_id": "F11N"
- },
- {
- "arrival": {
- "time": 1620710040
- },
- "departure": {
- "time": 1620710040
- },
- "stop_id": "F09N"
- },
- {
- "arrival": {
- "time": 1620710130
- },
- "departure": {
- "time": 1620710130
- },
- "stop_id": "G21N"
- },
- {
- "arrival": {
- "time": 1620710250
- },
- "departure": {
- "time": 1620710250
- },
- "stop_id": "G20N"
- },
- {
- "arrival": {
- "time": 1620710370
- },
- "departure": {
- "time": 1620710370
- },
- "stop_id": "G19N"
- },
- {
- "arrival": {
- "time": 1620710460
- },
- "departure": {
- "time": 1620710460
- },
- "stop_id": "G18N"
- },
- {
- "arrival": {
- "time": 1620710550
- },
- "departure": {
- "time": 1620710550
- },
- "stop_id": "G16N"
- },
- {
- "arrival": {
- "time": 1620710610
- },
- "departure": {
- "time": 1620710610
- },
- "stop_id": "G15N"
- },
- {
- "arrival": {
- "time": 1620710700
- },
- "departure": {
- "time": 1620710700
- },
- "stop_id": "G14N"
- },
- {
- "arrival": {
- "time": 1620710790
- },
- "departure": {
- "time": 1620710790
- },
- "stop_id": "G13N"
- },
- {
- "arrival": {
- "time": 1620710880
- },
- "departure": {
- "time": 1620710880
- },
- "stop_id": "G12N"
- },
- {
- "arrival": {
- "time": 1620711000
- },
- "departure": {
- "time": 1620711000
- },
- "stop_id": "G11N"
- },
- {
- "arrival": {
- "time": 1620711060
- },
- "departure": {
- "time": 1620711060
- },
- "stop_id": "G10N"
- },
- {
- "arrival": {
- "time": 1620711180
- },
- "departure": {
- "time": 1620711180
- },
- "stop_id": "G09N"
- },
- {
- "arrival": {
- "time": 1620711300
- },
- "departure": {
- "time": 1620711300
- },
- "stop_id": "G08N"
- },
- {
- "arrival": {
- "time": 1620711450
- },
- "departure": {
- "time": 1620711450
- },
- "stop_id": "F07N"
- },
- {
- "arrival": {
- "time": 1620711540
- },
- "departure": {
- "time": 1620711540
- },
- "stop_id": "F06N"
- },
- {
- "arrival": {
- "time": 1620711780
- },
- "departure": {
- "time": 1620711780
- },
- "stop_id": "F05N"
- },
- {
- "arrival": {
- "time": 1620711990
- },
- "departure": {
- "time": 1620711990
- },
- "stop_id": "G07N"
- },
- {
- "arrival": {
- "time": 1620712260
- },
- "departure": {
- "time": 1620712260
- },
- "stop_id": "G06N"
- },
- {
- "arrival": {
- "time": 1620712500
- },
- "departure": {
- "time": 1620712500
- },
- "stop_id": "G05N"
- }
- ]
- }
- },
- {
- "id": "000038E",
- "vehicle": {
- "trip": {
- "trip_id": "005300_E..N",
- "start_time": "00:53:00",
- "start_date": "20210511",
- "route_id": "E"
- },
- "timestamp": 1620708780,
- "stop_id": "E01N"
- }
- },
- {
- "id": "000001H",
- "trip_update": {
- "trip": {
- "trip_id": "127700_H..N",
- "start_time": "21:17:00",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000002H",
- "vehicle": {
- "trip": {
- "trip_id": "127700_H..N",
- "start_time": "21:17:00",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620696402,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000003H",
- "trip_update": {
- "trip": {
- "trip_id": "129600_H..N",
- "start_time": "21:36:00",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000004H",
- "vehicle": {
- "trip": {
- "trip_id": "129600_H..N",
- "start_time": "21:36:00",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620697731,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000005H",
- "trip_update": {
- "trip": {
- "trip_id": "131350_H..N",
- "start_time": "21:53:30",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000006H",
- "vehicle": {
- "trip": {
- "trip_id": "131350_H..N",
- "start_time": "21:53:30",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620698976,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000007H",
- "trip_update": {
- "trip": {
- "trip_id": "133050_H..N",
- "start_time": "22:10:30",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000008H",
- "vehicle": {
- "trip": {
- "trip_id": "133050_H..N",
- "start_time": "22:10:30",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620700446,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000009H",
- "trip_update": {
- "trip": {
- "trip_id": "135500_H..N",
- "start_time": "22:35:00",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000010H",
- "vehicle": {
- "trip": {
- "trip_id": "135500_H..N",
- "start_time": "22:35:00",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620701106,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000011H",
- "trip_update": {
- "trip": {
- "trip_id": "137450_H..N",
- "start_time": "22:54:30",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000012H",
- "vehicle": {
- "trip": {
- "trip_id": "137450_H..N",
- "start_time": "22:54:30",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620702411,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000013H",
- "trip_update": {
- "trip": {
- "trip_id": "139115_H..N",
- "start_time": "23:11:09",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000014H",
- "vehicle": {
- "trip": {
- "trip_id": "139115_H..N",
- "start_time": "23:11:09",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620703246,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000015H",
- "trip_update": {
- "trip": {
- "trip_id": "141200_H..N",
- "start_time": "23:32:00",
- "start_date": "20210510",
- "route_id": "H"
- }
- }
- },
- {
- "id": "000016H",
- "vehicle": {
- "trip": {
- "trip_id": "141200_H..N",
- "start_time": "23:32:00",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 5,
- "current_status": 1,
- "timestamp": 1620704561,
- "stop_id": "H19N"
- }
- },
- {
- "id": "000017H",
- "trip_update": {
- "trip": {
- "trip_id": "143400_H..S",
- "start_time": "23:54:00",
- "start_date": "20210510",
- "route_id": "H"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705547
- },
- "departure": {
- "time": 1620705547
- },
- "stop_id": "H13S"
- },
- {
- "arrival": {
- "time": 1620705607
- },
- "departure": {
- "time": 1620705607
- },
- "stop_id": "H14S"
- },
- {
- "arrival": {
- "time": 1620705697
- },
- "departure": {
- "time": 1620705697
- },
- "stop_id": "H15S"
- }
- ]
- }
- },
- {
- "id": "000018H",
- "vehicle": {
- "trip": {
- "trip_id": "143400_H..S",
- "start_time": "23:54:00",
- "start_date": "20210510",
- "route_id": "H"
- },
- "current_stop_sequence": 2,
- "current_status": 1,
- "timestamp": 1620705431,
- "stop_id": "H12S"
- }
- },
- {
- "id": "000019H",
- "trip_update": {
- "trip": {
- "trip_id": "143850_H..N",
- "start_time": "23:58:30",
- "start_date": "20210510",
- "route_id": "H"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620705510
- },
- "departure": {
- "time": 1620705510
- },
- "stop_id": "H15N"
- },
- {
- "arrival": {
- "time": 1620705630
- },
- "departure": {
- "time": 1620705630
- },
- "stop_id": "H14N"
- },
- {
- "arrival": {
- "time": 1620705750
- },
- "departure": {
- "time": 1620705750
- },
- "stop_id": "H13N"
- },
- {
- "arrival": {
- "time": 1620705840
- },
- "departure": {
- "time": 1620705840
- },
- "stop_id": "H12N"
- },
- {
- "arrival": {
- "time": 1620706125
- },
- "departure": {
- "time": 1620706125
- },
- "stop_id": "H04N"
- },
- {
- "arrival": {
- "time": 1620706290
- },
- "departure": {
- "time": 1620706290
- },
- "stop_id": "H19N"
- }
- ]
- }
- },
- {
- "id": "000020H",
- "vehicle": {
- "trip": {
- "trip_id": "143850_H..N",
- "start_time": "23:58:30",
- "start_date": "20210510",
- "route_id": "H"
- },
- "timestamp": 1620705510,
- "stop_id": "H15N"
- }
- },
- {
- "id": "000021H",
- "trip_update": {
- "trip": {
- "trip_id": "001700_H..S",
- "start_time": "00:17:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706620
- },
- "departure": {
- "time": 1620706620
- },
- "stop_id": "H19S"
- },
- {
- "arrival": {
- "time": 1620706710
- },
- "departure": {
- "time": 1620706710
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620706980
- },
- "departure": {
- "time": 1620706980
- },
- "stop_id": "H12S"
- },
- {
- "arrival": {
- "time": 1620707100
- },
- "departure": {
- "time": 1620707100
- },
- "stop_id": "H13S"
- },
- {
- "arrival": {
- "time": 1620707160
- },
- "departure": {
- "time": 1620707160
- },
- "stop_id": "H14S"
- },
- {
- "arrival": {
- "time": 1620707250
- },
- "departure": {
- "time": 1620707250
- },
- "stop_id": "H15S"
- }
- ]
- }
- },
- {
- "id": "000022H",
- "vehicle": {
- "trip": {
- "trip_id": "001700_H..S",
- "start_time": "00:17:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "timestamp": 1620706620,
- "stop_id": "H19S"
- }
- },
- {
- "id": "000023H",
- "trip_update": {
- "trip": {
- "trip_id": "002000_H..N",
- "start_time": "00:20:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706800
- },
- "departure": {
- "time": 1620706800
- },
- "stop_id": "H15N"
- },
- {
- "arrival": {
- "time": 1620706920
- },
- "departure": {
- "time": 1620706920
- },
- "stop_id": "H14N"
- },
- {
- "arrival": {
- "time": 1620707040
- },
- "departure": {
- "time": 1620707040
- },
- "stop_id": "H13N"
- },
- {
- "arrival": {
- "time": 1620707130
- },
- "departure": {
- "time": 1620707130
- },
- "stop_id": "H12N"
- },
- {
- "arrival": {
- "time": 1620707415
- },
- "departure": {
- "time": 1620707415
- },
- "stop_id": "H04N"
- },
- {
- "arrival": {
- "time": 1620707580
- },
- "departure": {
- "time": 1620707580
- },
- "stop_id": "H19N"
- }
- ]
- }
- },
- {
- "id": "000024H",
- "vehicle": {
- "trip": {
- "trip_id": "002000_H..N",
- "start_time": "00:20:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "timestamp": 1620706800,
- "stop_id": "H15N"
- }
- },
- {
- "id": "000025H",
- "trip_update": {
- "trip": {
- "trip_id": "004000_H..S",
- "start_time": "00:40:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "H19S"
- },
- {
- "arrival": {
- "time": 1620708090
- },
- "departure": {
- "time": 1620708090
- },
- "stop_id": "H04S"
- },
- {
- "arrival": {
- "time": 1620708360
- },
- "departure": {
- "time": 1620708360
- },
- "stop_id": "H12S"
- },
- {
- "arrival": {
- "time": 1620708480
- },
- "departure": {
- "time": 1620708480
- },
- "stop_id": "H13S"
- },
- {
- "arrival": {
- "time": 1620708540
- },
- "departure": {
- "time": 1620708540
- },
- "stop_id": "H14S"
- },
- {
- "arrival": {
- "time": 1620708630
- },
- "departure": {
- "time": 1620708630
- },
- "stop_id": "H15S"
- }
- ]
- }
- },
- {
- "id": "000026H",
- "vehicle": {
- "trip": {
- "trip_id": "004000_H..S",
- "start_time": "00:40:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "timestamp": 1620708000,
- "stop_id": "H19S"
- }
- },
- {
- "id": "000027H",
- "trip_update": {
- "trip": {
- "trip_id": "004100_H..N",
- "start_time": "00:41:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708060
- },
- "departure": {
- "time": 1620708060
- },
- "stop_id": "H15N"
- },
- {
- "arrival": {
- "time": 1620708180
- },
- "departure": {
- "time": 1620708180
- },
- "stop_id": "H14N"
- },
- {
- "arrival": {
- "time": 1620708300
- },
- "departure": {
- "time": 1620708300
- },
- "stop_id": "H13N"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "H12N"
- },
- {
- "arrival": {
- "time": 1620708675
- },
- "departure": {
- "time": 1620708675
- },
- "stop_id": "H04N"
- },
- {
- "arrival": {
- "time": 1620708840
- },
- "departure": {
- "time": 1620708840
- },
- "stop_id": "H19N"
- }
- ]
- }
- },
- {
- "id": "000028H",
- "vehicle": {
- "trip": {
- "trip_id": "004100_H..N",
- "start_time": "00:41:00",
- "start_date": "20210511",
- "route_id": "H"
- },
- "timestamp": 1620708060,
- "stop_id": "H15N"
- }
- },
- {
- "id": "000001FS",
- "trip_update": {
- "trip": {
- "trip_id": "132450_FS..N",
- "start_time": "22:04:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000002FS",
- "vehicle": {
- "trip": {
- "trip_id": "132450_FS..N",
- "start_time": "22:04:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620699196,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000003FS",
- "trip_update": {
- "trip": {
- "trip_id": "133950_FS..N",
- "start_time": "22:19:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000004FS",
- "vehicle": {
- "trip": {
- "trip_id": "133950_FS..N",
- "start_time": "22:19:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620699846,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000005FS",
- "trip_update": {
- "trip": {
- "trip_id": "135450_FS..N",
- "start_time": "22:34:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000006FS",
- "vehicle": {
- "trip": {
- "trip_id": "135450_FS..N",
- "start_time": "22:34:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620700866,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000007FS",
- "trip_update": {
- "trip": {
- "trip_id": "136950_FS..N",
- "start_time": "22:49:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000008FS",
- "vehicle": {
- "trip": {
- "trip_id": "136950_FS..N",
- "start_time": "22:49:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620704007,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000009FS",
- "trip_update": {
- "trip": {
- "trip_id": "138950_FS..N",
- "start_time": "23:09:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000010FS",
- "vehicle": {
- "trip": {
- "trip_id": "138950_FS..N",
- "start_time": "23:09:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620704016,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000011FS",
- "trip_update": {
- "trip": {
- "trip_id": "140950_FS..N",
- "start_time": "23:29:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000012FS",
- "vehicle": {
- "trip": {
- "trip_id": "140950_FS..N",
- "start_time": "23:29:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620704011,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000013FS",
- "trip_update": {
- "trip": {
- "trip_id": "000950_FS..N",
- "start_time": "00:09:30",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706170
- },
- "departure": {
- "time": 1620706170
- },
- "stop_id": "D26N"
- },
- {
- "arrival": {
- "time": 1620706350
- },
- "departure": {
- "time": 1620706350
- },
- "stop_id": "S04N"
- },
- {
- "arrival": {
- "time": 1620706470
- },
- "departure": {
- "time": 1620706470
- },
- "stop_id": "S03N"
- }
- ]
- }
- },
- {
- "id": "000014FS",
- "vehicle": {
- "trip": {
- "trip_id": "000950_FS..N",
- "start_time": "00:09:30",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620705192,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000015FS",
- "trip_update": {
- "trip": {
- "trip_id": "142950_FS..N",
- "start_time": "23:49:30",
- "start_date": "20210510",
- "route_id": "FS"
- }
- }
- },
- {
- "id": "000016FS",
- "vehicle": {
- "trip": {
- "trip_id": "142950_FS..N",
- "start_time": "23:49:30",
- "start_date": "20210510",
- "route_id": "FS"
- },
- "current_stop_sequence": 3,
- "current_status": 1,
- "timestamp": 1620705187,
- "stop_id": "S01N"
- }
- },
- {
- "id": "000017FS",
- "trip_update": {
- "trip": {
- "trip_id": "002000_FS..S",
- "start_time": "00:20:00",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620706800
- },
- "departure": {
- "time": 1620706800
- },
- "stop_id": "S01S"
- },
- {
- "arrival": {
- "time": 1620706920
- },
- "departure": {
- "time": 1620706920
- },
- "stop_id": "S03S"
- },
- {
- "arrival": {
- "time": 1620707010
- },
- "departure": {
- "time": 1620707010
- },
- "stop_id": "S04S"
- },
- {
- "arrival": {
- "time": 1620707190
- },
- "departure": {
- "time": 1620707190
- },
- "stop_id": "D26S"
- }
- ]
- }
- },
- {
- "id": "000018FS",
- "vehicle": {
- "trip": {
- "trip_id": "002000_FS..S",
- "start_time": "00:20:00",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "timestamp": 1620706800,
- "stop_id": "S01S"
- }
- },
- {
- "id": "000019FS",
- "trip_update": {
- "trip": {
- "trip_id": "002950_FS..N",
- "start_time": "00:29:30",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620707370
- },
- "departure": {
- "time": 1620707370
- },
- "stop_id": "D26N"
- },
- {
- "arrival": {
- "time": 1620707550
- },
- "departure": {
- "time": 1620707550
- },
- "stop_id": "S04N"
- },
- {
- "arrival": {
- "time": 1620707670
- },
- "departure": {
- "time": 1620707670
- },
- "stop_id": "S03N"
- },
- {
- "arrival": {
- "time": 1620707790
- },
- "departure": {
- "time": 1620707790
- },
- "stop_id": "S01N"
- }
- ]
- }
- },
- {
- "id": "000020FS",
- "vehicle": {
- "trip": {
- "trip_id": "002950_FS..N",
- "start_time": "00:29:30",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "timestamp": 1620707370,
- "stop_id": "D26N"
- }
- },
- {
- "id": "000021FS",
- "trip_update": {
- "trip": {
- "trip_id": "004000_FS..S",
- "start_time": "00:40:00",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708000
- },
- "departure": {
- "time": 1620708000
- },
- "stop_id": "S01S"
- },
- {
- "arrival": {
- "time": 1620708120
- },
- "departure": {
- "time": 1620708120
- },
- "stop_id": "S03S"
- },
- {
- "arrival": {
- "time": 1620708210
- },
- "departure": {
- "time": 1620708210
- },
- "stop_id": "S04S"
- },
- {
- "arrival": {
- "time": 1620708390
- },
- "departure": {
- "time": 1620708390
- },
- "stop_id": "D26S"
- }
- ]
- }
- },
- {
- "id": "000022FS",
- "vehicle": {
- "trip": {
- "trip_id": "004000_FS..S",
- "start_time": "00:40:00",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "timestamp": 1620708000,
- "stop_id": "S01S"
- }
- },
- {
- "id": "000023FS",
- "trip_update": {
- "trip": {
- "trip_id": "004950_FS..N",
- "start_time": "00:49:30",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "stop_time_update": [
- {
- "arrival": {
- "time": 1620708570
- },
- "departure": {
- "time": 1620708570
- },
- "stop_id": "D26N"
- },
- {
- "arrival": {
- "time": 1620708750
- },
- "departure": {
- "time": 1620708750
- },
- "stop_id": "S04N"
- },
- {
- "arrival": {
- "time": 1620708870
- },
- "departure": {
- "time": 1620708870
- },
- "stop_id": "S03N"
- },
- {
- "arrival": {
- "time": 1620708990
- },
- "departure": {
- "time": 1620708990
- },
- "stop_id": "S01N"
- }
- ]
- }
- },
- {
- "id": "000024FS",
- "vehicle": {
- "trip": {
- "trip_id": "004950_FS..N",
- "start_time": "00:49:30",
- "start_date": "20210511",
- "route_id": "FS"
- },
- "timestamp": 1620708570,
- "stop_id": "D26N"
- }
- }
-]
\ No newline at end of file
diff --git a/justfile b/justfile
new file mode 100644
index 0000000..ec3eaf0
--- /dev/null
+++ b/justfile
@@ -0,0 +1,77 @@
+# Show available commands
+default:
+ @just --list
+
+# Setup Python project
+init:
+ uv sync
+
+# Setup frontend project
+init-ui:
+ cd mta-sign-ui && pnpm install
+
+# Build frontend and run FastAPI serving static files
+run: build-ui
+ uv run python main.py
+
+# Development mode: Next.js dev server + FastAPI backend (hot reload for both)
+dev:
+ #!/usr/bin/env bash
+ set -e
+ echo "Starting FastAPI backend on :8000..."
+ uv run python main.py &
+ BACKEND_PID=$!
+ sleep 2
+ echo "Starting Next.js dev server on :3000..."
+ cd mta-sign-ui && pnpm dev &
+ FRONTEND_PID=$!
+ trap "kill $BACKEND_PID $FRONTEND_PID 2>/dev/null" EXIT
+ echo ""
+ echo "Development servers running:"
+ echo " Frontend: http://localhost:3000 (with hot reload)"
+ echo " Backend: http://localhost:8000 (API only)"
+ echo ""
+ wait
+
+# Run only the backend (for when you want to run frontend separately)
+dev-backend:
+ FRONTEND_ENABLE=false uv run python main.py
+
+# Run only the frontend dev server
+dev-frontend:
+ cd mta-sign-ui && pnpm dev
+
+# Lint Python project with ruff
+lint:
+ uv run ruff check .
+
+# Auto fix Python lint with ruff
+lint-fix:
+ uv run ruff check . --fix
+
+# Run backend tests
+test-backend:
+ uv run pytest tests/ -v
+
+# Run frontend tests
+test-frontend:
+ cd mta-sign-ui && pnpm test
+
+# Run all tests
+test: test-backend test-frontend
+
+# Build frontend for production
+build-ui:
+ cd mta-sign-ui && pnpm build
+ rm -rf static
+ cp -r mta-sign-ui/out static
+
+# Build multi-arch container image
+containers:
+ podman build --platform linux/arm64,linux/amd64 -f docker/Dockerfile --manifest chaos2theory/pi-mta-sign:test .
+ podman manifest push --all chaos2theory/pi-mta-sign:test
+ podman manifest rm chaos2theory/pi-mta-sign:test
+
+# Build container image (local arch only)
+build-container:
+ podman build -f docker/Dockerfile -t pi-mta-sign:local .
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..514f05c
--- /dev/null
+++ b/main.py
@@ -0,0 +1,59 @@
+import logging
+import os
+from pathlib import Path
+
+import uvicorn
+from dotenv import load_dotenv
+from fastapi import FastAPI
+from fastapi.staticfiles import StaticFiles
+from fastapi.responses import FileResponse
+from starlette.middleware.cors import CORSMiddleware
+
+from mta_sign_server.router import router as default_router
+from mta_sign_server.mta.router import router as mta_router
+from mta_sign_server.config.router import router as config_router
+
+load_dotenv()
+
+app = FastAPI()
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=['*']
+)
+
+app.include_router(default_router)
+app.include_router(mta_router)
+app.include_router(config_router)
+
+logger = logging.getLogger("main")
+
+# Serve static files from the Next.js build output
+# In production, the 'static' directory contains the built frontend
+# Set FRONTEND_ENABLE=false to disable serving static files
+frontend_enabled = os.getenv("FRONTEND_ENABLE", "true").lower() not in ("false", "0", "no")
+static_dir = Path(__file__).parent / "static"
+if frontend_enabled and static_dir.exists():
+ # Serve Next.js static assets (_next directory)
+ next_static = static_dir / "_next"
+ if next_static.exists():
+ app.mount("/_next", StaticFiles(directory=str(next_static)), name="next-static")
+
+ # Serve other static files (images, etc.)
+ app.mount("/static", StaticFiles(directory=str(static_dir)), name="static")
+
+ @app.get("/")
+ async def serve_index():
+ """Serve the main index.html for the SPA"""
+ return FileResponse(static_dir / "index.html")
+
+ @app.get("/{path:path}")
+ async def serve_spa(path: str):
+ """Serve static files or fall back to index.html for SPA routing"""
+ file_path = static_dir / path
+ if file_path.exists() and file_path.is_file():
+ return FileResponse(file_path)
+ # Fall back to index.html for client-side routing
+ return FileResponse(static_dir / "index.html")
+
+if __name__ == "__main__":
+ uvicorn.run("main:app", host="0.0.0.0", port=8000, log_level="info", reload=True)
diff --git a/mta-sign-ui/.eslintrc.json b/mta-sign-ui/.eslintrc.json
new file mode 100644
index 0000000..bffb357
--- /dev/null
+++ b/mta-sign-ui/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": "next/core-web-vitals"
+}
diff --git a/mta-sign-ui/.gitignore b/mta-sign-ui/.gitignore
new file mode 100644
index 0000000..5f7aff2
--- /dev/null
+++ b/mta-sign-ui/.gitignore
@@ -0,0 +1,37 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
+
+.yarn
diff --git a/mta-sign-ui/.nvmrc b/mta-sign-ui/.nvmrc
new file mode 100644
index 0000000..85aee5a
--- /dev/null
+++ b/mta-sign-ui/.nvmrc
@@ -0,0 +1 @@
+v20
\ No newline at end of file
diff --git a/mta-sign-ui/README.md b/mta-sign-ui/README.md
new file mode 100644
index 0000000..f4da3c4
--- /dev/null
+++ b/mta-sign-ui/README.md
@@ -0,0 +1,34 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/mta-sign-ui/app/favicon.ico b/mta-sign-ui/app/favicon.ico
new file mode 100644
index 0000000..718d6fe
Binary files /dev/null and b/mta-sign-ui/app/favicon.ico differ
diff --git a/mta-sign-ui/app/globals.css b/mta-sign-ui/app/globals.css
new file mode 100644
index 0000000..670eb51
--- /dev/null
+++ b/mta-sign-ui/app/globals.css
@@ -0,0 +1,12 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+html {
+ background-color: #1f2937;
+ color: #fff;
+}
+
+body {
+ @apply bg-gray-900 text-white;
+}
diff --git a/mta-sign-ui/app/layout.tsx b/mta-sign-ui/app/layout.tsx
new file mode 100644
index 0000000..16d9408
--- /dev/null
+++ b/mta-sign-ui/app/layout.tsx
@@ -0,0 +1,19 @@
+import './globals.css'
+import type { Metadata } from 'next'
+
+export const metadata: Metadata = {
+ title: 'Pi MTA Sign!',
+ description: 'Using a raspberry pi to display subway information!',
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+ {children}
+
+ )
+}
diff --git a/mta-sign-ui/app/page.tsx b/mta-sign-ui/app/page.tsx
new file mode 100644
index 0000000..07ef653
--- /dev/null
+++ b/mta-sign-ui/app/page.tsx
@@ -0,0 +1,175 @@
+'use client'
+
+import { useState, useEffect, useCallback } from 'react'
+import { PlusIcon } from '@heroicons/react/24/outline'
+import Header from '@/components/Header'
+import StationCard from '@/components/trains/StationCard'
+import { AppConfig, StationConfig, CONFIG_VERSION } from '@/types/config'
+import axios from 'axios'
+
+const generateId = () => Math.random().toString(36).substring(2, 11)
+
+const DEFAULT_CONFIGS: StationConfig[] = [
+ { id: generateId(), stationId: '127', stationName: 'Times Sq-42 St', showNorth: true, showSouth: true, selectedLines: [] },
+ { id: generateId(), stationId: 'A27', stationName: 'Times Sq-42 St', showNorth: true, showSouth: true, selectedLines: [] },
+]
+
+const STORAGE_KEY = 'mta-sign-config'
+
+export default function Home() {
+ const [stationConfigs, setStationConfigs] = useState(DEFAULT_CONFIGS)
+ const [availableLines, setAvailableLines] = useState([])
+ const [startTime, setStartTime] = useState(null)
+ const [lastUpdated, setLastUpdated] = useState(null)
+ const [isLoaded, setIsLoaded] = useState(false)
+
+ // Load config from localStorage on mount
+ useEffect(() => {
+ if (typeof window === 'undefined') return
+ try {
+ const saved = localStorage.getItem(STORAGE_KEY)
+ if (saved) {
+ const config = JSON.parse(saved)
+ if (config.stations && Array.isArray(config.stations)) {
+ // Ensure all stations have IDs
+ const stationsWithIds = config.stations.map((s: any) => ({
+ ...s,
+ id: s.id || generateId(),
+ }))
+ setStationConfigs(stationsWithIds)
+ }
+ }
+ } catch (err) {
+ console.error('Error loading config from localStorage:', err)
+ }
+ setIsLoaded(true)
+ }, [])
+
+ useEffect(() => {
+ axios.get('/api/lines')
+ .then(response => {
+ const lines = response.data.lines || []
+ setAvailableLines(lines)
+ // Update default configs to include all lines
+ setStationConfigs(prev => prev.map(config => ({
+ ...config,
+ selectedLines: config.selectedLines.length === 0 ? lines : config.selectedLines
+ })))
+ })
+ .catch(err => console.error('Error fetching lines:', err))
+ }, [])
+
+ useEffect(() => {
+ axios.post('/api/start_time')
+ .then(response => {
+ if (response.data) {
+ setStartTime(new Date(response.data).toLocaleString('en-US'))
+ }
+ })
+ .catch(err => console.error('Error fetching start time:', err))
+ }, [])
+
+ useEffect(() => {
+ const interval = setInterval(() => {
+ setLastUpdated(new Date().toLocaleString('en-US'))
+ }, 5000)
+ return () => clearInterval(interval)
+ }, [])
+
+ // Save config to localStorage whenever it changes
+ useEffect(() => {
+ if (typeof window === 'undefined') return
+ try {
+ const configToSave = {
+ version: CONFIG_VERSION,
+ stations: stationConfigs,
+ }
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(configToSave))
+ } catch (err) {
+ console.error('Error saving config to localStorage:', err)
+ }
+ }, [stationConfigs])
+
+ const handleConfigChange = useCallback((configId: string, newConfig: StationConfig) => {
+ setStationConfigs(prevConfigs => {
+ const updated = prevConfigs.map(config => config.id === configId ? newConfig : config)
+ return updated
+ })
+ }, [])
+
+ const addStation = () => {
+ const newConfig: StationConfig = {
+ id: generateId(),
+ stationId: '',
+ stationName: '',
+ showNorth: true,
+ showSouth: true,
+ selectedLines: availableLines,
+ }
+ setStationConfigs([...stationConfigs, newConfig])
+ }
+
+ const removeStation = (configId: string) => {
+ setStationConfigs(stationConfigs.filter(config => config.id !== configId))
+ }
+
+ const exportConfig = useCallback((): AppConfig => {
+ return {
+ version: CONFIG_VERSION,
+ stations: stationConfigs,
+ }
+ }, [stationConfigs])
+
+ const importConfig = useCallback((config: AppConfig) => {
+ if (config.version !== CONFIG_VERSION) {
+ alert(`Config version mismatch. Expected ${CONFIG_VERSION}, got ${config.version}`)
+ return
+ }
+ // Ensure all stations have IDs
+ const stationsWithIds = config.stations.map(station => ({
+ ...station,
+ id: station.id || generateId(),
+ }))
+ setStationConfigs(stationsWithIds)
+ }, [])
+
+ if (availableLines.length === 0) {
+ return (
+
+ Loading...
+
+ )
+ }
+
+ return (
+
+
+
+
+ {stationConfigs.map((config) => (
+
removeStation(config.id)}
+ />
+ ))}
+
+
+
+ Add Station
+
+
+
+ )
+}
diff --git a/mta-sign-ui/components/Header.tsx b/mta-sign-ui/components/Header.tsx
new file mode 100644
index 0000000..049d57b
--- /dev/null
+++ b/mta-sign-ui/components/Header.tsx
@@ -0,0 +1,106 @@
+'use client'
+
+import { useRef } from 'react'
+import Image from 'next/image'
+import { ArrowDownTrayIcon, ArrowUpTrayIcon } from '@heroicons/react/24/outline'
+import { AppConfig } from '@/types/config'
+
+interface HeaderProps {
+ startTime: string | null
+ lastUpdated: string | null
+ onExportConfig: () => AppConfig
+ onImportConfig: (config: AppConfig) => void
+}
+
+export default function Header({ startTime, lastUpdated, onExportConfig, onImportConfig }: HeaderProps) {
+ const fileInputRef = useRef(null)
+
+ const handleExport = () => {
+ const config = onExportConfig()
+ const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' })
+ const url = URL.createObjectURL(blob)
+ const a = document.createElement('a')
+ a.href = url
+ a.download = 'mta-sign-config.json'
+ a.click()
+ URL.revokeObjectURL(url)
+ }
+
+ const handleImport = (event: React.ChangeEvent) => {
+ const file = event.target.files?.[0]
+ if (!file) return
+
+ const reader = new FileReader()
+ reader.onload = (e) => {
+ try {
+ const config = JSON.parse(e.target?.result as string) as AppConfig
+ onImportConfig(config)
+ } catch (err) {
+ console.error('Failed to parse config file:', err)
+ alert('Invalid config file')
+ }
+ }
+ reader.readAsText(file)
+
+ // Reset input so same file can be imported again
+ if (fileInputRef.current) {
+ fileInputRef.current.value = ''
+ }
+ }
+
+ return (
+
+
+
+
+
+ Pi MTA Display!
+
+
+
+
+
+
+
+
+
fileInputRef.current?.click()}
+ className="p-2 rounded-lg bg-gray-700 hover:bg-gray-600 transition-colors"
+ title="Import config"
+ >
+
+
+
+
+
+
+
+ Last Updated: {' '}
+ {lastUpdated || 'Loading...'}
+
+
+ Started: {' '}
+ {startTime || 'Loading...'}
+
+
+
+
+
+ )
+}
diff --git a/mta-sign-ui/components/StationSelector.tsx b/mta-sign-ui/components/StationSelector.tsx
new file mode 100644
index 0000000..71820ef
--- /dev/null
+++ b/mta-sign-ui/components/StationSelector.tsx
@@ -0,0 +1,108 @@
+'use client'
+
+import { useState, useEffect, useRef } from 'react'
+import { ChevronDownIcon } from '@heroicons/react/24/outline'
+import axios from 'axios'
+
+export interface Station {
+ id: string
+ name: string
+}
+
+interface StationSelectorProps {
+ selectedStation: Station | null
+ onSelect: (station: Station) => void
+}
+
+export default function StationSelector({ selectedStation, onSelect }: StationSelectorProps) {
+ const [search, setSearch] = useState('')
+ const [stations, setStations] = useState([])
+ const [isOpen, setIsOpen] = useState(false)
+ const [loading, setLoading] = useState(false)
+ const dropdownRef = useRef(null)
+
+ useEffect(() => {
+ const fetchStations = async () => {
+ setLoading(true)
+ try {
+ const params = search ? { search } : {}
+ const response = await axios.get('/api/stations', { params })
+ setStations(response.data.stations || [])
+ } catch (err) {
+ console.error('Error fetching stations:', err)
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ const debounce = setTimeout(fetchStations, 300)
+ return () => clearTimeout(debounce)
+ }, [search])
+
+ useEffect(() => {
+ const handleClickOutside = (event: MouseEvent) => {
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
+ setIsOpen(false)
+ }
+ }
+
+ document.addEventListener('mousedown', handleClickOutside)
+ return () => document.removeEventListener('mousedown', handleClickOutside)
+ }, [])
+
+ const handleSelect = (station: Station) => {
+ onSelect(station)
+ setSearch('')
+ setIsOpen(false)
+ }
+
+ return (
+
+
setIsOpen(!isOpen)}
+ >
+ {
+ setSearch(e.target.value)
+ setIsOpen(true)
+ }}
+ onClick={(e) => {
+ e.stopPropagation()
+ setIsOpen(true)
+ }}
+ className="flex-1 bg-transparent text-white placeholder-gray-400 outline-none text-sm md:text-base lg:text-lg"
+ />
+
+
+
+ {isOpen && (
+
+ {loading ? (
+
Loading...
+ ) : stations.length === 0 ? (
+
No stations found
+ ) : (
+ stations.map((station) => (
+
handleSelect(station)}
+ className={`px-3 py-2 cursor-pointer hover:bg-gray-700 transition-colors ${
+ selectedStation?.id === station.id ? 'bg-gray-700' : ''
+ }`}
+ >
+ {station.name}
+ ({station.id})
+
+ ))
+ )}
+
+ )}
+
+ )
+}
diff --git a/mta-sign-ui/components/trains/DirectionCard.tsx b/mta-sign-ui/components/trains/DirectionCard.tsx
new file mode 100644
index 0000000..263c4fd
--- /dev/null
+++ b/mta-sign-ui/components/trains/DirectionCard.tsx
@@ -0,0 +1,42 @@
+'use client'
+
+import TrainLine from './TrainLine'
+
+interface Route {
+ routeId: string
+ arrival_times: number[]
+}
+
+interface DirectionCardProps {
+ direction: 'North' | 'South'
+ routes: Route[]
+}
+
+const DirectionCard = ({ direction, routes }: DirectionCardProps) => {
+ return (
+
+
+
+ {direction}
+
+
+
+ {routes && routes.length > 0 ? (
+ routes.map((route, index) => (
+
+ ))
+ ) : (
+
+ No trains available
+
+ )}
+
+
+ )
+}
+
+export default DirectionCard
diff --git a/mta-sign-ui/components/trains/StationCard.tsx b/mta-sign-ui/components/trains/StationCard.tsx
new file mode 100644
index 0000000..7588dd6
--- /dev/null
+++ b/mta-sign-ui/components/trains/StationCard.tsx
@@ -0,0 +1,272 @@
+'use client'
+
+import { useState, useEffect, useCallback, useMemo } from 'react'
+import { XMarkIcon } from '@heroicons/react/24/outline'
+import axios from 'axios'
+import StationSelector, { Station } from '../StationSelector'
+import DirectionCard from './DirectionCard'
+import { StationConfig } from '@/types/config'
+
+interface Route {
+ routeId: string
+ arrival_times: number[]
+}
+
+interface StationData {
+ stationId: string
+ routes: Route[]
+}
+
+interface StationCardProps {
+ configId: string
+ initialConfig?: StationConfig
+ availableLines: string[]
+ onConfigChange?: (configId: string, config: StationConfig) => void
+ onRemove?: () => void
+}
+
+export default function StationCard({ configId, initialConfig, availableLines, onConfigChange, onRemove }: StationCardProps) {
+ const [selectedStation, setSelectedStation] = useState(
+ initialConfig ? { id: initialConfig.stationId, name: initialConfig.stationName } : null
+ )
+ const [showNorth, setShowNorth] = useState(initialConfig?.showNorth ?? true)
+ const [showSouth, setShowSouth] = useState(initialConfig?.showSouth ?? true)
+ const [selectedLines, setSelectedLines] = useState>(
+ new Set(initialConfig?.selectedLines ?? availableLines)
+ )
+ const [northData, setNorthData] = useState(null)
+ const [southData, setSouthData] = useState(null)
+
+ const notifyConfigChange = useCallback(() => {
+ if (onConfigChange && selectedStation) {
+ onConfigChange(configId, {
+ id: configId,
+ stationId: selectedStation.id,
+ stationName: selectedStation.name,
+ showNorth,
+ showSouth,
+ selectedLines: Array.from(selectedLines),
+ })
+ }
+ }, [configId, onConfigChange, selectedStation, showNorth, showSouth, selectedLines])
+
+ useEffect(() => {
+ notifyConfigChange()
+ }, [notifyConfigChange])
+
+ const fetchStationData = useCallback(async () => {
+ if (!selectedStation) return
+
+ try {
+ if (showNorth) {
+ const response = await axios.post(`/api/mta/${selectedStation.id}N`)
+ setNorthData(response.data)
+ }
+ if (showSouth) {
+ const response = await axios.post(`/api/mta/${selectedStation.id}S`)
+ setSouthData(response.data)
+ }
+ } catch (err) {
+ console.error('Error fetching station data:', err)
+ }
+ }, [selectedStation, showNorth, showSouth])
+
+ useEffect(() => {
+ if (selectedStation) {
+ fetchStationData()
+ const interval = setInterval(fetchStationData, 5000)
+ return () => clearInterval(interval)
+ }
+ }, [selectedStation, fetchStationData])
+
+ const availableDirections = useMemo(() => {
+ const directions = new Set()
+ if (northData && northData.routes.length > 0) directions.add('North')
+ if (southData && southData.routes.length > 0) directions.add('South')
+ return directions
+ }, [northData, southData])
+
+ const stationAvailableLines = useMemo(() => {
+ const lines = new Set()
+ if (northData) {
+ northData.routes.forEach(route => {
+ const lineId = route.routeId.replace('Route.', '')
+ lines.add(lineId)
+ })
+ }
+ if (southData) {
+ southData.routes.forEach(route => {
+ const lineId = route.routeId.replace('Route.', '')
+ lines.add(lineId)
+ })
+ }
+ return Array.from(lines).sort()
+ }, [northData, southData])
+
+ const toggleLine = (line: string) => {
+ const newSelected = new Set(selectedLines)
+ if (newSelected.has(line)) {
+ newSelected.delete(line)
+ } else {
+ newSelected.add(line)
+ }
+ setSelectedLines(newSelected)
+ }
+
+ const toggleDirection = (direction: 'North' | 'South') => {
+ if (direction === 'North') {
+ setShowNorth(!showNorth)
+ } else {
+ setShowSouth(!showSouth)
+ }
+ }
+
+ const filterRoutes = (routes: Route[]): Route[] => {
+ return routes.filter(route => {
+ const lineId = route.routeId.replace('Route.', '')
+ return selectedLines.has(lineId)
+ })
+ }
+
+ return (
+
+
+
+
+
+ )
+}
+
+interface HeaderProps {
+ selectedStation: Station | null
+ onSelectStation: (station: Station) => void
+ showNorth: boolean
+ showSouth: boolean
+ selectedLines: Set
+ availableDirections: Set
+ availableLines: string[]
+ onToggleDirection: (direction: 'North' | 'South') => void
+ onToggleLine: (line: string) => void
+ onRemove?: () => void
+}
+
+function Header({
+ selectedStation,
+ onSelectStation,
+ showNorth,
+ showSouth,
+ selectedLines,
+ availableDirections,
+ availableLines,
+ onToggleDirection,
+ onToggleLine,
+ onRemove,
+}: HeaderProps) {
+ return (
+
+
+
+
+
+
+ {availableDirections.has('North') && (
+
+ onToggleDirection('North')}
+ className="w-4 h-4 rounded"
+ />
+ N
+
+ )}
+
+ {availableDirections.has('South') && (
+
+ onToggleDirection('South')}
+ className="w-4 h-4 rounded"
+ />
+ S
+
+ )}
+
+
+ {availableLines.map(line => (
+ onToggleLine(line)}
+ className={`w-6 h-6 md:w-7 md:h-7 rounded-full text-xs font-bold transition-all ${
+ selectedLines.has(line) ? 'bg-blue-600 text-white' : 'bg-gray-600 text-gray-400'
+ }`}
+ >
+ {line}
+
+ ))}
+
+
+ {onRemove && (
+
+
+
+ )}
+
+
+ )
+}
+
+interface ContentProps {
+ selectedStation: Station | null
+ showNorth: boolean
+ showSouth: boolean
+ northRoutes: Route[]
+ southRoutes: Route[]
+}
+
+function Content({ selectedStation, showNorth, showSouth, northRoutes, southRoutes }: ContentProps) {
+ if (!selectedStation) {
+ return (
+
+ Select a station to view train arrivals
+
+ )
+ }
+
+ return (
+
+ {showNorth && (
+
+
+
+ )}
+ {showSouth && (
+
+
+
+ )}
+
+ )
+}
diff --git a/mta-sign-ui/components/trains/TrainLine.tsx b/mta-sign-ui/components/trains/TrainLine.tsx
new file mode 100644
index 0000000..250759f
--- /dev/null
+++ b/mta-sign-ui/components/trains/TrainLine.tsx
@@ -0,0 +1,43 @@
+'use client'
+
+import Image from 'next/image'
+
+interface TrainLineProps {
+ routeId: string
+ arrivalTimes: number[]
+}
+
+const TrainLine = ({ routeId, arrivalTimes }: TrainLineProps) => {
+ const formatTimes = (times: number[]): string => {
+ if (!times || times.length === 0) {
+ return 'No trains'
+ }
+ return times
+ .sort((a, b) => a - b)
+ .join(', ')
+ }
+
+ const getLineImage = (route: string): string => {
+ const cleanRoute = route.replace('Route.', '')
+ return `/images/lines/${cleanRoute}.svg`
+ }
+
+ return (
+
+
+
+
+
+ {formatTimes(arrivalTimes)}
+
+
+ )
+}
+
+export default TrainLine
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/.gitignore b/mta-sign-ui/gen-sources/mta-sign-api/.gitignore
new file mode 100644
index 0000000..149b576
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/.gitignore
@@ -0,0 +1,4 @@
+wwwroot/*.js
+node_modules
+typings
+dist
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/.npmignore b/mta-sign-ui/gen-sources/mta-sign-api/.npmignore
new file mode 100644
index 0000000..999d88d
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/.npmignore
@@ -0,0 +1 @@
+# empty npmignore to ensure all required files (e.g., in the dist folder) are published by npm
\ No newline at end of file
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator-ignore b/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator-ignore
new file mode 100644
index 0000000..7484ee5
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator-ignore
@@ -0,0 +1,23 @@
+# OpenAPI Generator Ignore
+# Generated by openapi-generator https://github.com/openapitools/openapi-generator
+
+# Use this file to prevent files from being overwritten by the generator.
+# The patterns follow closely to .gitignore or .dockerignore.
+
+# As an example, the C# client generator defines ApiClient.cs.
+# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
+#ApiClient.cs
+
+# You can match any string of characters against a directory, file or extension with a single asterisk (*):
+#foo/*/qux
+# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
+
+# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
+#foo/**/qux
+# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
+
+# You can also negate patterns with an exclamation (!).
+# For example, you can ignore all files in a docs folder with the file extension .md:
+#docs/*.md
+# Then explicitly reverse the ignore rule for a single file:
+#!docs/README.md
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator/FILES b/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator/FILES
new file mode 100644
index 0000000..a80cd4f
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator/FILES
@@ -0,0 +1,8 @@
+.gitignore
+.npmignore
+api.ts
+base.ts
+common.ts
+configuration.ts
+git_push.sh
+index.ts
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator/VERSION b/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator/VERSION
new file mode 100644
index 0000000..cd802a1
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/.openapi-generator/VERSION
@@ -0,0 +1 @@
+6.6.0
\ No newline at end of file
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/api.ts b/mta-sign-ui/gen-sources/mta-sign-api/api.ts
new file mode 100644
index 0000000..c1588ac
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/api.ts
@@ -0,0 +1,559 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FastAPI
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+import type { Configuration } from './configuration';
+import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
+import globalAxios from 'axios';
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common';
+import type { RequestArgs } from './base';
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from './base';
+
+/**
+ *
+ * @export
+ * @interface AllStationResponse
+ */
+export interface AllStationResponse {
+ /**
+ *
+ * @type {any}
+ * @memberof AllStationResponse
+ */
+ 'stations': any;
+}
+/**
+ *
+ * @export
+ * @interface HTTPValidationError
+ */
+export interface HTTPValidationError {
+ /**
+ *
+ * @type {any}
+ * @memberof HTTPValidationError
+ */
+ 'detail'?: any;
+}
+/**
+ * An enumeration.
+ * @export
+ * @interface Route
+ */
+export interface Route {
+}
+/**
+ *
+ * @export
+ * @interface RouteResponse
+ */
+export interface RouteResponse {
+ /**
+ *
+ * @type {Route}
+ * @memberof RouteResponse
+ */
+ 'routeId': Route;
+ /**
+ *
+ * @type {any}
+ * @memberof RouteResponse
+ */
+ 'arrival_times': any;
+}
+
+
+/**
+ *
+ * @export
+ * @interface StationResponse
+ */
+export interface StationResponse {
+ /**
+ *
+ * @type {any}
+ * @memberof StationResponse
+ */
+ 'stationId': any;
+ /**
+ *
+ * @type {any}
+ * @memberof StationResponse
+ */
+ 'routes': any;
+}
+/**
+ *
+ * @export
+ * @interface ValidationError
+ */
+export interface ValidationError {
+ /**
+ *
+ * @type {any}
+ * @memberof ValidationError
+ */
+ 'loc': any;
+ /**
+ *
+ * @type {any}
+ * @memberof ValidationError
+ */
+ 'msg': any;
+ /**
+ *
+ * @type {any}
+ * @memberof ValidationError
+ */
+ 'type': any;
+}
+
+/**
+ * ConfigApi - axios parameter creator
+ * @export
+ */
+export const ConfigApiAxiosParamCreator = function (configuration?: Configuration) {
+ return {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getAllApiConfigGet: async (options: AxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/config`;
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ }
+};
+
+/**
+ * ConfigApi - functional programming interface
+ * @export
+ */
+export const ConfigApiFp = function(configuration?: Configuration) {
+ const localVarAxiosParamCreator = ConfigApiAxiosParamCreator(configuration)
+ return {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async getAllApiConfigGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getAllApiConfigGet(options);
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+ },
+ }
+};
+
+/**
+ * ConfigApi - factory interface
+ * @export
+ */
+export const ConfigApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+ const localVarFp = ConfigApiFp(configuration)
+ return {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getAllApiConfigGet(options?: any): AxiosPromise {
+ return localVarFp.getAllApiConfigGet(options).then((request) => request(axios, basePath));
+ },
+ };
+};
+
+/**
+ * ConfigApi - object-oriented interface
+ * @export
+ * @class ConfigApi
+ * @extends {BaseAPI}
+ */
+export class ConfigApi extends BaseAPI {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof ConfigApi
+ */
+ public getAllApiConfigGet(options?: AxiosRequestConfig) {
+ return ConfigApiFp(this.configuration).getAllApiConfigGet(options).then((request) => request(this.axios, this.basePath));
+ }
+}
+
+
+/**
+ * MtaDataApi - axios parameter creator
+ * @export
+ */
+export const MtaDataApiAxiosParamCreator = function (configuration?: Configuration) {
+ return {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getAllApiMtaPost: async (options: AxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/mta`;
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ /**
+ *
+ * @summary Get Route
+ * @param {any} stopId
+ * @param {Route} route
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getRouteApiMtaStopIdRoutePost: async (stopId: any, route: Route, options: AxiosRequestConfig = {}): Promise => {
+ // verify required parameter 'stopId' is not null or undefined
+ assertParamExists('getRouteApiMtaStopIdRoutePost', 'stopId', stopId)
+ // verify required parameter 'route' is not null or undefined
+ assertParamExists('getRouteApiMtaStopIdRoutePost', 'route', route)
+ const localVarPath = `/api/mta/{stop_id}/{route}`
+ .replace(`{${"stop_id"}}`, encodeURIComponent(String(stopId)))
+ .replace(`{${"route"}}`, encodeURIComponent(String(route)));
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ /**
+ *
+ * @summary Get Station
+ * @param {any} stopId
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getStationApiMtaStopIdPost: async (stopId: any, options: AxiosRequestConfig = {}): Promise => {
+ // verify required parameter 'stopId' is not null or undefined
+ assertParamExists('getStationApiMtaStopIdPost', 'stopId', stopId)
+ const localVarPath = `/api/mta/{stop_id}`
+ .replace(`{${"stop_id"}}`, encodeURIComponent(String(stopId)));
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ }
+};
+
+/**
+ * MtaDataApi - functional programming interface
+ * @export
+ */
+export const MtaDataApiFp = function(configuration?: Configuration) {
+ const localVarAxiosParamCreator = MtaDataApiAxiosParamCreator(configuration)
+ return {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async getAllApiMtaPost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getAllApiMtaPost(options);
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+ },
+ /**
+ *
+ * @summary Get Route
+ * @param {any} stopId
+ * @param {Route} route
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async getRouteApiMtaStopIdRoutePost(stopId: any, route: Route, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getRouteApiMtaStopIdRoutePost(stopId, route, options);
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+ },
+ /**
+ *
+ * @summary Get Station
+ * @param {any} stopId
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async getStationApiMtaStopIdPost(stopId: any, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getStationApiMtaStopIdPost(stopId, options);
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+ },
+ }
+};
+
+/**
+ * MtaDataApi - factory interface
+ * @export
+ */
+export const MtaDataApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+ const localVarFp = MtaDataApiFp(configuration)
+ return {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getAllApiMtaPost(options?: any): AxiosPromise {
+ return localVarFp.getAllApiMtaPost(options).then((request) => request(axios, basePath));
+ },
+ /**
+ *
+ * @summary Get Route
+ * @param {any} stopId
+ * @param {Route} route
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getRouteApiMtaStopIdRoutePost(stopId: any, route: Route, options?: any): AxiosPromise {
+ return localVarFp.getRouteApiMtaStopIdRoutePost(stopId, route, options).then((request) => request(axios, basePath));
+ },
+ /**
+ *
+ * @summary Get Station
+ * @param {any} stopId
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getStationApiMtaStopIdPost(stopId: any, options?: any): AxiosPromise {
+ return localVarFp.getStationApiMtaStopIdPost(stopId, options).then((request) => request(axios, basePath));
+ },
+ };
+};
+
+/**
+ * MtaDataApi - object-oriented interface
+ * @export
+ * @class MtaDataApi
+ * @extends {BaseAPI}
+ */
+export class MtaDataApi extends BaseAPI {
+ /**
+ *
+ * @summary Get All
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof MtaDataApi
+ */
+ public getAllApiMtaPost(options?: AxiosRequestConfig) {
+ return MtaDataApiFp(this.configuration).getAllApiMtaPost(options).then((request) => request(this.axios, this.basePath));
+ }
+
+ /**
+ *
+ * @summary Get Route
+ * @param {any} stopId
+ * @param {Route} route
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof MtaDataApi
+ */
+ public getRouteApiMtaStopIdRoutePost(stopId: any, route: Route, options?: AxiosRequestConfig) {
+ return MtaDataApiFp(this.configuration).getRouteApiMtaStopIdRoutePost(stopId, route, options).then((request) => request(this.axios, this.basePath));
+ }
+
+ /**
+ *
+ * @summary Get Station
+ * @param {any} stopId
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof MtaDataApi
+ */
+ public getStationApiMtaStopIdPost(stopId: any, options?: AxiosRequestConfig) {
+ return MtaDataApiFp(this.configuration).getStationApiMtaStopIdPost(stopId, options).then((request) => request(this.axios, this.basePath));
+ }
+}
+
+
+/**
+ * StartApi - axios parameter creator
+ * @export
+ */
+export const StartApiAxiosParamCreator = function (configuration?: Configuration) {
+ return {
+ /**
+ *
+ * @summary Get Start Time
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getStartTimeApiStartTimePost: async (options: AxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/start_time`;
+ // use dummy base URL string because the URL constructor only accepts absolute URLs.
+ const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
+ let baseOptions;
+ if (configuration) {
+ baseOptions = configuration.baseOptions;
+ }
+
+ const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
+ const localVarHeaderParameter = {} as any;
+ const localVarQueryParameter = {} as any;
+
+
+
+ setSearchParams(localVarUrlObj, localVarQueryParameter);
+ let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+ localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
+ }
+};
+
+/**
+ * StartApi - functional programming interface
+ * @export
+ */
+export const StartApiFp = function(configuration?: Configuration) {
+ const localVarAxiosParamCreator = StartApiAxiosParamCreator(configuration)
+ return {
+ /**
+ *
+ * @summary Get Start Time
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async getStartTimeApiStartTimePost(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getStartTimeApiStartTimePost(options);
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+ },
+ }
+};
+
+/**
+ * StartApi - factory interface
+ * @export
+ */
+export const StartApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+ const localVarFp = StartApiFp(configuration)
+ return {
+ /**
+ *
+ * @summary Get Start Time
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getStartTimeApiStartTimePost(options?: any): AxiosPromise {
+ return localVarFp.getStartTimeApiStartTimePost(options).then((request) => request(axios, basePath));
+ },
+ };
+};
+
+/**
+ * StartApi - object-oriented interface
+ * @export
+ * @class StartApi
+ * @extends {BaseAPI}
+ */
+export class StartApi extends BaseAPI {
+ /**
+ *
+ * @summary Get Start Time
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof StartApi
+ */
+ public getStartTimeApiStartTimePost(options?: AxiosRequestConfig) {
+ return StartApiFp(this.configuration).getStartTimeApiStartTimePost(options).then((request) => request(this.axios, this.basePath));
+ }
+}
+
+
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/base.ts b/mta-sign-ui/gen-sources/mta-sign-api/base.ts
new file mode 100644
index 0000000..8e27304
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/base.ts
@@ -0,0 +1,72 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FastAPI
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+import type { Configuration } from './configuration';
+// Some imports not used depending on template conditions
+// @ts-ignore
+import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios';
+import globalAxios from 'axios';
+
+export const BASE_PATH = "http://localhost".replace(/\/+$/, "");
+
+/**
+ *
+ * @export
+ */
+export const COLLECTION_FORMATS = {
+ csv: ",",
+ ssv: " ",
+ tsv: "\t",
+ pipes: "|",
+};
+
+/**
+ *
+ * @export
+ * @interface RequestArgs
+ */
+export interface RequestArgs {
+ url: string;
+ options: AxiosRequestConfig;
+}
+
+/**
+ *
+ * @export
+ * @class BaseAPI
+ */
+export class BaseAPI {
+ protected configuration: Configuration | undefined;
+
+ constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) {
+ if (configuration) {
+ this.configuration = configuration;
+ this.basePath = configuration.basePath || this.basePath;
+ }
+ }
+};
+
+/**
+ *
+ * @export
+ * @class RequiredError
+ * @extends {Error}
+ */
+export class RequiredError extends Error {
+ constructor(public field: string, msg?: string) {
+ super(msg);
+ this.name = "RequiredError"
+ }
+}
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/common.ts b/mta-sign-ui/gen-sources/mta-sign-api/common.ts
new file mode 100644
index 0000000..3d82baa
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/common.ts
@@ -0,0 +1,150 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FastAPI
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+import type { Configuration } from "./configuration";
+import type { RequestArgs } from "./base";
+import type { AxiosInstance, AxiosResponse } from 'axios';
+import { RequiredError } from "./base";
+
+/**
+ *
+ * @export
+ */
+export const DUMMY_BASE_URL = 'https://example.com'
+
+/**
+ *
+ * @throws {RequiredError}
+ * @export
+ */
+export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) {
+ if (paramValue === null || paramValue === undefined) {
+ throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`);
+ }
+}
+
+/**
+ *
+ * @export
+ */
+export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) {
+ if (configuration && configuration.apiKey) {
+ const localVarApiKeyValue = typeof configuration.apiKey === 'function'
+ ? await configuration.apiKey(keyParamName)
+ : await configuration.apiKey;
+ object[keyParamName] = localVarApiKeyValue;
+ }
+}
+
+/**
+ *
+ * @export
+ */
+export const setBasicAuthToObject = function (object: any, configuration?: Configuration) {
+ if (configuration && (configuration.username || configuration.password)) {
+ object["auth"] = { username: configuration.username, password: configuration.password };
+ }
+}
+
+/**
+ *
+ * @export
+ */
+export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) {
+ if (configuration && configuration.accessToken) {
+ const accessToken = typeof configuration.accessToken === 'function'
+ ? await configuration.accessToken()
+ : await configuration.accessToken;
+ object["Authorization"] = "Bearer " + accessToken;
+ }
+}
+
+/**
+ *
+ * @export
+ */
+export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) {
+ if (configuration && configuration.accessToken) {
+ const localVarAccessTokenValue = typeof configuration.accessToken === 'function'
+ ? await configuration.accessToken(name, scopes)
+ : await configuration.accessToken;
+ object["Authorization"] = "Bearer " + localVarAccessTokenValue;
+ }
+}
+
+function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void {
+ if (parameter == null) return;
+ if (typeof parameter === "object") {
+ if (Array.isArray(parameter)) {
+ (parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key));
+ }
+ else {
+ Object.keys(parameter).forEach(currentKey =>
+ setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`)
+ );
+ }
+ }
+ else {
+ if (urlSearchParams.has(key)) {
+ urlSearchParams.append(key, parameter);
+ }
+ else {
+ urlSearchParams.set(key, parameter);
+ }
+ }
+}
+
+/**
+ *
+ * @export
+ */
+export const setSearchParams = function (url: URL, ...objects: any[]) {
+ const searchParams = new URLSearchParams(url.search);
+ setFlattenedQueryParams(searchParams, objects);
+ url.search = searchParams.toString();
+}
+
+/**
+ *
+ * @export
+ */
+export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) {
+ const nonString = typeof value !== 'string';
+ const needsSerialization = nonString && configuration && configuration.isJsonMime
+ ? configuration.isJsonMime(requestOptions.headers['Content-Type'])
+ : nonString;
+ return needsSerialization
+ ? JSON.stringify(value !== undefined ? value : {})
+ : (value || "");
+}
+
+/**
+ *
+ * @export
+ */
+export const toPathString = function (url: URL) {
+ return url.pathname + url.search + url.hash
+}
+
+/**
+ *
+ * @export
+ */
+export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
+ return >(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+ const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url};
+ return axios.request(axiosRequestArgs);
+ };
+}
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/configuration.ts b/mta-sign-ui/gen-sources/mta-sign-api/configuration.ts
new file mode 100644
index 0000000..fb2a6f2
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/configuration.ts
@@ -0,0 +1,101 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FastAPI
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+export interface ConfigurationParameters {
+ apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise);
+ username?: string;
+ password?: string;
+ accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise);
+ basePath?: string;
+ baseOptions?: any;
+ formDataCtor?: new () => any;
+}
+
+export class Configuration {
+ /**
+ * parameter for apiKey security
+ * @param name security name
+ * @memberof Configuration
+ */
+ apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise);
+ /**
+ * parameter for basic security
+ *
+ * @type {string}
+ * @memberof Configuration
+ */
+ username?: string;
+ /**
+ * parameter for basic security
+ *
+ * @type {string}
+ * @memberof Configuration
+ */
+ password?: string;
+ /**
+ * parameter for oauth2 security
+ * @param name security name
+ * @param scopes oauth2 scope
+ * @memberof Configuration
+ */
+ accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise);
+ /**
+ * override base path
+ *
+ * @type {string}
+ * @memberof Configuration
+ */
+ basePath?: string;
+ /**
+ * base options for axios calls
+ *
+ * @type {any}
+ * @memberof Configuration
+ */
+ baseOptions?: any;
+ /**
+ * The FormData constructor that will be used to create multipart form data
+ * requests. You can inject this here so that execution environments that
+ * do not support the FormData class can still run the generated client.
+ *
+ * @type {new () => FormData}
+ */
+ formDataCtor?: new () => any;
+
+ constructor(param: ConfigurationParameters = {}) {
+ this.apiKey = param.apiKey;
+ this.username = param.username;
+ this.password = param.password;
+ this.accessToken = param.accessToken;
+ this.basePath = param.basePath;
+ this.baseOptions = param.baseOptions;
+ this.formDataCtor = param.formDataCtor;
+ }
+
+ /**
+ * Check if the given MIME is a JSON MIME.
+ * JSON MIME examples:
+ * application/json
+ * application/json; charset=UTF8
+ * APPLICATION/JSON
+ * application/vnd.company+json
+ * @param mime - MIME (Multipurpose Internet Mail Extensions)
+ * @return True if the given MIME is JSON, false otherwise.
+ */
+ public isJsonMime(mime: string): boolean {
+ const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i');
+ return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json');
+ }
+}
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/git_push.sh b/mta-sign-ui/gen-sources/mta-sign-api/git_push.sh
new file mode 100644
index 0000000..f53a75d
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/git_push.sh
@@ -0,0 +1,57 @@
+#!/bin/sh
+# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/
+#
+# Usage example: /bin/sh ./git_push.sh wing328 openapi-petstore-perl "minor update" "gitlab.com"
+
+git_user_id=$1
+git_repo_id=$2
+release_note=$3
+git_host=$4
+
+if [ "$git_host" = "" ]; then
+ git_host="github.com"
+ echo "[INFO] No command line input provided. Set \$git_host to $git_host"
+fi
+
+if [ "$git_user_id" = "" ]; then
+ git_user_id="GIT_USER_ID"
+ echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
+fi
+
+if [ "$git_repo_id" = "" ]; then
+ git_repo_id="GIT_REPO_ID"
+ echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
+fi
+
+if [ "$release_note" = "" ]; then
+ release_note="Minor update"
+ echo "[INFO] No command line input provided. Set \$release_note to $release_note"
+fi
+
+# Initialize the local directory as a Git repository
+git init
+
+# Adds the files in the local repository and stages them for commit.
+git add .
+
+# Commits the tracked changes and prepares them to be pushed to a remote repository.
+git commit -m "$release_note"
+
+# Sets the new remote
+git_remote=$(git remote)
+if [ "$git_remote" = "" ]; then # git remote not defined
+
+ if [ "$GIT_TOKEN" = "" ]; then
+ echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment."
+ git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git
+ else
+ git remote add origin https://${git_user_id}:"${GIT_TOKEN}"@${git_host}/${git_user_id}/${git_repo_id}.git
+ fi
+
+fi
+
+git pull origin master
+
+# Pushes (Forces) the changes in the local repository up to the remote repository
+echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git"
+git push origin master 2>&1 | grep -v 'To https'
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/index.ts b/mta-sign-ui/gen-sources/mta-sign-api/index.ts
new file mode 100644
index 0000000..c7d5556
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/index.ts
@@ -0,0 +1,18 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * FastAPI
+ * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
+ *
+ * The version of the OpenAPI document: 0.1.0
+ *
+ *
+ * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * https://openapi-generator.tech
+ * Do not edit the class manually.
+ */
+
+
+export * from "./api";
+export * from "./configuration";
+
diff --git a/mta-sign-ui/gen-sources/mta-sign-api/openapi.json b/mta-sign-ui/gen-sources/mta-sign-api/openapi.json
new file mode 100644
index 0000000..086ece5
--- /dev/null
+++ b/mta-sign-ui/gen-sources/mta-sign-api/openapi.json
@@ -0,0 +1 @@
+{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/api/start_time":{"post":{"tags":["start"],"summary":"Get Start Time","operationId":"get_start_time_api_start_time_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/mta/{stop_id}/{route}":{"post":{"tags":["mta-data"],"summary":"Get Route","operationId":"get_route_api_mta__stop_id___route__post","parameters":[{"required":true,"schema":{"type":"string","title":"Stop Id"},"name":"stop_id","in":"path"},{"required":true,"schema":{"$ref":"#/components/schemas/Route"},"name":"route","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RouteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mta/{stop_id}":{"post":{"tags":["mta-data"],"summary":"Get Station","operationId":"get_station_api_mta__stop_id__post","parameters":[{"required":true,"schema":{"type":"string","title":"Stop Id"},"name":"stop_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/mta":{"post":{"tags":["mta-data"],"summary":"Get All","operationId":"get_all_api_mta_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllStationResponse"}}}}}}},"/api/config":{"get":{"tags":["config"],"summary":"Get All","operationId":"get_all_api_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AllStationResponse":{"properties":{"stations":{"items":{"$ref":"#/components/schemas/StationResponse"},"type":"array","title":"Stations"}},"type":"object","required":["stations"],"title":"AllStationResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"Route":{"enum":["A","C","E","B","D","F","M","G","J","Z","N","Q","R","W","1","2","3","4","5","6","7","L","SIR"],"title":"Route","description":"An enumeration."},"RouteResponse":{"properties":{"routeId":{"$ref":"#/components/schemas/Route"},"arrival_times":{"items":{"type":"integer"},"type":"array","title":"Arrival Times"}},"type":"object","required":["routeId","arrival_times"],"title":"RouteResponse"},"StationResponse":{"properties":{"stationId":{"type":"string","title":"Stationid"},"routes":{"items":{"$ref":"#/components/schemas/RouteResponse"},"type":"array","title":"Routes"}},"type":"object","required":["stationId","routes"],"title":"StationResponse"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}}}
\ No newline at end of file
diff --git a/mta-sign-ui/next-env.d.ts b/mta-sign-ui/next-env.d.ts
new file mode 100644
index 0000000..c4b7818
--- /dev/null
+++ b/mta-sign-ui/next-env.d.ts
@@ -0,0 +1,6 @@
+///
+///
+import "./.next/dev/types/routes.d.ts";
+
+// NOTE: This file should not be edited
+// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/mta-sign-ui/next.config.js b/mta-sign-ui/next.config.js
new file mode 100644
index 0000000..d3f84bd
--- /dev/null
+++ b/mta-sign-ui/next.config.js
@@ -0,0 +1,19 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {
+ output: 'export',
+ images: {
+ unoptimized: true,
+ },
+ // Rewrites only work during development (next dev)
+ // They are ignored during static export build
+ rewrites: async () => {
+ return [
+ {
+ source: '/api/:path*',
+ destination: 'http://localhost:8000/api/:path*',
+ },
+ ]
+ },
+}
+
+module.exports = nextConfig
diff --git a/mta-sign-ui/openapitools.json b/mta-sign-ui/openapitools.json
new file mode 100644
index 0000000..c19201d
--- /dev/null
+++ b/mta-sign-ui/openapitools.json
@@ -0,0 +1,15 @@
+{
+ "$schema": "./node_modules/@openapitools/openapi-generator-cli/config.schema.json",
+ "spaces": 2,
+ "generator-cli": {
+ "version": "6.6.0",
+ "generators": {
+ "mta-sign-api": {
+ "generatorName": "typescript-axios",
+ "output": "#{cwd}/gen-sources/mta-sign-api/",
+ "glob": "gen-sources/mta-sign-api/openapi.{json,yaml}",
+ "additionalProperties": "supportsES6=true,typescriptThreePlus=true"
+ }
+ }
+ }
+}
diff --git a/mta-sign-ui/package.json b/mta-sign-ui/package.json
new file mode 100644
index 0000000..3689345
--- /dev/null
+++ b/mta-sign-ui/package.json
@@ -0,0 +1,41 @@
+{
+ "name": "mta-sign",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "build:watch": "chokidar 'app/**/*' 'components/**/*' 'public/**/*' -c 'next build'",
+ "start": "next start",
+ "lint": "next lint",
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "gen-apis": "npx openapi-typescript http://localhost:8000/openapi.json --output gen-sources/mtaserver.ts"
+ },
+ "dependencies": {
+ "@heroicons/react": "^2.2.0",
+ "autoprefixer": "^10.4.20",
+ "axios": "^1.7.9",
+ "bootstrap": "^5.3.8",
+ "next": "^16.1.2",
+ "openapi-typescript-fetch": "^2.0.0",
+ "postcss": "^8.5.1",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "tailwindcss": "^3.4.17"
+ },
+ "devDependencies": {
+ "@testing-library/react": "^16.1.0",
+ "@types/node": "^22.10.7",
+ "@types/react": "^19.0.7",
+ "@types/react-dom": "^19.0.3",
+ "@vitejs/plugin-react": "^4.3.4",
+ "chokidar-cli": "^3.0.0",
+ "eslint": "^9.18.0",
+ "eslint-config-next": "^16.1.2",
+ "jsdom": "^26.0.0",
+ "typescript": "^5.7.3",
+ "vitest": "^3.0.0"
+ },
+ "packageManager": "pnpm@10.28.1"
+}
diff --git a/mta-sign-ui/pnpm-lock.yaml b/mta-sign-ui/pnpm-lock.yaml
new file mode 100644
index 0000000..1ca0c7b
--- /dev/null
+++ b/mta-sign-ui/pnpm-lock.yaml
@@ -0,0 +1,5742 @@
+lockfileVersion: '9.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+importers:
+
+ .:
+ dependencies:
+ '@heroicons/react':
+ specifier: ^2.2.0
+ version: 2.2.0(react@19.2.3)
+ autoprefixer:
+ specifier: ^10.4.20
+ version: 10.4.23(postcss@8.5.6)
+ axios:
+ specifier: ^1.7.9
+ version: 1.13.2
+ bootstrap:
+ specifier: ^5.3.8
+ version: 5.3.8(@popperjs/core@2.11.8)
+ next:
+ specifier: ^16.1.2
+ version: 16.1.4(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ openapi-typescript-fetch:
+ specifier: ^2.0.0
+ version: 2.2.1
+ postcss:
+ specifier: ^8.5.1
+ version: 8.5.6
+ react:
+ specifier: ^19.0.0
+ version: 19.2.3
+ react-dom:
+ specifier: ^19.0.0
+ version: 19.2.3(react@19.2.3)
+ tailwindcss:
+ specifier: ^3.4.17
+ version: 3.4.19
+ devDependencies:
+ '@testing-library/react':
+ specifier: ^16.1.0
+ version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
+ '@types/node':
+ specifier: ^22.10.7
+ version: 22.19.7
+ '@types/react':
+ specifier: ^19.0.7
+ version: 19.2.9
+ '@types/react-dom':
+ specifier: ^19.0.3
+ version: 19.2.3(@types/react@19.2.9)
+ '@vitejs/plugin-react':
+ specifier: ^4.3.4
+ version: 4.7.0(vite@7.3.1(@types/node@22.19.7)(jiti@1.21.7))
+ chokidar-cli:
+ specifier: ^3.0.0
+ version: 3.0.0
+ eslint:
+ specifier: ^9.18.0
+ version: 9.39.2(jiti@1.21.7)
+ eslint-config-next:
+ specifier: ^16.1.2
+ version: 16.1.4(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ jsdom:
+ specifier: ^26.0.0
+ version: 26.1.0
+ typescript:
+ specifier: ^5.7.3
+ version: 5.9.3
+ vitest:
+ specifier: ^3.0.0
+ version: 3.2.4(@types/node@22.19.7)(jiti@1.21.7)(jsdom@26.1.0)
+
+packages:
+
+ '@alloc/quick-lru@5.2.0':
+ resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
+ engines: {node: '>=10'}
+
+ '@asamuzakjp/css-color@3.2.0':
+ resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==}
+
+ '@babel/code-frame@7.28.6':
+ resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/compat-data@7.28.6':
+ resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/core@7.28.6':
+ resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/generator@7.28.6':
+ resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-compilation-targets@7.28.6':
+ resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-globals@7.28.0':
+ resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-imports@7.28.6':
+ resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-module-transforms@7.28.6':
+ resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+
+ '@babel/helper-plugin-utils@7.28.6':
+ resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-string-parser@7.27.1':
+ resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-identifier@7.28.5':
+ resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helper-validator-option@7.27.1':
+ resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/helpers@7.28.6':
+ resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/parser@7.28.6':
+ resolution: {integrity: sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1':
+ resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1':
+ resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+
+ '@babel/runtime@7.28.6':
+ resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/template@7.28.6':
+ resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/traverse@7.28.6':
+ resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==}
+ engines: {node: '>=6.9.0'}
+
+ '@babel/types@7.28.6':
+ resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==}
+ engines: {node: '>=6.9.0'}
+
+ '@csstools/color-helpers@5.1.0':
+ resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
+ engines: {node: '>=18'}
+
+ '@csstools/css-calc@2.1.4':
+ resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-color-parser@3.1.0':
+ resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-parser-algorithms': ^3.0.5
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-parser-algorithms@3.0.5':
+ resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@csstools/css-tokenizer': ^3.0.4
+
+ '@csstools/css-tokenizer@3.0.4':
+ resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==}
+ engines: {node: '>=18'}
+
+ '@emnapi/core@1.8.1':
+ resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==}
+
+ '@emnapi/runtime@1.8.1':
+ resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==}
+
+ '@emnapi/wasi-threads@1.1.0':
+ resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==}
+
+ '@esbuild/aix-ppc64@0.27.2':
+ resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@esbuild/android-arm64@0.27.2':
+ resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [android]
+
+ '@esbuild/android-arm@0.27.2':
+ resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [android]
+
+ '@esbuild/android-x64@0.27.2':
+ resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [android]
+
+ '@esbuild/darwin-arm64@0.27.2':
+ resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@esbuild/darwin-x64@0.27.2':
+ resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@esbuild/freebsd-arm64@0.27.2':
+ resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@esbuild/freebsd-x64@0.27.2':
+ resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@esbuild/linux-arm64@0.27.2':
+ resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@esbuild/linux-arm@0.27.2':
+ resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==}
+ engines: {node: '>=18'}
+ cpu: [arm]
+ os: [linux]
+
+ '@esbuild/linux-ia32@0.27.2':
+ resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [linux]
+
+ '@esbuild/linux-loong64@0.27.2':
+ resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==}
+ engines: {node: '>=18'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@esbuild/linux-mips64el@0.27.2':
+ resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==}
+ engines: {node: '>=18'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@esbuild/linux-ppc64@0.27.2':
+ resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==}
+ engines: {node: '>=18'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@esbuild/linux-riscv64@0.27.2':
+ resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==}
+ engines: {node: '>=18'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@esbuild/linux-s390x@0.27.2':
+ resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==}
+ engines: {node: '>=18'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@esbuild/linux-x64@0.27.2':
+ resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [linux]
+
+ '@esbuild/netbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@esbuild/netbsd-x64@0.27.2':
+ resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@esbuild/openbsd-arm64@0.27.2':
+ resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@esbuild/openbsd-x64@0.27.2':
+ resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@esbuild/openharmony-arm64@0.27.2':
+ resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.27.2':
+ resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@esbuild/win32-arm64@0.27.2':
+ resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@esbuild/win32-ia32@0.27.2':
+ resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==}
+ engines: {node: '>=18'}
+ cpu: [ia32]
+ os: [win32]
+
+ '@esbuild/win32-x64@0.27.2':
+ resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==}
+ engines: {node: '>=18'}
+ cpu: [x64]
+ os: [win32]
+
+ '@eslint-community/eslint-utils@4.9.1':
+ resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ peerDependencies:
+ eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+
+ '@eslint-community/regexpp@4.12.2':
+ resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==}
+ engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+
+ '@eslint/config-array@0.21.1':
+ resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/config-helpers@0.4.2':
+ resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/core@0.17.0':
+ resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/eslintrc@3.3.3':
+ resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/js@9.39.2':
+ resolution: {integrity: sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/object-schema@2.1.7':
+ resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/plugin-kit@0.4.1':
+ resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@heroicons/react@2.2.0':
+ resolution: {integrity: sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==}
+ peerDependencies:
+ react: '>= 16 || ^19.0.0-rc'
+
+ '@humanfs/core@0.19.1':
+ resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanfs/node@0.16.7':
+ resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==}
+ engines: {node: '>=18.18.0'}
+
+ '@humanwhocodes/module-importer@1.0.1':
+ resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+ engines: {node: '>=12.22'}
+
+ '@humanwhocodes/retry@0.4.3':
+ resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
+ engines: {node: '>=18.18'}
+
+ '@img/colour@1.0.0':
+ resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==}
+ engines: {node: '>=18'}
+
+ '@img/sharp-darwin-arm64@0.34.5':
+ resolution: {integrity: sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@img/sharp-darwin-x64@0.34.5':
+ resolution: {integrity: sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ resolution: {integrity: sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ resolution: {integrity: sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
+ cpu: [arm]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-linux-arm64@0.34.5':
+ resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-linux-arm@0.34.5':
+ resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@img/sharp-linux-ppc64@0.34.5':
+ resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@img/sharp-linux-riscv64@0.34.5':
+ resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@img/sharp-linux-s390x@0.34.5':
+ resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [s390x]
+ os: [linux]
+
+ '@img/sharp-linux-x64@0.34.5':
+ resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [linux]
+
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [linux]
+
+ '@img/sharp-wasm32@0.34.5':
+ resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [wasm32]
+
+ '@img/sharp-win32-arm64@0.34.5':
+ resolution: {integrity: sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@img/sharp-win32-ia32@0.34.5':
+ resolution: {integrity: sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [ia32]
+ os: [win32]
+
+ '@img/sharp-win32-x64@0.34.5':
+ resolution: {integrity: sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
+
+ '@jridgewell/remapping@2.3.5':
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
+
+ '@jridgewell/resolve-uri@3.1.2':
+ resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
+ engines: {node: '>=6.0.0'}
+
+ '@jridgewell/sourcemap-codec@1.5.5':
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
+
+ '@napi-rs/wasm-runtime@0.2.12':
+ resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==}
+
+ '@next/env@16.1.4':
+ resolution: {integrity: sha512-gkrXnZyxPUy0Gg6SrPQPccbNVLSP3vmW8LU5dwEttEEC1RwDivk8w4O+sZIjFvPrSICXyhQDCG+y3VmjlJf+9A==}
+
+ '@next/eslint-plugin-next@16.1.4':
+ resolution: {integrity: sha512-38WMjGP8y+1MN4bcZFs+GTcBe0iem5GGTzFE5GWW/dWdRKde7LOXH3lQT2QuoquVWyfl2S0fQRchGmeacGZ4Wg==}
+
+ '@next/swc-darwin-arm64@16.1.4':
+ resolution: {integrity: sha512-T8atLKuvk13XQUdVLCv1ZzMPgLPW0+DWWbHSQXs0/3TjPrKNxTmUIhOEaoEyl3Z82k8h/gEtqyuoZGv6+Ugawg==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@next/swc-darwin-x64@16.1.4':
+ resolution: {integrity: sha512-AKC/qVjUGUQDSPI6gESTx0xOnOPQ5gttogNS3o6bA83yiaSZJek0Am5yXy82F1KcZCx3DdOwdGPZpQCluonuxg==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@next/swc-linux-arm64-gnu@16.1.4':
+ resolution: {integrity: sha512-POQ65+pnYOkZNdngWfMEt7r53bzWiKkVNbjpmCt1Zb3V6lxJNXSsjwRuTQ8P/kguxDC8LRkqaL3vvsFrce4dMQ==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@next/swc-linux-arm64-musl@16.1.4':
+ resolution: {integrity: sha512-3Wm0zGYVCs6qDFAiSSDL+Z+r46EdtCv/2l+UlIdMbAq9hPJBvGu/rZOeuvCaIUjbArkmXac8HnTyQPJFzFWA0Q==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@next/swc-linux-x64-gnu@16.1.4':
+ resolution: {integrity: sha512-lWAYAezFinaJiD5Gv8HDidtsZdT3CDaCeqoPoJjeB57OqzvMajpIhlZFce5sCAH6VuX4mdkxCRqecCJFwfm2nQ==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@next/swc-linux-x64-musl@16.1.4':
+ resolution: {integrity: sha512-fHaIpT7x4gA6VQbdEpYUXRGyge/YbRrkG6DXM60XiBqDM2g2NcrsQaIuj375egnGFkJow4RHacgBOEsHfGbiUw==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [linux]
+
+ '@next/swc-win32-arm64-msvc@16.1.4':
+ resolution: {integrity: sha512-MCrXxrTSE7jPN1NyXJr39E+aNFBrQZtO154LoCz7n99FuKqJDekgxipoodLNWdQP7/DZ5tKMc/efybx1l159hw==}
+ engines: {node: '>= 10'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@next/swc-win32-x64-msvc@16.1.4':
+ resolution: {integrity: sha512-JSVlm9MDhmTXw/sO2PE/MRj+G6XOSMZB+BcZ0a7d6KwVFZVpkHcb2okyoYFBaco6LeiL53BBklRlOrDDbOeE5w==}
+ engines: {node: '>= 10'}
+ cpu: [x64]
+ os: [win32]
+
+ '@nodelib/fs.scandir@2.1.5':
+ resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.stat@2.0.5':
+ resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+ engines: {node: '>= 8'}
+
+ '@nodelib/fs.walk@1.2.8':
+ resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+ engines: {node: '>= 8'}
+
+ '@nolyfill/is-core-module@1.0.39':
+ resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
+ engines: {node: '>=12.4.0'}
+
+ '@popperjs/core@2.11.8':
+ resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
+
+ '@rolldown/pluginutils@1.0.0-beta.27':
+ resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==}
+
+ '@rollup/rollup-android-arm-eabi@4.55.2':
+ resolution: {integrity: sha512-21J6xzayjy3O6NdnlO6aXi/urvSRjm6nCI6+nF6ra2YofKruGixN9kfT+dt55HVNwfDmpDHJcaS3JuP/boNnlA==}
+ cpu: [arm]
+ os: [android]
+
+ '@rollup/rollup-android-arm64@4.55.2':
+ resolution: {integrity: sha512-eXBg7ibkNUZ+sTwbFiDKou0BAckeV6kIigK7y5Ko4mB/5A1KLhuzEKovsmfvsL8mQorkoincMFGnQuIT92SKqA==}
+ cpu: [arm64]
+ os: [android]
+
+ '@rollup/rollup-darwin-arm64@4.55.2':
+ resolution: {integrity: sha512-UCbaTklREjrc5U47ypLulAgg4njaqfOVLU18VrCrI+6E5MQjuG0lSWaqLlAJwsD7NpFV249XgB0Bi37Zh5Sz4g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@rollup/rollup-darwin-x64@4.55.2':
+ resolution: {integrity: sha512-dP67MA0cCMHFT2g5XyjtpVOtp7y4UyUxN3dhLdt11at5cPKnSm4lY+EhwNvDXIMzAMIo2KU+mc9wxaAQJTn7sQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@rollup/rollup-freebsd-arm64@4.55.2':
+ resolution: {integrity: sha512-WDUPLUwfYV9G1yxNRJdXcvISW15mpvod1Wv3ok+Ws93w1HjIVmCIFxsG2DquO+3usMNCpJQ0wqO+3GhFdl6Fow==}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@rollup/rollup-freebsd-x64@4.55.2':
+ resolution: {integrity: sha512-Ng95wtHVEulRwn7R0tMrlUuiLVL/HXA8Lt/MYVpy88+s5ikpntzZba1qEulTuPnPIZuOPcW9wNEiqvZxZmgmqQ==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.55.2':
+ resolution: {integrity: sha512-AEXMESUDWWGqD6LwO/HkqCZgUE1VCJ1OhbvYGsfqX2Y6w5quSXuyoy/Fg3nRqiwro+cJYFxiw5v4kB2ZDLhxrw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm-musleabihf@4.55.2':
+ resolution: {integrity: sha512-ZV7EljjBDwBBBSv570VWj0hiNTdHt9uGznDtznBB4Caj3ch5rgD4I2K1GQrtbvJ/QiB+663lLgOdcADMNVC29Q==}
+ cpu: [arm]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-gnu@4.55.2':
+ resolution: {integrity: sha512-uvjwc8NtQVPAJtq4Tt7Q49FOodjfbf6NpqXyW/rjXoV+iZ3EJAHLNAnKT5UJBc6ffQVgmXTUL2ifYiLABlGFqA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-arm64-musl@4.55.2':
+ resolution: {integrity: sha512-s3KoWVNnye9mm/2WpOZ3JeUiediUVw6AvY/H7jNA6qgKA2V2aM25lMkVarTDfiicn/DLq3O0a81jncXszoyCFA==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-gnu@4.55.2':
+ resolution: {integrity: sha512-gi21faacK+J8aVSyAUptML9VQN26JRxe484IbF+h3hpG+sNVoMXPduhREz2CcYr5my0NE3MjVvQ5bMKX71pfVA==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-loong64-musl@4.55.2':
+ resolution: {integrity: sha512-qSlWiXnVaS/ceqXNfnoFZh4IiCA0EwvCivivTGbEu1qv2o+WTHpn1zNmCTAoOG5QaVr2/yhCoLScQtc/7RxshA==}
+ cpu: [loong64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-gnu@4.55.2':
+ resolution: {integrity: sha512-rPyuLFNoF1B0+wolH277E780NUKf+KoEDb3OyoLbAO18BbeKi++YN6gC/zuJoPPDlQRL3fIxHxCxVEWiem2yXw==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-ppc64-musl@4.55.2':
+ resolution: {integrity: sha512-g+0ZLMook31iWV4PvqKU0i9E78gaZgYpSrYPed/4Bu+nGTgfOPtfs1h11tSSRPXSjC5EzLTjV/1A7L2Vr8pJoQ==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-gnu@4.55.2':
+ resolution: {integrity: sha512-i+sGeRGsjKZcQRh3BRfpLsM3LX3bi4AoEVqmGDyc50L6KfYsN45wVCSz70iQMwPWr3E5opSiLOwsC9WB4/1pqg==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-riscv64-musl@4.55.2':
+ resolution: {integrity: sha512-C1vLcKc4MfFV6I0aWsC7B2Y9QcsiEcvKkfxprwkPfLaN8hQf0/fKHwSF2lcYzA9g4imqnhic729VB9Fo70HO3Q==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@rollup/rollup-linux-s390x-gnu@4.55.2':
+ resolution: {integrity: sha512-68gHUK/howpQjh7g7hlD9DvTTt4sNLp1Bb+Yzw2Ki0xvscm2cOdCLZNJNhd2jW8lsTPrHAHuF751BygifW4bkQ==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-gnu@4.55.2':
+ resolution: {integrity: sha512-1e30XAuaBP1MAizaOBApsgeGZge2/Byd6wV4a8oa6jPdHELbRHBiw7wvo4dp7Ie2PE8TZT4pj9RLGZv9N4qwlw==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-linux-x64-musl@4.55.2':
+ resolution: {integrity: sha512-4BJucJBGbuGnH6q7kpPqGJGzZnYrpAzRd60HQSt3OpX/6/YVgSsJnNzR8Ot74io50SeVT4CtCWe/RYIAymFPwA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@rollup/rollup-openbsd-x64@4.55.2':
+ resolution: {integrity: sha512-cT2MmXySMo58ENv8p6/O6wI/h/gLnD3D6JoajwXFZH6X9jz4hARqUhWpGuQhOgLNXscfZYRQMJvZDtWNzMAIDw==}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@rollup/rollup-openharmony-arm64@4.55.2':
+ resolution: {integrity: sha512-sZnyUgGkuzIXaK3jNMPmUIyJrxu/PjmATQrocpGA1WbCPX8H5tfGgRSuYtqBYAvLuIGp8SPRb1O4d1Fkb5fXaQ==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@rollup/rollup-win32-arm64-msvc@4.55.2':
+ resolution: {integrity: sha512-sDpFbenhmWjNcEbBcoTV0PWvW5rPJFvu+P7XoTY0YLGRupgLbFY0XPfwIbJOObzO7QgkRDANh65RjhPmgSaAjQ==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@rollup/rollup-win32-ia32-msvc@4.55.2':
+ resolution: {integrity: sha512-GvJ03TqqaweWCigtKQVBErw2bEhu1tyfNQbarwr94wCGnczA9HF8wqEe3U/Lfu6EdeNP0p6R+APeHVwEqVxpUQ==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-gnu@4.55.2':
+ resolution: {integrity: sha512-KvXsBvp13oZz9JGe5NYS7FNizLe99Ny+W8ETsuCyjXiKdiGrcz2/J/N8qxZ/RSwivqjQguug07NLHqrIHrqfYw==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rollup/rollup-win32-x64-msvc@4.55.2':
+ resolution: {integrity: sha512-xNO+fksQhsAckRtDSPWaMeT1uIM+JrDRXlerpnWNXhn1TdB3YZ6uKBMBTKP0eX9XtYEP978hHk1f8332i2AW8Q==}
+ cpu: [x64]
+ os: [win32]
+
+ '@rtsao/scc@1.1.0':
+ resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
+
+ '@swc/helpers@0.5.15':
+ resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==}
+
+ '@testing-library/dom@10.4.1':
+ resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
+ engines: {node: '>=18'}
+
+ '@testing-library/react@16.3.2':
+ resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@testing-library/dom': ^10.0.0
+ '@types/react': ^18.0.0 || ^19.0.0
+ '@types/react-dom': ^18.0.0 || ^19.0.0
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@tybys/wasm-util@0.10.1':
+ resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
+
+ '@types/aria-query@5.0.4':
+ resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
+
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
+ '@types/chai@5.2.3':
+ resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
+
+ '@types/deep-eql@4.0.2':
+ resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==}
+
+ '@types/estree@1.0.8':
+ resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
+
+ '@types/json-schema@7.0.15':
+ resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+
+ '@types/json5@0.0.29':
+ resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
+
+ '@types/node@22.19.7':
+ resolution: {integrity: sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==}
+
+ '@types/react-dom@19.2.3':
+ resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==}
+ peerDependencies:
+ '@types/react': ^19.2.0
+
+ '@types/react@19.2.9':
+ resolution: {integrity: sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==}
+
+ '@typescript-eslint/eslint-plugin@8.53.1':
+ resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ '@typescript-eslint/parser': ^8.53.1
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/parser@8.53.1':
+ resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/project-service@8.53.1':
+ resolution: {integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/scope-manager@8.53.1':
+ resolution: {integrity: sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/tsconfig-utils@8.53.1':
+ resolution: {integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/type-utils@8.53.1':
+ resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/types@8.53.1':
+ resolution: {integrity: sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@typescript-eslint/typescript-estree@8.53.1':
+ resolution: {integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/utils@8.53.1':
+ resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ '@typescript-eslint/visitor-keys@8.53.1':
+ resolution: {integrity: sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@unrs/resolver-binding-android-arm-eabi@1.11.1':
+ resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==}
+ cpu: [arm]
+ os: [android]
+
+ '@unrs/resolver-binding-android-arm64@1.11.1':
+ resolution: {integrity: sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==}
+ cpu: [arm64]
+ os: [android]
+
+ '@unrs/resolver-binding-darwin-arm64@1.11.1':
+ resolution: {integrity: sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@unrs/resolver-binding-darwin-x64@1.11.1':
+ resolution: {integrity: sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@unrs/resolver-binding-freebsd-x64@1.11.1':
+ resolution: {integrity: sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
+ resolution: {integrity: sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
+ resolution: {integrity: sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==}
+ cpu: [arm]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
+ resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
+ resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
+ cpu: [arm64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
+ resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
+ resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
+ resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
+ resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
+ cpu: [s390x]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
+ resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
+ cpu: [x64]
+ os: [linux]
+
+ '@unrs/resolver-binding-linux-x64-musl@1.11.1':
+ resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
+ cpu: [x64]
+ os: [linux]
+
+ '@unrs/resolver-binding-wasm32-wasi@1.11.1':
+ resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
+ resolution: {integrity: sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
+ resolution: {integrity: sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==}
+ cpu: [ia32]
+ os: [win32]
+
+ '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
+ resolution: {integrity: sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==}
+ cpu: [x64]
+ os: [win32]
+
+ '@vitejs/plugin-react@4.7.0':
+ resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
+
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
+
+ '@vitest/mocker@3.2.4':
+ resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==}
+ peerDependencies:
+ msw: ^2.4.9
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0
+ peerDependenciesMeta:
+ msw:
+ optional: true
+ vite:
+ optional: true
+
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
+
+ '@vitest/runner@3.2.4':
+ resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==}
+
+ '@vitest/snapshot@3.2.4':
+ resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==}
+
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
+
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
+
+ acorn-jsx@5.3.2:
+ resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+ peerDependencies:
+ acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ acorn@8.15.0:
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
+ agent-base@7.1.4:
+ resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
+ engines: {node: '>= 14'}
+
+ ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+
+ ansi-regex@4.1.1:
+ resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
+ engines: {node: '>=6'}
+
+ ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+
+ ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+
+ ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+
+ ansi-styles@5.2.0:
+ resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
+ engines: {node: '>=10'}
+
+ any-promise@1.3.0:
+ resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
+ anymatch@3.1.3:
+ resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
+ engines: {node: '>= 8'}
+
+ arg@5.0.2:
+ resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==}
+
+ argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+
+ aria-query@5.3.0:
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+
+ aria-query@5.3.2:
+ resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==}
+ engines: {node: '>= 0.4'}
+
+ array-buffer-byte-length@1.0.2:
+ resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==}
+ engines: {node: '>= 0.4'}
+
+ array-includes@3.1.9:
+ resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.findlast@1.2.5:
+ resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.findlastindex@1.2.6:
+ resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.flat@1.3.3:
+ resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.flatmap@1.3.3:
+ resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==}
+ engines: {node: '>= 0.4'}
+
+ array.prototype.tosorted@1.1.4:
+ resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==}
+ engines: {node: '>= 0.4'}
+
+ arraybuffer.prototype.slice@1.0.4:
+ resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==}
+ engines: {node: '>= 0.4'}
+
+ assertion-error@2.0.1:
+ resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
+ engines: {node: '>=12'}
+
+ ast-types-flow@0.0.8:
+ resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+
+ async-function@1.0.0:
+ resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
+ engines: {node: '>= 0.4'}
+
+ asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+
+ autoprefixer@10.4.23:
+ resolution: {integrity: sha512-YYTXSFulfwytnjAPlw8QHncHJmlvFKtczb8InXaAx9Q0LbfDnfEYDE55omerIJKihhmU61Ft+cAOSzQVaBUmeA==}
+ engines: {node: ^10 || ^12 || >=14}
+ hasBin: true
+ peerDependencies:
+ postcss: ^8.1.0
+
+ available-typed-arrays@1.0.7:
+ resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==}
+ engines: {node: '>= 0.4'}
+
+ axe-core@4.11.1:
+ resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==}
+ engines: {node: '>=4'}
+
+ axios@1.13.2:
+ resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==}
+
+ axobject-query@4.1.0:
+ resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==}
+ engines: {node: '>= 0.4'}
+
+ balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+
+ baseline-browser-mapping@2.9.16:
+ resolution: {integrity: sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==}
+ hasBin: true
+
+ binary-extensions@2.3.0:
+ resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
+ engines: {node: '>=8'}
+
+ bootstrap@5.3.8:
+ resolution: {integrity: sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==}
+ peerDependencies:
+ '@popperjs/core': ^2.11.8
+
+ brace-expansion@1.1.12:
+ resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==}
+
+ brace-expansion@2.0.2:
+ resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==}
+
+ braces@3.0.3:
+ resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
+ engines: {node: '>=8'}
+
+ browserslist@4.28.1:
+ resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+
+ cac@6.7.14:
+ resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
+ engines: {node: '>=8'}
+
+ call-bind-apply-helpers@1.0.2:
+ resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
+ engines: {node: '>= 0.4'}
+
+ call-bind@1.0.8:
+ resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
+ engines: {node: '>= 0.4'}
+
+ call-bound@1.0.4:
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
+ engines: {node: '>= 0.4'}
+
+ callsites@3.1.0:
+ resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+ engines: {node: '>=6'}
+
+ camelcase-css@2.0.1:
+ resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
+ engines: {node: '>= 6'}
+
+ camelcase@5.3.1:
+ resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+ engines: {node: '>=6'}
+
+ caniuse-lite@1.0.30001765:
+ resolution: {integrity: sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==}
+
+ chai@5.3.3:
+ resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
+ engines: {node: '>=18'}
+
+ chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+
+ check-error@2.1.3:
+ resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
+ engines: {node: '>= 16'}
+
+ chokidar-cli@3.0.0:
+ resolution: {integrity: sha512-xVW+Qeh7z15uZRxHOkP93Ux8A0xbPzwK4GaqD8dQOYc34TlkqUhVSS59fK36DOp5WdJlrRzlYSy02Ht99FjZqQ==}
+ engines: {node: '>= 8.10.0'}
+ hasBin: true
+
+ chokidar@3.6.0:
+ resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
+ engines: {node: '>= 8.10.0'}
+
+ client-only@0.0.1:
+ resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
+
+ cliui@5.0.0:
+ resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==}
+
+ color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+
+ color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+
+ color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+
+ color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+
+ combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+
+ commander@4.1.1:
+ resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+ engines: {node: '>= 6'}
+
+ concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+
+ convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+
+ cross-spawn@7.0.6:
+ resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
+ engines: {node: '>= 8'}
+
+ cssesc@3.0.0:
+ resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
+ engines: {node: '>=4'}
+ hasBin: true
+
+ cssstyle@4.6.0:
+ resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==}
+ engines: {node: '>=18'}
+
+ csstype@3.2.3:
+ resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==}
+
+ damerau-levenshtein@1.0.8:
+ resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
+
+ data-urls@5.0.0:
+ resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==}
+ engines: {node: '>=18'}
+
+ data-view-buffer@1.0.2:
+ resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==}
+ engines: {node: '>= 0.4'}
+
+ data-view-byte-length@1.0.2:
+ resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==}
+ engines: {node: '>= 0.4'}
+
+ data-view-byte-offset@1.0.1:
+ resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==}
+ engines: {node: '>= 0.4'}
+
+ debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ debug@4.4.3:
+ resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
+ decamelize@1.2.0:
+ resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+ engines: {node: '>=0.10.0'}
+
+ decimal.js@10.6.0:
+ resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+
+ deep-eql@5.0.2:
+ resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
+ engines: {node: '>=6'}
+
+ deep-is@0.1.4:
+ resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+
+ define-data-property@1.1.4:
+ resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
+ engines: {node: '>= 0.4'}
+
+ define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+
+ delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
+ detect-libc@2.1.2:
+ resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
+ engines: {node: '>=8'}
+
+ didyoumean@1.2.2:
+ resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
+
+ dlv@1.1.3:
+ resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
+
+ doctrine@2.1.0:
+ resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
+ engines: {node: '>=0.10.0'}
+
+ dom-accessibility-api@0.5.16:
+ resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
+
+ dunder-proto@1.0.1:
+ resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
+ engines: {node: '>= 0.4'}
+
+ electron-to-chromium@1.5.267:
+ resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==}
+
+ emoji-regex@7.0.3:
+ resolution: {integrity: sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==}
+
+ emoji-regex@9.2.2:
+ resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
+
+ entities@6.0.1:
+ resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
+ engines: {node: '>=0.12'}
+
+ es-abstract@1.24.1:
+ resolution: {integrity: sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==}
+ engines: {node: '>= 0.4'}
+
+ es-define-property@1.0.1:
+ resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==}
+ engines: {node: '>= 0.4'}
+
+ es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+
+ es-iterator-helpers@1.2.2:
+ resolution: {integrity: sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==}
+ engines: {node: '>= 0.4'}
+
+ es-module-lexer@1.7.0:
+ resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==}
+
+ es-object-atoms@1.1.1:
+ resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
+ engines: {node: '>= 0.4'}
+
+ es-set-tostringtag@2.1.0:
+ resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==}
+ engines: {node: '>= 0.4'}
+
+ es-shim-unscopables@1.1.0:
+ resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==}
+ engines: {node: '>= 0.4'}
+
+ es-to-primitive@1.3.0:
+ resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==}
+ engines: {node: '>= 0.4'}
+
+ esbuild@0.27.2:
+ resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==}
+ engines: {node: '>=18'}
+ hasBin: true
+
+ escalade@3.2.0:
+ resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
+ engines: {node: '>=6'}
+
+ escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+
+ eslint-config-next@16.1.4:
+ resolution: {integrity: sha512-iCrrNolUPpn/ythx0HcyNRfUBgTkaNBXByisKUbusPGCl8DMkDXXAu7exlSTSLGTIsH9lFE/c4s/3Qiyv2qwdA==}
+ peerDependencies:
+ eslint: '>=9.0.0'
+ typescript: '>=3.3.1'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ eslint-import-resolver-node@0.3.9:
+ resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
+
+ eslint-import-resolver-typescript@3.10.1:
+ resolution: {integrity: sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ eslint: '*'
+ eslint-plugin-import: '*'
+ eslint-plugin-import-x: '*'
+ peerDependenciesMeta:
+ eslint-plugin-import:
+ optional: true
+ eslint-plugin-import-x:
+ optional: true
+
+ eslint-module-utils@2.12.1:
+ resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: '*'
+ eslint-import-resolver-node: '*'
+ eslint-import-resolver-typescript: '*'
+ eslint-import-resolver-webpack: '*'
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+ eslint:
+ optional: true
+ eslint-import-resolver-node:
+ optional: true
+ eslint-import-resolver-typescript:
+ optional: true
+ eslint-import-resolver-webpack:
+ optional: true
+
+ eslint-plugin-import@2.32.0:
+ resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ '@typescript-eslint/parser': '*'
+ eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9
+ peerDependenciesMeta:
+ '@typescript-eslint/parser':
+ optional: true
+
+ eslint-plugin-jsx-a11y@6.10.2:
+ resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9
+
+ eslint-plugin-react-hooks@7.0.1:
+ resolution: {integrity: sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0
+
+ eslint-plugin-react@7.37.5:
+ resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==}
+ engines: {node: '>=4'}
+ peerDependencies:
+ eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+
+ eslint-scope@8.4.0:
+ resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint-visitor-keys@3.4.3:
+ resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+ engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+
+ eslint-visitor-keys@4.2.1:
+ resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint@9.39.2:
+ resolution: {integrity: sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ hasBin: true
+ peerDependencies:
+ jiti: '*'
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+
+ espree@10.4.0:
+ resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ esquery@1.7.0:
+ resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==}
+ engines: {node: '>=0.10'}
+
+ esrecurse@4.3.0:
+ resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+ engines: {node: '>=4.0'}
+
+ estraverse@5.3.0:
+ resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+ engines: {node: '>=4.0'}
+
+ estree-walker@3.0.3:
+ resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
+
+ esutils@2.0.3:
+ resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+ engines: {node: '>=0.10.0'}
+
+ expect-type@1.3.0:
+ resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
+ engines: {node: '>=12.0.0'}
+
+ fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+
+ fast-glob@3.3.1:
+ resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==}
+ engines: {node: '>=8.6.0'}
+
+ fast-glob@3.3.3:
+ resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==}
+ engines: {node: '>=8.6.0'}
+
+ fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+
+ fast-levenshtein@2.0.6:
+ resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+
+ fastq@1.20.1:
+ resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==}
+
+ fdir@6.5.0:
+ resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
+ engines: {node: '>=12.0.0'}
+ peerDependencies:
+ picomatch: ^3 || ^4
+ peerDependenciesMeta:
+ picomatch:
+ optional: true
+
+ file-entry-cache@8.0.0:
+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+ engines: {node: '>=16.0.0'}
+
+ fill-range@7.1.1:
+ resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
+ engines: {node: '>=8'}
+
+ find-up@3.0.0:
+ resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
+ engines: {node: '>=6'}
+
+ find-up@5.0.0:
+ resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+ engines: {node: '>=10'}
+
+ flat-cache@4.0.1:
+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+ engines: {node: '>=16'}
+
+ flatted@3.3.3:
+ resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
+
+ follow-redirects@1.15.11:
+ resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+
+ for-each@0.3.5:
+ resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==}
+ engines: {node: '>= 0.4'}
+
+ form-data@4.0.5:
+ resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==}
+ engines: {node: '>= 6'}
+
+ fraction.js@5.3.4:
+ resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==}
+
+ fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+
+ function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+
+ function.prototype.name@1.1.8:
+ resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==}
+ engines: {node: '>= 0.4'}
+
+ functions-have-names@1.2.3:
+ resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
+
+ generator-function@2.0.1:
+ resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==}
+ engines: {node: '>= 0.4'}
+
+ gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+
+ get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+
+ get-intrinsic@1.3.0:
+ resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
+ engines: {node: '>= 0.4'}
+
+ get-proto@1.0.1:
+ resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
+ engines: {node: '>= 0.4'}
+
+ get-symbol-description@1.1.0:
+ resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==}
+ engines: {node: '>= 0.4'}
+
+ get-tsconfig@4.13.0:
+ resolution: {integrity: sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==}
+
+ glob-parent@5.1.2:
+ resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+ engines: {node: '>= 6'}
+
+ glob-parent@6.0.2:
+ resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+ engines: {node: '>=10.13.0'}
+
+ globals@14.0.0:
+ resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+ engines: {node: '>=18'}
+
+ globals@16.4.0:
+ resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==}
+ engines: {node: '>=18'}
+
+ globalthis@1.0.4:
+ resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==}
+ engines: {node: '>= 0.4'}
+
+ gopd@1.2.0:
+ resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==}
+ engines: {node: '>= 0.4'}
+
+ has-bigints@1.1.0:
+ resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
+ engines: {node: '>= 0.4'}
+
+ has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+
+ has-property-descriptors@1.0.2:
+ resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
+
+ has-proto@1.2.0:
+ resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==}
+ engines: {node: '>= 0.4'}
+
+ has-symbols@1.1.0:
+ resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==}
+ engines: {node: '>= 0.4'}
+
+ has-tostringtag@1.0.2:
+ resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==}
+ engines: {node: '>= 0.4'}
+
+ hasown@2.0.2:
+ resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+ engines: {node: '>= 0.4'}
+
+ hermes-estree@0.25.1:
+ resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
+
+ hermes-parser@0.25.1:
+ resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
+
+ html-encoding-sniffer@4.0.0:
+ resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
+ engines: {node: '>=18'}
+
+ http-proxy-agent@7.0.2:
+ resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
+ engines: {node: '>= 14'}
+
+ https-proxy-agent@7.0.6:
+ resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
+ engines: {node: '>= 14'}
+
+ iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+
+ ignore@5.3.2:
+ resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
+ engines: {node: '>= 4'}
+
+ ignore@7.0.5:
+ resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
+ engines: {node: '>= 4'}
+
+ import-fresh@3.3.1:
+ resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
+ engines: {node: '>=6'}
+
+ imurmurhash@0.1.4:
+ resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+ engines: {node: '>=0.8.19'}
+
+ internal-slot@1.1.0:
+ resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==}
+ engines: {node: '>= 0.4'}
+
+ is-array-buffer@3.0.5:
+ resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
+ engines: {node: '>= 0.4'}
+
+ is-async-function@2.1.1:
+ resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
+ engines: {node: '>= 0.4'}
+
+ is-bigint@1.1.0:
+ resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==}
+ engines: {node: '>= 0.4'}
+
+ is-binary-path@2.1.0:
+ resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
+ engines: {node: '>=8'}
+
+ is-boolean-object@1.2.2:
+ resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==}
+ engines: {node: '>= 0.4'}
+
+ is-bun-module@2.0.0:
+ resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
+
+ is-callable@1.2.7:
+ resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
+ engines: {node: '>= 0.4'}
+
+ is-core-module@2.16.1:
+ resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==}
+ engines: {node: '>= 0.4'}
+
+ is-data-view@1.0.2:
+ resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==}
+ engines: {node: '>= 0.4'}
+
+ is-date-object@1.1.0:
+ resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==}
+ engines: {node: '>= 0.4'}
+
+ is-extglob@2.1.1:
+ resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+ engines: {node: '>=0.10.0'}
+
+ is-finalizationregistry@1.1.1:
+ resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==}
+ engines: {node: '>= 0.4'}
+
+ is-fullwidth-code-point@2.0.0:
+ resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==}
+ engines: {node: '>=4'}
+
+ is-generator-function@1.1.2:
+ resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
+ engines: {node: '>= 0.4'}
+
+ is-glob@4.0.3:
+ resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+ engines: {node: '>=0.10.0'}
+
+ is-map@2.0.3:
+ resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==}
+ engines: {node: '>= 0.4'}
+
+ is-negative-zero@2.0.3:
+ resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
+ engines: {node: '>= 0.4'}
+
+ is-number-object@1.1.1:
+ resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==}
+ engines: {node: '>= 0.4'}
+
+ is-number@7.0.0:
+ resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+ engines: {node: '>=0.12.0'}
+
+ is-potential-custom-element-name@1.0.1:
+ resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
+
+ is-regex@1.2.1:
+ resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==}
+ engines: {node: '>= 0.4'}
+
+ is-set@2.0.3:
+ resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==}
+ engines: {node: '>= 0.4'}
+
+ is-shared-array-buffer@1.0.4:
+ resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==}
+ engines: {node: '>= 0.4'}
+
+ is-string@1.1.1:
+ resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==}
+ engines: {node: '>= 0.4'}
+
+ is-symbol@1.1.1:
+ resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==}
+ engines: {node: '>= 0.4'}
+
+ is-typed-array@1.1.15:
+ resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
+ engines: {node: '>= 0.4'}
+
+ is-weakmap@2.0.2:
+ resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==}
+ engines: {node: '>= 0.4'}
+
+ is-weakref@1.1.1:
+ resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==}
+ engines: {node: '>= 0.4'}
+
+ is-weakset@2.0.4:
+ resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
+ engines: {node: '>= 0.4'}
+
+ isarray@2.0.5:
+ resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==}
+
+ isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+
+ iterator.prototype@1.1.5:
+ resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==}
+ engines: {node: '>= 0.4'}
+
+ jiti@1.21.7:
+ resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==}
+ hasBin: true
+
+ js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+
+ js-tokens@9.0.1:
+ resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==}
+
+ js-yaml@4.1.1:
+ resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==}
+ hasBin: true
+
+ jsdom@26.1.0:
+ resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ canvas: ^3.0.0
+ peerDependenciesMeta:
+ canvas:
+ optional: true
+
+ jsesc@3.1.0:
+ resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ json-buffer@3.0.1:
+ resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+
+ json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+
+ json-stable-stringify-without-jsonify@1.0.1:
+ resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+
+ json5@1.0.2:
+ resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==}
+ hasBin: true
+
+ json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+
+ jsx-ast-utils@3.3.5:
+ resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
+ engines: {node: '>=4.0'}
+
+ keyv@4.5.4:
+ resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+
+ language-subtag-registry@0.3.23:
+ resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==}
+
+ language-tags@1.0.9:
+ resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==}
+ engines: {node: '>=0.10'}
+
+ levn@0.4.1:
+ resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+ engines: {node: '>= 0.8.0'}
+
+ lilconfig@3.1.3:
+ resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
+ engines: {node: '>=14'}
+
+ lines-and-columns@1.2.4:
+ resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+
+ locate-path@3.0.0:
+ resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
+ engines: {node: '>=6'}
+
+ locate-path@6.0.0:
+ resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+ engines: {node: '>=10'}
+
+ lodash.debounce@4.0.8:
+ resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
+
+ lodash.merge@4.6.2:
+ resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+
+ lodash.throttle@4.1.1:
+ resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==}
+
+ loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
+
+ lru-cache@10.4.3:
+ resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
+
+ lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+
+ lz-string@1.5.0:
+ resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==}
+ hasBin: true
+
+ magic-string@0.30.21:
+ resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
+
+ math-intrinsics@1.1.0:
+ resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
+ engines: {node: '>= 0.4'}
+
+ merge2@1.4.1:
+ resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+ engines: {node: '>= 8'}
+
+ micromatch@4.0.8:
+ resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
+ engines: {node: '>=8.6'}
+
+ mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+
+ mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+
+ minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+
+ minimatch@9.0.5:
+ resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
+ engines: {node: '>=16 || 14 >=14.17'}
+
+ minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+
+ ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+
+ mz@2.7.0:
+ resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
+ nanoid@3.3.11:
+ resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+
+ napi-postinstall@0.3.4:
+ resolution: {integrity: sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==}
+ engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ hasBin: true
+
+ natural-compare@1.4.0:
+ resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+
+ next@16.1.4:
+ resolution: {integrity: sha512-gKSecROqisnV7Buen5BfjmXAm7Xlpx9o2ueVQRo5DxQcjC8d330dOM1xiGWc2k3Dcnz0In3VybyRPOsudwgiqQ==}
+ engines: {node: '>=20.9.0'}
+ hasBin: true
+ peerDependencies:
+ '@opentelemetry/api': ^1.1.0
+ '@playwright/test': ^1.51.1
+ babel-plugin-react-compiler: '*'
+ react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
+ react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
+ sass: ^1.3.0
+ peerDependenciesMeta:
+ '@opentelemetry/api':
+ optional: true
+ '@playwright/test':
+ optional: true
+ babel-plugin-react-compiler:
+ optional: true
+ sass:
+ optional: true
+
+ node-releases@2.0.27:
+ resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==}
+
+ normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+
+ nwsapi@2.2.23:
+ resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==}
+
+ object-assign@4.1.1:
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
+ engines: {node: '>=0.10.0'}
+
+ object-hash@3.0.0:
+ resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==}
+ engines: {node: '>= 6'}
+
+ object-inspect@1.13.4:
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
+ engines: {node: '>= 0.4'}
+
+ object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+
+ object.assign@4.1.7:
+ resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==}
+ engines: {node: '>= 0.4'}
+
+ object.entries@1.1.9:
+ resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==}
+ engines: {node: '>= 0.4'}
+
+ object.fromentries@2.0.8:
+ resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==}
+ engines: {node: '>= 0.4'}
+
+ object.groupby@1.0.3:
+ resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==}
+ engines: {node: '>= 0.4'}
+
+ object.values@1.2.1:
+ resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==}
+ engines: {node: '>= 0.4'}
+
+ openapi-typescript-fetch@2.2.1:
+ resolution: {integrity: sha512-aBp1cR5FTNxp4HA8bb2ST53aIqEiJgoOMyXiyzKi6YF7vogW8KkyyUQ1FeDz8D05uspxFrKvFbkVU2YiiKkULA==}
+ engines: {node: '>= 12.0.0', npm: '>= 7.0.0'}
+
+ optionator@0.9.4:
+ resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+ engines: {node: '>= 0.8.0'}
+
+ own-keys@1.0.1:
+ resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==}
+ engines: {node: '>= 0.4'}
+
+ p-limit@2.3.0:
+ resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+ engines: {node: '>=6'}
+
+ p-limit@3.1.0:
+ resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+ engines: {node: '>=10'}
+
+ p-locate@3.0.0:
+ resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==}
+ engines: {node: '>=6'}
+
+ p-locate@5.0.0:
+ resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+ engines: {node: '>=10'}
+
+ p-try@2.2.0:
+ resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+ engines: {node: '>=6'}
+
+ parent-module@1.0.1:
+ resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+ engines: {node: '>=6'}
+
+ parse5@7.3.0:
+ resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
+
+ path-exists@3.0.0:
+ resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==}
+ engines: {node: '>=4'}
+
+ path-exists@4.0.0:
+ resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+ engines: {node: '>=8'}
+
+ path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+
+ path-parse@1.0.7:
+ resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+
+ pathe@2.0.3:
+ resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+
+ pathval@2.0.1:
+ resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
+ engines: {node: '>= 14.16'}
+
+ picocolors@1.1.1:
+ resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
+
+ picomatch@2.3.1:
+ resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+ engines: {node: '>=8.6'}
+
+ picomatch@4.0.3:
+ resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
+ engines: {node: '>=12'}
+
+ pify@2.3.0:
+ resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
+ engines: {node: '>=0.10.0'}
+
+ pirates@4.0.7:
+ resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
+ engines: {node: '>= 6'}
+
+ possible-typed-array-names@1.1.0:
+ resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
+ engines: {node: '>= 0.4'}
+
+ postcss-import@15.1.0:
+ resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ postcss: ^8.0.0
+
+ postcss-js@4.1.0:
+ resolution: {integrity: sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==}
+ engines: {node: ^12 || ^14 || >= 16}
+ peerDependencies:
+ postcss: ^8.4.21
+
+ postcss-load-config@6.0.1:
+ resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
+ engines: {node: '>= 18'}
+ peerDependencies:
+ jiti: '>=1.21.0'
+ postcss: '>=8.0.9'
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ jiti:
+ optional: true
+ postcss:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ postcss-nested@6.2.0:
+ resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==}
+ engines: {node: '>=12.0'}
+ peerDependencies:
+ postcss: ^8.2.14
+
+ postcss-selector-parser@6.1.2:
+ resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==}
+ engines: {node: '>=4'}
+
+ postcss-value-parser@4.2.0:
+ resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
+
+ postcss@8.4.31:
+ resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ postcss@8.5.6:
+ resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==}
+ engines: {node: ^10 || ^12 || >=14}
+
+ prelude-ls@1.2.1:
+ resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+ engines: {node: '>= 0.8.0'}
+
+ pretty-format@27.5.1:
+ resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==}
+ engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0}
+
+ prop-types@15.8.1:
+ resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+
+ proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+
+ punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+
+ queue-microtask@1.2.3:
+ resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+
+ react-dom@19.2.3:
+ resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==}
+ peerDependencies:
+ react: ^19.2.3
+
+ react-is@16.13.1:
+ resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
+
+ react-is@17.0.2:
+ resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
+
+ react-refresh@0.17.0:
+ resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==}
+ engines: {node: '>=0.10.0'}
+
+ react@19.2.3:
+ resolution: {integrity: sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==}
+ engines: {node: '>=0.10.0'}
+
+ read-cache@1.0.0:
+ resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==}
+
+ readdirp@3.6.0:
+ resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
+ engines: {node: '>=8.10.0'}
+
+ reflect.getprototypeof@1.0.10:
+ resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==}
+ engines: {node: '>= 0.4'}
+
+ regexp.prototype.flags@1.5.4:
+ resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
+ engines: {node: '>= 0.4'}
+
+ require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+
+ require-main-filename@2.0.0:
+ resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
+
+ resolve-from@4.0.0:
+ resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+ engines: {node: '>=4'}
+
+ resolve-pkg-maps@1.0.0:
+ resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+
+ resolve@1.22.11:
+ resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
+ resolve@2.0.0-next.5:
+ resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
+
+ reusify@1.1.0:
+ resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
+ engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+
+ rollup@4.55.2:
+ resolution: {integrity: sha512-PggGy4dhwx5qaW+CKBilA/98Ql9keyfnb7lh4SR6shQ91QQQi1ORJ1v4UinkdP2i87OBs9AQFooQylcrrRfIcg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+
+ rrweb-cssom@0.8.0:
+ resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
+
+ run-parallel@1.2.0:
+ resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+
+ safe-array-concat@1.1.3:
+ resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==}
+ engines: {node: '>=0.4'}
+
+ safe-push-apply@1.0.0:
+ resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==}
+ engines: {node: '>= 0.4'}
+
+ safe-regex-test@1.1.0:
+ resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==}
+ engines: {node: '>= 0.4'}
+
+ safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+
+ saxes@6.0.0:
+ resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
+ engines: {node: '>=v12.22.7'}
+
+ scheduler@0.27.0:
+ resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
+
+ semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+
+ semver@7.7.3:
+ resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==}
+ engines: {node: '>=10'}
+ hasBin: true
+
+ set-blocking@2.0.0:
+ resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
+
+ set-function-length@1.2.2:
+ resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==}
+ engines: {node: '>= 0.4'}
+
+ set-function-name@2.0.2:
+ resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==}
+ engines: {node: '>= 0.4'}
+
+ set-proto@1.0.0:
+ resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
+ engines: {node: '>= 0.4'}
+
+ sharp@0.34.5:
+ resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==}
+ engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
+
+ shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+
+ shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+
+ side-channel-list@1.0.0:
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-map@1.0.1:
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
+ engines: {node: '>= 0.4'}
+
+ side-channel-weakmap@1.0.2:
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
+ engines: {node: '>= 0.4'}
+
+ side-channel@1.1.0:
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
+ engines: {node: '>= 0.4'}
+
+ siginfo@2.0.0:
+ resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
+
+ source-map-js@1.2.1:
+ resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
+ engines: {node: '>=0.10.0'}
+
+ stable-hash@0.0.5:
+ resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
+
+ stackback@0.0.2:
+ resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
+
+ std-env@3.10.0:
+ resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
+
+ stop-iteration-iterator@1.1.0:
+ resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
+ engines: {node: '>= 0.4'}
+
+ string-width@3.1.0:
+ resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==}
+ engines: {node: '>=6'}
+
+ string.prototype.includes@2.0.1:
+ resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.matchall@4.0.12:
+ resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.repeat@1.0.0:
+ resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==}
+
+ string.prototype.trim@1.2.10:
+ resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.trimend@1.0.9:
+ resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==}
+ engines: {node: '>= 0.4'}
+
+ string.prototype.trimstart@1.0.8:
+ resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==}
+ engines: {node: '>= 0.4'}
+
+ strip-ansi@5.2.0:
+ resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==}
+ engines: {node: '>=6'}
+
+ strip-bom@3.0.0:
+ resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
+ engines: {node: '>=4'}
+
+ strip-json-comments@3.1.1:
+ resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+ engines: {node: '>=8'}
+
+ strip-literal@3.1.0:
+ resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==}
+
+ styled-jsx@5.1.6:
+ resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==}
+ engines: {node: '>= 12.0.0'}
+ peerDependencies:
+ '@babel/core': '*'
+ babel-plugin-macros: '*'
+ react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0'
+ peerDependenciesMeta:
+ '@babel/core':
+ optional: true
+ babel-plugin-macros:
+ optional: true
+
+ sucrase@3.35.1:
+ resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ hasBin: true
+
+ supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+
+ supports-preserve-symlinks-flag@1.0.0:
+ resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+ engines: {node: '>= 0.4'}
+
+ symbol-tree@3.2.4:
+ resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
+
+ tailwindcss@3.4.19:
+ resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+
+ thenify-all@1.6.0:
+ resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+ engines: {node: '>=0.8'}
+
+ thenify@3.3.1:
+ resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
+ tinybench@2.9.0:
+ resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
+
+ tinyexec@0.3.2:
+ resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
+
+ tinyglobby@0.2.15:
+ resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
+ engines: {node: '>=12.0.0'}
+
+ tinypool@1.1.1:
+ resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+
+ tinyrainbow@2.0.0:
+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
+ engines: {node: '>=14.0.0'}
+
+ tinyspy@4.0.4:
+ resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
+ engines: {node: '>=14.0.0'}
+
+ tldts-core@6.1.86:
+ resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==}
+
+ tldts@6.1.86:
+ resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==}
+ hasBin: true
+
+ to-regex-range@5.0.1:
+ resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+ engines: {node: '>=8.0'}
+
+ tough-cookie@5.1.2:
+ resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==}
+ engines: {node: '>=16'}
+
+ tr46@5.1.1:
+ resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==}
+ engines: {node: '>=18'}
+
+ ts-api-utils@2.4.0:
+ resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==}
+ engines: {node: '>=18.12'}
+ peerDependencies:
+ typescript: '>=4.8.4'
+
+ ts-interface-checker@0.1.13:
+ resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
+ tsconfig-paths@3.15.0:
+ resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
+
+ tslib@2.8.1:
+ resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
+
+ type-check@0.4.0:
+ resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+ engines: {node: '>= 0.8.0'}
+
+ typed-array-buffer@1.0.3:
+ resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
+ engines: {node: '>= 0.4'}
+
+ typed-array-byte-length@1.0.3:
+ resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==}
+ engines: {node: '>= 0.4'}
+
+ typed-array-byte-offset@1.0.4:
+ resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==}
+ engines: {node: '>= 0.4'}
+
+ typed-array-length@1.0.7:
+ resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==}
+ engines: {node: '>= 0.4'}
+
+ typescript-eslint@8.53.1:
+ resolution: {integrity: sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ peerDependencies:
+ eslint: ^8.57.0 || ^9.0.0
+ typescript: '>=4.8.4 <6.0.0'
+
+ typescript@5.9.3:
+ resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+
+ unbox-primitive@1.1.0:
+ resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==}
+ engines: {node: '>= 0.4'}
+
+ undici-types@6.21.0:
+ resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
+
+ unrs-resolver@1.11.1:
+ resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==}
+
+ update-browserslist-db@1.2.3:
+ resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+
+ uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+
+ util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+
+ vite-node@3.2.4:
+ resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+
+ vite@7.3.1:
+ resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ lightningcss: ^1.21.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
+ vitest@3.2.4:
+ resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==}
+ engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
+ hasBin: true
+ peerDependencies:
+ '@edge-runtime/vm': '*'
+ '@types/debug': ^4.1.12
+ '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0
+ '@vitest/browser': 3.2.4
+ '@vitest/ui': 3.2.4
+ happy-dom: '*'
+ jsdom: '*'
+ peerDependenciesMeta:
+ '@edge-runtime/vm':
+ optional: true
+ '@types/debug':
+ optional: true
+ '@types/node':
+ optional: true
+ '@vitest/browser':
+ optional: true
+ '@vitest/ui':
+ optional: true
+ happy-dom:
+ optional: true
+ jsdom:
+ optional: true
+
+ w3c-xmlserializer@5.0.0:
+ resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
+ engines: {node: '>=18'}
+
+ webidl-conversions@7.0.0:
+ resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
+ engines: {node: '>=12'}
+
+ whatwg-encoding@3.1.1:
+ resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
+ engines: {node: '>=18'}
+ deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
+
+ whatwg-mimetype@4.0.0:
+ resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==}
+ engines: {node: '>=18'}
+
+ whatwg-url@14.2.0:
+ resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==}
+ engines: {node: '>=18'}
+
+ which-boxed-primitive@1.1.1:
+ resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==}
+ engines: {node: '>= 0.4'}
+
+ which-builtin-type@1.2.1:
+ resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==}
+ engines: {node: '>= 0.4'}
+
+ which-collection@1.0.2:
+ resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==}
+ engines: {node: '>= 0.4'}
+
+ which-module@2.0.1:
+ resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==}
+
+ which-typed-array@1.1.20:
+ resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==}
+ engines: {node: '>= 0.4'}
+
+ which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+
+ why-is-node-running@2.3.0:
+ resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
+ engines: {node: '>=8'}
+ hasBin: true
+
+ word-wrap@1.2.5:
+ resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+ engines: {node: '>=0.10.0'}
+
+ wrap-ansi@5.1.0:
+ resolution: {integrity: sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==}
+ engines: {node: '>=6'}
+
+ ws@8.19.0:
+ resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
+ xml-name-validator@5.0.0:
+ resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==}
+ engines: {node: '>=18'}
+
+ xmlchars@2.2.0:
+ resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
+
+ y18n@4.0.3:
+ resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
+
+ yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+
+ yargs-parser@13.1.2:
+ resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==}
+
+ yargs@13.3.2:
+ resolution: {integrity: sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==}
+
+ yocto-queue@0.1.0:
+ resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+ engines: {node: '>=10'}
+
+ zod-validation-error@4.0.2:
+ resolution: {integrity: sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==}
+ engines: {node: '>=18.0.0'}
+ peerDependencies:
+ zod: ^3.25.0 || ^4.0.0
+
+ zod@4.3.5:
+ resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==}
+
+snapshots:
+
+ '@alloc/quick-lru@5.2.0': {}
+
+ '@asamuzakjp/css-color@3.2.0':
+ dependencies:
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+ lru-cache: 10.4.3
+
+ '@babel/code-frame@7.28.6':
+ dependencies:
+ '@babel/helper-validator-identifier': 7.28.5
+ js-tokens: 4.0.0
+ picocolors: 1.1.1
+
+ '@babel/compat-data@7.28.6': {}
+
+ '@babel/core@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/helper-compilation-targets': 7.28.6
+ '@babel/helper-module-transforms': 7.28.6(@babel/core@7.28.6)
+ '@babel/helpers': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ '@jridgewell/remapping': 2.3.5
+ convert-source-map: 2.0.0
+ debug: 4.4.3
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/generator@7.28.6':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+ jsesc: 3.1.0
+
+ '@babel/helper-compilation-targets@7.28.6':
+ dependencies:
+ '@babel/compat-data': 7.28.6
+ '@babel/helper-validator-option': 7.27.1
+ browserslist: 4.28.1
+ lru-cache: 5.1.1
+ semver: 6.3.1
+
+ '@babel/helper-globals@7.28.0': {}
+
+ '@babel/helper-module-imports@7.28.6':
+ dependencies:
+ '@babel/traverse': 7.28.6
+ '@babel/types': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-module-transforms@7.28.6(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-module-imports': 7.28.6
+ '@babel/helper-validator-identifier': 7.28.5
+ '@babel/traverse': 7.28.6
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/helper-plugin-utils@7.28.6': {}
+
+ '@babel/helper-string-parser@7.27.1': {}
+
+ '@babel/helper-validator-identifier@7.28.5': {}
+
+ '@babel/helper-validator-option@7.27.1': {}
+
+ '@babel/helpers@7.28.6':
+ dependencies:
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+
+ '@babel/parser@7.28.6':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.6)':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/helper-plugin-utils': 7.28.6
+
+ '@babel/runtime@7.28.6': {}
+
+ '@babel/template@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+
+ '@babel/traverse@7.28.6':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/generator': 7.28.6
+ '@babel/helper-globals': 7.28.0
+ '@babel/parser': 7.28.6
+ '@babel/template': 7.28.6
+ '@babel/types': 7.28.6
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@babel/types@7.28.6':
+ dependencies:
+ '@babel/helper-string-parser': 7.27.1
+ '@babel/helper-validator-identifier': 7.28.5
+
+ '@csstools/color-helpers@5.1.0': {}
+
+ '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+
+ '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/color-helpers': 5.1.0
+ '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4)
+ '@csstools/css-tokenizer': 3.0.4
+
+ '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)':
+ dependencies:
+ '@csstools/css-tokenizer': 3.0.4
+
+ '@csstools/css-tokenizer@3.0.4': {}
+
+ '@emnapi/core@1.8.1':
+ dependencies:
+ '@emnapi/wasi-threads': 1.1.0
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/runtime@1.8.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/wasi-threads@1.1.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@esbuild/aix-ppc64@0.27.2':
+ optional: true
+
+ '@esbuild/android-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/android-arm@0.27.2':
+ optional: true
+
+ '@esbuild/android-x64@0.27.2':
+ optional: true
+
+ '@esbuild/darwin-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/darwin-x64@0.27.2':
+ optional: true
+
+ '@esbuild/freebsd-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/freebsd-x64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-arm@0.27.2':
+ optional: true
+
+ '@esbuild/linux-ia32@0.27.2':
+ optional: true
+
+ '@esbuild/linux-loong64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-mips64el@0.27.2':
+ optional: true
+
+ '@esbuild/linux-ppc64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-riscv64@0.27.2':
+ optional: true
+
+ '@esbuild/linux-s390x@0.27.2':
+ optional: true
+
+ '@esbuild/linux-x64@0.27.2':
+ optional: true
+
+ '@esbuild/netbsd-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/netbsd-x64@0.27.2':
+ optional: true
+
+ '@esbuild/openbsd-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/openbsd-x64@0.27.2':
+ optional: true
+
+ '@esbuild/openharmony-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/sunos-x64@0.27.2':
+ optional: true
+
+ '@esbuild/win32-arm64@0.27.2':
+ optional: true
+
+ '@esbuild/win32-ia32@0.27.2':
+ optional: true
+
+ '@esbuild/win32-x64@0.27.2':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.9.1(eslint@9.39.2(jiti@1.21.7))':
+ dependencies:
+ eslint: 9.39.2(jiti@1.21.7)
+ eslint-visitor-keys: 3.4.3
+
+ '@eslint-community/regexpp@4.12.2': {}
+
+ '@eslint/config-array@0.21.1':
+ dependencies:
+ '@eslint/object-schema': 2.1.7
+ debug: 4.4.3
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/config-helpers@0.4.2':
+ dependencies:
+ '@eslint/core': 0.17.0
+
+ '@eslint/core@0.17.0':
+ dependencies:
+ '@types/json-schema': 7.0.15
+
+ '@eslint/eslintrc@3.3.3':
+ dependencies:
+ ajv: 6.12.6
+ debug: 4.4.3
+ espree: 10.4.0
+ globals: 14.0.0
+ ignore: 5.3.2
+ import-fresh: 3.3.1
+ js-yaml: 4.1.1
+ minimatch: 3.1.2
+ strip-json-comments: 3.1.1
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/js@9.39.2': {}
+
+ '@eslint/object-schema@2.1.7': {}
+
+ '@eslint/plugin-kit@0.4.1':
+ dependencies:
+ '@eslint/core': 0.17.0
+ levn: 0.4.1
+
+ '@heroicons/react@2.2.0(react@19.2.3)':
+ dependencies:
+ react: 19.2.3
+
+ '@humanfs/core@0.19.1': {}
+
+ '@humanfs/node@0.16.7':
+ dependencies:
+ '@humanfs/core': 0.19.1
+ '@humanwhocodes/retry': 0.4.3
+
+ '@humanwhocodes/module-importer@1.0.1': {}
+
+ '@humanwhocodes/retry@0.4.3': {}
+
+ '@img/colour@1.0.0':
+ optional: true
+
+ '@img/sharp-darwin-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ optional: true
+
+ '@img/sharp-darwin-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-libvips-darwin-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-darwin-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-arm@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-ppc64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-riscv64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-s390x@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linux-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linuxmusl-arm64@1.2.4':
+ optional: true
+
+ '@img/sharp-libvips-linuxmusl-x64@1.2.4':
+ optional: true
+
+ '@img/sharp-linux-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-arm@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-arm': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-ppc64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-riscv64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-s390x@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-s390x': 1.2.4
+ optional: true
+
+ '@img/sharp-linux-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linux-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-linuxmusl-arm64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ optional: true
+
+ '@img/sharp-linuxmusl-x64@0.34.5':
+ optionalDependencies:
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ optional: true
+
+ '@img/sharp-wasm32@0.34.5':
+ dependencies:
+ '@emnapi/runtime': 1.8.1
+ optional: true
+
+ '@img/sharp-win32-arm64@0.34.5':
+ optional: true
+
+ '@img/sharp-win32-ia32@0.34.5':
+ optional: true
+
+ '@img/sharp-win32-x64@0.34.5':
+ optional: true
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/remapping@2.3.5':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/sourcemap-codec@1.5.5': {}
+
+ '@jridgewell/trace-mapping@0.3.31':
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.2
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ '@napi-rs/wasm-runtime@0.2.12':
+ dependencies:
+ '@emnapi/core': 1.8.1
+ '@emnapi/runtime': 1.8.1
+ '@tybys/wasm-util': 0.10.1
+ optional: true
+
+ '@next/env@16.1.4': {}
+
+ '@next/eslint-plugin-next@16.1.4':
+ dependencies:
+ fast-glob: 3.3.1
+
+ '@next/swc-darwin-arm64@16.1.4':
+ optional: true
+
+ '@next/swc-darwin-x64@16.1.4':
+ optional: true
+
+ '@next/swc-linux-arm64-gnu@16.1.4':
+ optional: true
+
+ '@next/swc-linux-arm64-musl@16.1.4':
+ optional: true
+
+ '@next/swc-linux-x64-gnu@16.1.4':
+ optional: true
+
+ '@next/swc-linux-x64-musl@16.1.4':
+ optional: true
+
+ '@next/swc-win32-arm64-msvc@16.1.4':
+ optional: true
+
+ '@next/swc-win32-x64-msvc@16.1.4':
+ optional: true
+
+ '@nodelib/fs.scandir@2.1.5':
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ run-parallel: 1.2.0
+
+ '@nodelib/fs.stat@2.0.5': {}
+
+ '@nodelib/fs.walk@1.2.8':
+ dependencies:
+ '@nodelib/fs.scandir': 2.1.5
+ fastq: 1.20.1
+
+ '@nolyfill/is-core-module@1.0.39': {}
+
+ '@popperjs/core@2.11.8': {}
+
+ '@rolldown/pluginutils@1.0.0-beta.27': {}
+
+ '@rollup/rollup-android-arm-eabi@4.55.2':
+ optional: true
+
+ '@rollup/rollup-android-arm64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-darwin-arm64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-darwin-x64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-arm64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-freebsd-x64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-gnueabihf@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm-musleabihf@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-arm64-musl@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-loong64-musl@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-ppc64-musl@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-riscv64-musl@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-s390x-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-linux-x64-musl@4.55.2':
+ optional: true
+
+ '@rollup/rollup-openbsd-x64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-openharmony-arm64@4.55.2':
+ optional: true
+
+ '@rollup/rollup-win32-arm64-msvc@4.55.2':
+ optional: true
+
+ '@rollup/rollup-win32-ia32-msvc@4.55.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-gnu@4.55.2':
+ optional: true
+
+ '@rollup/rollup-win32-x64-msvc@4.55.2':
+ optional: true
+
+ '@rtsao/scc@1.1.0': {}
+
+ '@swc/helpers@0.5.15':
+ dependencies:
+ tslib: 2.8.1
+
+ '@testing-library/dom@10.4.1':
+ dependencies:
+ '@babel/code-frame': 7.28.6
+ '@babel/runtime': 7.28.6
+ '@types/aria-query': 5.0.4
+ aria-query: 5.3.0
+ dom-accessibility-api: 0.5.16
+ lz-string: 1.5.0
+ picocolors: 1.1.1
+ pretty-format: 27.5.1
+
+ '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)':
+ dependencies:
+ '@babel/runtime': 7.28.6
+ '@testing-library/dom': 10.4.1
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ optionalDependencies:
+ '@types/react': 19.2.9
+ '@types/react-dom': 19.2.3(@types/react@19.2.9)
+
+ '@tybys/wasm-util@0.10.1':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
+ '@types/aria-query@5.0.4': {}
+
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.28.6
+ '@babel/types': 7.28.6
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.28.6
+
+ '@types/chai@5.2.3':
+ dependencies:
+ '@types/deep-eql': 4.0.2
+ assertion-error: 2.0.1
+
+ '@types/deep-eql@4.0.2': {}
+
+ '@types/estree@1.0.8': {}
+
+ '@types/json-schema@7.0.15': {}
+
+ '@types/json5@0.0.29': {}
+
+ '@types/node@22.19.7':
+ dependencies:
+ undici-types: 6.21.0
+
+ '@types/react-dom@19.2.3(@types/react@19.2.9)':
+ dependencies:
+ '@types/react': 19.2.9
+
+ '@types/react@19.2.9':
+ dependencies:
+ csstype: 3.2.3
+
+ '@typescript-eslint/eslint-plugin@8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)':
+ dependencies:
+ '@eslint-community/regexpp': 4.12.2
+ '@typescript-eslint/parser': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ '@typescript-eslint/scope-manager': 8.53.1
+ '@typescript-eslint/type-utils': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.53.1
+ eslint: 9.39.2(jiti@1.21.7)
+ ignore: 7.0.5
+ natural-compare: 1.4.0
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/scope-manager': 8.53.1
+ '@typescript-eslint/types': 8.53.1
+ '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3)
+ '@typescript-eslint/visitor-keys': 8.53.1
+ debug: 4.4.3
+ eslint: 9.39.2(jiti@1.21.7)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/project-service@8.53.1(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/tsconfig-utils': 8.53.1(typescript@5.9.3)
+ '@typescript-eslint/types': 8.53.1
+ debug: 4.4.3
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/scope-manager@8.53.1':
+ dependencies:
+ '@typescript-eslint/types': 8.53.1
+ '@typescript-eslint/visitor-keys': 8.53.1
+
+ '@typescript-eslint/tsconfig-utils@8.53.1(typescript@5.9.3)':
+ dependencies:
+ typescript: 5.9.3
+
+ '@typescript-eslint/type-utils@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/types': 8.53.1
+ '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ debug: 4.4.3
+ eslint: 9.39.2(jiti@1.21.7)
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/types@8.53.1': {}
+
+ '@typescript-eslint/typescript-estree@8.53.1(typescript@5.9.3)':
+ dependencies:
+ '@typescript-eslint/project-service': 8.53.1(typescript@5.9.3)
+ '@typescript-eslint/tsconfig-utils': 8.53.1(typescript@5.9.3)
+ '@typescript-eslint/types': 8.53.1
+ '@typescript-eslint/visitor-keys': 8.53.1
+ debug: 4.4.3
+ minimatch: 9.0.5
+ semver: 7.7.3
+ tinyglobby: 0.2.15
+ ts-api-utils: 2.4.0(typescript@5.9.3)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/utils@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)':
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7))
+ '@typescript-eslint/scope-manager': 8.53.1
+ '@typescript-eslint/types': 8.53.1
+ '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3)
+ eslint: 9.39.2(jiti@1.21.7)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ '@typescript-eslint/visitor-keys@8.53.1':
+ dependencies:
+ '@typescript-eslint/types': 8.53.1
+ eslint-visitor-keys: 4.2.1
+
+ '@unrs/resolver-binding-android-arm-eabi@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-android-arm64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-darwin-arm64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-darwin-x64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-freebsd-x64@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm-musleabihf@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-arm64-musl@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-x64-gnu@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-linux-x64-musl@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-wasm32-wasi@1.11.1':
+ dependencies:
+ '@napi-rs/wasm-runtime': 0.2.12
+ optional: true
+
+ '@unrs/resolver-binding-win32-arm64-msvc@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-win32-ia32-msvc@1.11.1':
+ optional: true
+
+ '@unrs/resolver-binding-win32-x64-msvc@1.11.1':
+ optional: true
+
+ '@vitejs/plugin-react@4.7.0(vite@7.3.1(@types/node@22.19.7)(jiti@1.21.7))':
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.6)
+ '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.6)
+ '@rolldown/pluginutils': 1.0.0-beta.27
+ '@types/babel__core': 7.20.5
+ react-refresh: 0.17.0
+ vite: 7.3.1(@types/node@22.19.7)(jiti@1.21.7)
+ transitivePeerDependencies:
+ - supports-color
+
+ '@vitest/expect@3.2.4':
+ dependencies:
+ '@types/chai': 5.2.3
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ tinyrainbow: 2.0.0
+
+ '@vitest/mocker@3.2.4(vite@7.3.1(@types/node@22.19.7)(jiti@1.21.7))':
+ dependencies:
+ '@vitest/spy': 3.2.4
+ estree-walker: 3.0.3
+ magic-string: 0.30.21
+ optionalDependencies:
+ vite: 7.3.1(@types/node@22.19.7)(jiti@1.21.7)
+
+ '@vitest/pretty-format@3.2.4':
+ dependencies:
+ tinyrainbow: 2.0.0
+
+ '@vitest/runner@3.2.4':
+ dependencies:
+ '@vitest/utils': 3.2.4
+ pathe: 2.0.3
+ strip-literal: 3.1.0
+
+ '@vitest/snapshot@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ magic-string: 0.30.21
+ pathe: 2.0.3
+
+ '@vitest/spy@3.2.4':
+ dependencies:
+ tinyspy: 4.0.4
+
+ '@vitest/utils@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.2.1
+ tinyrainbow: 2.0.0
+
+ acorn-jsx@5.3.2(acorn@8.15.0):
+ dependencies:
+ acorn: 8.15.0
+
+ acorn@8.15.0: {}
+
+ agent-base@7.1.4: {}
+
+ ajv@6.12.6:
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+
+ ansi-regex@4.1.1: {}
+
+ ansi-regex@5.0.1: {}
+
+ ansi-styles@3.2.1:
+ dependencies:
+ color-convert: 1.9.3
+
+ ansi-styles@4.3.0:
+ dependencies:
+ color-convert: 2.0.1
+
+ ansi-styles@5.2.0: {}
+
+ any-promise@1.3.0: {}
+
+ anymatch@3.1.3:
+ dependencies:
+ normalize-path: 3.0.0
+ picomatch: 2.3.1
+
+ arg@5.0.2: {}
+
+ argparse@2.0.1: {}
+
+ aria-query@5.3.0:
+ dependencies:
+ dequal: 2.0.3
+
+ aria-query@5.3.2: {}
+
+ array-buffer-byte-length@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ is-array-buffer: 3.0.5
+
+ array-includes@3.1.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ is-string: 1.1.1
+ math-intrinsics: 1.1.0
+
+ array.prototype.findlast@1.2.5:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.findlastindex@1.2.6:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.flat@1.3.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.flatmap@1.3.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-shim-unscopables: 1.1.0
+
+ array.prototype.tosorted@1.1.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-shim-unscopables: 1.1.0
+
+ arraybuffer.prototype.slice@1.0.4:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ is-array-buffer: 3.0.5
+
+ assertion-error@2.0.1: {}
+
+ ast-types-flow@0.0.8: {}
+
+ async-function@1.0.0: {}
+
+ asynckit@0.4.0: {}
+
+ autoprefixer@10.4.23(postcss@8.5.6):
+ dependencies:
+ browserslist: 4.28.1
+ caniuse-lite: 1.0.30001765
+ fraction.js: 5.3.4
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+
+ available-typed-arrays@1.0.7:
+ dependencies:
+ possible-typed-array-names: 1.1.0
+
+ axe-core@4.11.1: {}
+
+ axios@1.13.2:
+ dependencies:
+ follow-redirects: 1.15.11
+ form-data: 4.0.5
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+
+ axobject-query@4.1.0: {}
+
+ balanced-match@1.0.2: {}
+
+ baseline-browser-mapping@2.9.16: {}
+
+ binary-extensions@2.3.0: {}
+
+ bootstrap@5.3.8(@popperjs/core@2.11.8):
+ dependencies:
+ '@popperjs/core': 2.11.8
+
+ brace-expansion@1.1.12:
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+
+ brace-expansion@2.0.2:
+ dependencies:
+ balanced-match: 1.0.2
+
+ braces@3.0.3:
+ dependencies:
+ fill-range: 7.1.1
+
+ browserslist@4.28.1:
+ dependencies:
+ baseline-browser-mapping: 2.9.16
+ caniuse-lite: 1.0.30001765
+ electron-to-chromium: 1.5.267
+ node-releases: 2.0.27
+ update-browserslist-db: 1.2.3(browserslist@4.28.1)
+
+ cac@6.7.14: {}
+
+ call-bind-apply-helpers@1.0.2:
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+
+ call-bind@1.0.8:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ get-intrinsic: 1.3.0
+ set-function-length: 1.2.2
+
+ call-bound@1.0.4:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ get-intrinsic: 1.3.0
+
+ callsites@3.1.0: {}
+
+ camelcase-css@2.0.1: {}
+
+ camelcase@5.3.1: {}
+
+ caniuse-lite@1.0.30001765: {}
+
+ chai@5.3.3:
+ dependencies:
+ assertion-error: 2.0.1
+ check-error: 2.1.3
+ deep-eql: 5.0.2
+ loupe: 3.2.1
+ pathval: 2.0.1
+
+ chalk@4.1.2:
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+
+ check-error@2.1.3: {}
+
+ chokidar-cli@3.0.0:
+ dependencies:
+ chokidar: 3.6.0
+ lodash.debounce: 4.0.8
+ lodash.throttle: 4.1.1
+ yargs: 13.3.2
+
+ chokidar@3.6.0:
+ dependencies:
+ anymatch: 3.1.3
+ braces: 3.0.3
+ glob-parent: 5.1.2
+ is-binary-path: 2.1.0
+ is-glob: 4.0.3
+ normalize-path: 3.0.0
+ readdirp: 3.6.0
+ optionalDependencies:
+ fsevents: 2.3.3
+
+ client-only@0.0.1: {}
+
+ cliui@5.0.0:
+ dependencies:
+ string-width: 3.1.0
+ strip-ansi: 5.2.0
+ wrap-ansi: 5.1.0
+
+ color-convert@1.9.3:
+ dependencies:
+ color-name: 1.1.3
+
+ color-convert@2.0.1:
+ dependencies:
+ color-name: 1.1.4
+
+ color-name@1.1.3: {}
+
+ color-name@1.1.4: {}
+
+ combined-stream@1.0.8:
+ dependencies:
+ delayed-stream: 1.0.0
+
+ commander@4.1.1: {}
+
+ concat-map@0.0.1: {}
+
+ convert-source-map@2.0.0: {}
+
+ cross-spawn@7.0.6:
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+
+ cssesc@3.0.0: {}
+
+ cssstyle@4.6.0:
+ dependencies:
+ '@asamuzakjp/css-color': 3.2.0
+ rrweb-cssom: 0.8.0
+
+ csstype@3.2.3: {}
+
+ damerau-levenshtein@1.0.8: {}
+
+ data-urls@5.0.0:
+ dependencies:
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 14.2.0
+
+ data-view-buffer@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ data-view-byte-length@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ data-view-byte-offset@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-data-view: 1.0.2
+
+ debug@3.2.7:
+ dependencies:
+ ms: 2.1.3
+
+ debug@4.4.3:
+ dependencies:
+ ms: 2.1.3
+
+ decamelize@1.2.0: {}
+
+ decimal.js@10.6.0: {}
+
+ deep-eql@5.0.2: {}
+
+ deep-is@0.1.4: {}
+
+ define-data-property@1.1.4:
+ dependencies:
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ define-properties@1.2.1:
+ dependencies:
+ define-data-property: 1.1.4
+ has-property-descriptors: 1.0.2
+ object-keys: 1.1.1
+
+ delayed-stream@1.0.0: {}
+
+ dequal@2.0.3: {}
+
+ detect-libc@2.1.2:
+ optional: true
+
+ didyoumean@1.2.2: {}
+
+ dlv@1.1.3: {}
+
+ doctrine@2.1.0:
+ dependencies:
+ esutils: 2.0.3
+
+ dom-accessibility-api@0.5.16: {}
+
+ dunder-proto@1.0.1:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-errors: 1.3.0
+ gopd: 1.2.0
+
+ electron-to-chromium@1.5.267: {}
+
+ emoji-regex@7.0.3: {}
+
+ emoji-regex@9.2.2: {}
+
+ entities@6.0.1: {}
+
+ es-abstract@1.24.1:
+ dependencies:
+ array-buffer-byte-length: 1.0.2
+ arraybuffer.prototype.slice: 1.0.4
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ data-view-buffer: 1.0.2
+ data-view-byte-length: 1.0.2
+ data-view-byte-offset: 1.0.1
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ es-set-tostringtag: 2.1.0
+ es-to-primitive: 1.3.0
+ function.prototype.name: 1.1.8
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ get-symbol-description: 1.1.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ internal-slot: 1.1.0
+ is-array-buffer: 3.0.5
+ is-callable: 1.2.7
+ is-data-view: 1.0.2
+ is-negative-zero: 2.0.3
+ is-regex: 1.2.1
+ is-set: 2.0.3
+ is-shared-array-buffer: 1.0.4
+ is-string: 1.1.1
+ is-typed-array: 1.1.15
+ is-weakref: 1.1.1
+ math-intrinsics: 1.1.0
+ object-inspect: 1.13.4
+ object-keys: 1.1.1
+ object.assign: 4.1.7
+ own-keys: 1.0.1
+ regexp.prototype.flags: 1.5.4
+ safe-array-concat: 1.1.3
+ safe-push-apply: 1.0.0
+ safe-regex-test: 1.1.0
+ set-proto: 1.0.0
+ stop-iteration-iterator: 1.1.0
+ string.prototype.trim: 1.2.10
+ string.prototype.trimend: 1.0.9
+ string.prototype.trimstart: 1.0.8
+ typed-array-buffer: 1.0.3
+ typed-array-byte-length: 1.0.3
+ typed-array-byte-offset: 1.0.4
+ typed-array-length: 1.0.7
+ unbox-primitive: 1.1.0
+ which-typed-array: 1.1.20
+
+ es-define-property@1.0.1: {}
+
+ es-errors@1.3.0: {}
+
+ es-iterator-helpers@1.2.2:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-set-tostringtag: 2.1.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ globalthis: 1.0.4
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+ has-proto: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ iterator.prototype: 1.1.5
+ safe-array-concat: 1.1.3
+
+ es-module-lexer@1.7.0: {}
+
+ es-object-atoms@1.1.1:
+ dependencies:
+ es-errors: 1.3.0
+
+ es-set-tostringtag@2.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ es-shim-unscopables@1.1.0:
+ dependencies:
+ hasown: 2.0.2
+
+ es-to-primitive@1.3.0:
+ dependencies:
+ is-callable: 1.2.7
+ is-date-object: 1.1.0
+ is-symbol: 1.1.1
+
+ esbuild@0.27.2:
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.27.2
+ '@esbuild/android-arm': 0.27.2
+ '@esbuild/android-arm64': 0.27.2
+ '@esbuild/android-x64': 0.27.2
+ '@esbuild/darwin-arm64': 0.27.2
+ '@esbuild/darwin-x64': 0.27.2
+ '@esbuild/freebsd-arm64': 0.27.2
+ '@esbuild/freebsd-x64': 0.27.2
+ '@esbuild/linux-arm': 0.27.2
+ '@esbuild/linux-arm64': 0.27.2
+ '@esbuild/linux-ia32': 0.27.2
+ '@esbuild/linux-loong64': 0.27.2
+ '@esbuild/linux-mips64el': 0.27.2
+ '@esbuild/linux-ppc64': 0.27.2
+ '@esbuild/linux-riscv64': 0.27.2
+ '@esbuild/linux-s390x': 0.27.2
+ '@esbuild/linux-x64': 0.27.2
+ '@esbuild/netbsd-arm64': 0.27.2
+ '@esbuild/netbsd-x64': 0.27.2
+ '@esbuild/openbsd-arm64': 0.27.2
+ '@esbuild/openbsd-x64': 0.27.2
+ '@esbuild/openharmony-arm64': 0.27.2
+ '@esbuild/sunos-x64': 0.27.2
+ '@esbuild/win32-arm64': 0.27.2
+ '@esbuild/win32-ia32': 0.27.2
+ '@esbuild/win32-x64': 0.27.2
+
+ escalade@3.2.0: {}
+
+ escape-string-regexp@4.0.0: {}
+
+ eslint-config-next@16.1.4(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3):
+ dependencies:
+ '@next/eslint-plugin-next': 16.1.4
+ eslint: 9.39.2(jiti@1.21.7)
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@1.21.7))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7))
+ eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2(jiti@1.21.7))
+ eslint-plugin-react: 7.37.5(eslint@9.39.2(jiti@1.21.7))
+ eslint-plugin-react-hooks: 7.0.1(eslint@9.39.2(jiti@1.21.7))
+ globals: 16.4.0
+ typescript-eslint: 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@typescript-eslint/parser'
+ - eslint-import-resolver-webpack
+ - eslint-plugin-import-x
+ - supports-color
+
+ eslint-import-resolver-node@0.3.9:
+ dependencies:
+ debug: 3.2.7
+ is-core-module: 2.16.1
+ resolve: 1.22.11
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@1.21.7)):
+ dependencies:
+ '@nolyfill/is-core-module': 1.0.39
+ debug: 4.4.3
+ eslint: 9.39.2(jiti@1.21.7)
+ get-tsconfig: 4.13.0
+ is-bun-module: 2.0.0
+ stable-hash: 0.0.5
+ tinyglobby: 0.2.15
+ unrs-resolver: 1.11.1
+ optionalDependencies:
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7))
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-module-utils@2.12.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7)):
+ dependencies:
+ debug: 3.2.7
+ optionalDependencies:
+ '@typescript-eslint/parser': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ eslint: 9.39.2(jiti@1.21.7)
+ eslint-import-resolver-node: 0.3.9
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.2(jiti@1.21.7))
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7)):
+ dependencies:
+ '@rtsao/scc': 1.1.0
+ array-includes: 3.1.9
+ array.prototype.findlastindex: 1.2.6
+ array.prototype.flat: 1.3.3
+ array.prototype.flatmap: 1.3.3
+ debug: 3.2.7
+ doctrine: 2.1.0
+ eslint: 9.39.2(jiti@1.21.7)
+ eslint-import-resolver-node: 0.3.9
+ eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2(jiti@1.21.7))
+ hasown: 2.0.2
+ is-core-module: 2.16.1
+ is-glob: 4.0.3
+ minimatch: 3.1.2
+ object.fromentries: 2.0.8
+ object.groupby: 1.0.3
+ object.values: 1.2.1
+ semver: 6.3.1
+ string.prototype.trimend: 1.0.9
+ tsconfig-paths: 3.15.0
+ optionalDependencies:
+ '@typescript-eslint/parser': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ transitivePeerDependencies:
+ - eslint-import-resolver-typescript
+ - eslint-import-resolver-webpack
+ - supports-color
+
+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.2(jiti@1.21.7)):
+ dependencies:
+ aria-query: 5.3.2
+ array-includes: 3.1.9
+ array.prototype.flatmap: 1.3.3
+ ast-types-flow: 0.0.8
+ axe-core: 4.11.1
+ axobject-query: 4.1.0
+ damerau-levenshtein: 1.0.8
+ emoji-regex: 9.2.2
+ eslint: 9.39.2(jiti@1.21.7)
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ language-tags: 1.0.9
+ minimatch: 3.1.2
+ object.fromentries: 2.0.8
+ safe-regex-test: 1.1.0
+ string.prototype.includes: 2.0.1
+
+ eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@1.21.7)):
+ dependencies:
+ '@babel/core': 7.28.6
+ '@babel/parser': 7.28.6
+ eslint: 9.39.2(jiti@1.21.7)
+ hermes-parser: 0.25.1
+ zod: 4.3.5
+ zod-validation-error: 4.0.2(zod@4.3.5)
+ transitivePeerDependencies:
+ - supports-color
+
+ eslint-plugin-react@7.37.5(eslint@9.39.2(jiti@1.21.7)):
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.findlast: 1.2.5
+ array.prototype.flatmap: 1.3.3
+ array.prototype.tosorted: 1.1.4
+ doctrine: 2.1.0
+ es-iterator-helpers: 1.2.2
+ eslint: 9.39.2(jiti@1.21.7)
+ estraverse: 5.3.0
+ hasown: 2.0.2
+ jsx-ast-utils: 3.3.5
+ minimatch: 3.1.2
+ object.entries: 1.1.9
+ object.fromentries: 2.0.8
+ object.values: 1.2.1
+ prop-types: 15.8.1
+ resolve: 2.0.0-next.5
+ semver: 6.3.1
+ string.prototype.matchall: 4.0.12
+ string.prototype.repeat: 1.0.0
+
+ eslint-scope@8.4.0:
+ dependencies:
+ esrecurse: 4.3.0
+ estraverse: 5.3.0
+
+ eslint-visitor-keys@3.4.3: {}
+
+ eslint-visitor-keys@4.2.1: {}
+
+ eslint@9.39.2(jiti@1.21.7):
+ dependencies:
+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7))
+ '@eslint-community/regexpp': 4.12.2
+ '@eslint/config-array': 0.21.1
+ '@eslint/config-helpers': 0.4.2
+ '@eslint/core': 0.17.0
+ '@eslint/eslintrc': 3.3.3
+ '@eslint/js': 9.39.2
+ '@eslint/plugin-kit': 0.4.1
+ '@humanfs/node': 0.16.7
+ '@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.4.3
+ '@types/estree': 1.0.8
+ ajv: 6.12.6
+ chalk: 4.1.2
+ cross-spawn: 7.0.6
+ debug: 4.4.3
+ escape-string-regexp: 4.0.0
+ eslint-scope: 8.4.0
+ eslint-visitor-keys: 4.2.1
+ espree: 10.4.0
+ esquery: 1.7.0
+ esutils: 2.0.3
+ fast-deep-equal: 3.1.3
+ file-entry-cache: 8.0.0
+ find-up: 5.0.0
+ glob-parent: 6.0.2
+ ignore: 5.3.2
+ imurmurhash: 0.1.4
+ is-glob: 4.0.3
+ json-stable-stringify-without-jsonify: 1.0.1
+ lodash.merge: 4.6.2
+ minimatch: 3.1.2
+ natural-compare: 1.4.0
+ optionator: 0.9.4
+ optionalDependencies:
+ jiti: 1.21.7
+ transitivePeerDependencies:
+ - supports-color
+
+ espree@10.4.0:
+ dependencies:
+ acorn: 8.15.0
+ acorn-jsx: 5.3.2(acorn@8.15.0)
+ eslint-visitor-keys: 4.2.1
+
+ esquery@1.7.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ esrecurse@4.3.0:
+ dependencies:
+ estraverse: 5.3.0
+
+ estraverse@5.3.0: {}
+
+ estree-walker@3.0.3:
+ dependencies:
+ '@types/estree': 1.0.8
+
+ esutils@2.0.3: {}
+
+ expect-type@1.3.0: {}
+
+ fast-deep-equal@3.1.3: {}
+
+ fast-glob@3.3.1:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fast-glob@3.3.3:
+ dependencies:
+ '@nodelib/fs.stat': 2.0.5
+ '@nodelib/fs.walk': 1.2.8
+ glob-parent: 5.1.2
+ merge2: 1.4.1
+ micromatch: 4.0.8
+
+ fast-json-stable-stringify@2.1.0: {}
+
+ fast-levenshtein@2.0.6: {}
+
+ fastq@1.20.1:
+ dependencies:
+ reusify: 1.1.0
+
+ fdir@6.5.0(picomatch@4.0.3):
+ optionalDependencies:
+ picomatch: 4.0.3
+
+ file-entry-cache@8.0.0:
+ dependencies:
+ flat-cache: 4.0.1
+
+ fill-range@7.1.1:
+ dependencies:
+ to-regex-range: 5.0.1
+
+ find-up@3.0.0:
+ dependencies:
+ locate-path: 3.0.0
+
+ find-up@5.0.0:
+ dependencies:
+ locate-path: 6.0.0
+ path-exists: 4.0.0
+
+ flat-cache@4.0.1:
+ dependencies:
+ flatted: 3.3.3
+ keyv: 4.5.4
+
+ flatted@3.3.3: {}
+
+ follow-redirects@1.15.11: {}
+
+ for-each@0.3.5:
+ dependencies:
+ is-callable: 1.2.7
+
+ form-data@4.0.5:
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ es-set-tostringtag: 2.1.0
+ hasown: 2.0.2
+ mime-types: 2.1.35
+
+ fraction.js@5.3.4: {}
+
+ fsevents@2.3.3:
+ optional: true
+
+ function-bind@1.1.2: {}
+
+ function.prototype.name@1.1.8:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ functions-have-names: 1.2.3
+ hasown: 2.0.2
+ is-callable: 1.2.7
+
+ functions-have-names@1.2.3: {}
+
+ generator-function@2.0.1: {}
+
+ gensync@1.0.0-beta.2: {}
+
+ get-caller-file@2.0.5: {}
+
+ get-intrinsic@1.3.0:
+ dependencies:
+ call-bind-apply-helpers: 1.0.2
+ es-define-property: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ function-bind: 1.1.2
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ hasown: 2.0.2
+ math-intrinsics: 1.1.0
+
+ get-proto@1.0.1:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-object-atoms: 1.1.1
+
+ get-symbol-description@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+
+ get-tsconfig@4.13.0:
+ dependencies:
+ resolve-pkg-maps: 1.0.0
+
+ glob-parent@5.1.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ glob-parent@6.0.2:
+ dependencies:
+ is-glob: 4.0.3
+
+ globals@14.0.0: {}
+
+ globals@16.4.0: {}
+
+ globalthis@1.0.4:
+ dependencies:
+ define-properties: 1.2.1
+ gopd: 1.2.0
+
+ gopd@1.2.0: {}
+
+ has-bigints@1.1.0: {}
+
+ has-flag@4.0.0: {}
+
+ has-property-descriptors@1.0.2:
+ dependencies:
+ es-define-property: 1.0.1
+
+ has-proto@1.2.0:
+ dependencies:
+ dunder-proto: 1.0.1
+
+ has-symbols@1.1.0: {}
+
+ has-tostringtag@1.0.2:
+ dependencies:
+ has-symbols: 1.1.0
+
+ hasown@2.0.2:
+ dependencies:
+ function-bind: 1.1.2
+
+ hermes-estree@0.25.1: {}
+
+ hermes-parser@0.25.1:
+ dependencies:
+ hermes-estree: 0.25.1
+
+ html-encoding-sniffer@4.0.0:
+ dependencies:
+ whatwg-encoding: 3.1.1
+
+ http-proxy-agent@7.0.2:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ https-proxy-agent@7.0.6:
+ dependencies:
+ agent-base: 7.1.4
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
+ iconv-lite@0.6.3:
+ dependencies:
+ safer-buffer: 2.1.2
+
+ ignore@5.3.2: {}
+
+ ignore@7.0.5: {}
+
+ import-fresh@3.3.1:
+ dependencies:
+ parent-module: 1.0.1
+ resolve-from: 4.0.0
+
+ imurmurhash@0.1.4: {}
+
+ internal-slot@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ hasown: 2.0.2
+ side-channel: 1.1.0
+
+ is-array-buffer@3.0.5:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+
+ is-async-function@2.1.1:
+ dependencies:
+ async-function: 1.0.0
+ call-bound: 1.0.4
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
+ is-bigint@1.1.0:
+ dependencies:
+ has-bigints: 1.1.0
+
+ is-binary-path@2.1.0:
+ dependencies:
+ binary-extensions: 2.3.0
+
+ is-boolean-object@1.2.2:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-bun-module@2.0.0:
+ dependencies:
+ semver: 7.7.3
+
+ is-callable@1.2.7: {}
+
+ is-core-module@2.16.1:
+ dependencies:
+ hasown: 2.0.2
+
+ is-data-view@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ is-typed-array: 1.1.15
+
+ is-date-object@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-extglob@2.1.1: {}
+
+ is-finalizationregistry@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-fullwidth-code-point@2.0.0: {}
+
+ is-generator-function@1.1.2:
+ dependencies:
+ call-bound: 1.0.4
+ generator-function: 2.0.1
+ get-proto: 1.0.1
+ has-tostringtag: 1.0.2
+ safe-regex-test: 1.1.0
+
+ is-glob@4.0.3:
+ dependencies:
+ is-extglob: 2.1.1
+
+ is-map@2.0.3: {}
+
+ is-negative-zero@2.0.3: {}
+
+ is-number-object@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-number@7.0.0: {}
+
+ is-potential-custom-element-name@1.0.1: {}
+
+ is-regex@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+ hasown: 2.0.2
+
+ is-set@2.0.3: {}
+
+ is-shared-array-buffer@1.0.4:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-string@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-tostringtag: 1.0.2
+
+ is-symbol@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+ has-symbols: 1.1.0
+ safe-regex-test: 1.1.0
+
+ is-typed-array@1.1.15:
+ dependencies:
+ which-typed-array: 1.1.20
+
+ is-weakmap@2.0.2: {}
+
+ is-weakref@1.1.1:
+ dependencies:
+ call-bound: 1.0.4
+
+ is-weakset@2.0.4:
+ dependencies:
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+
+ isarray@2.0.5: {}
+
+ isexe@2.0.0: {}
+
+ iterator.prototype@1.1.5:
+ dependencies:
+ define-data-property: 1.1.4
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ has-symbols: 1.1.0
+ set-function-name: 2.0.2
+
+ jiti@1.21.7: {}
+
+ js-tokens@4.0.0: {}
+
+ js-tokens@9.0.1: {}
+
+ js-yaml@4.1.1:
+ dependencies:
+ argparse: 2.0.1
+
+ jsdom@26.1.0:
+ dependencies:
+ cssstyle: 4.6.0
+ data-urls: 5.0.0
+ decimal.js: 10.6.0
+ html-encoding-sniffer: 4.0.0
+ http-proxy-agent: 7.0.2
+ https-proxy-agent: 7.0.6
+ is-potential-custom-element-name: 1.0.1
+ nwsapi: 2.2.23
+ parse5: 7.3.0
+ rrweb-cssom: 0.8.0
+ saxes: 6.0.0
+ symbol-tree: 3.2.4
+ tough-cookie: 5.1.2
+ w3c-xmlserializer: 5.0.0
+ webidl-conversions: 7.0.0
+ whatwg-encoding: 3.1.1
+ whatwg-mimetype: 4.0.0
+ whatwg-url: 14.2.0
+ ws: 8.19.0
+ xml-name-validator: 5.0.0
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ jsesc@3.1.0: {}
+
+ json-buffer@3.0.1: {}
+
+ json-schema-traverse@0.4.1: {}
+
+ json-stable-stringify-without-jsonify@1.0.1: {}
+
+ json5@1.0.2:
+ dependencies:
+ minimist: 1.2.8
+
+ json5@2.2.3: {}
+
+ jsx-ast-utils@3.3.5:
+ dependencies:
+ array-includes: 3.1.9
+ array.prototype.flat: 1.3.3
+ object.assign: 4.1.7
+ object.values: 1.2.1
+
+ keyv@4.5.4:
+ dependencies:
+ json-buffer: 3.0.1
+
+ language-subtag-registry@0.3.23: {}
+
+ language-tags@1.0.9:
+ dependencies:
+ language-subtag-registry: 0.3.23
+
+ levn@0.4.1:
+ dependencies:
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+
+ lilconfig@3.1.3: {}
+
+ lines-and-columns@1.2.4: {}
+
+ locate-path@3.0.0:
+ dependencies:
+ p-locate: 3.0.0
+ path-exists: 3.0.0
+
+ locate-path@6.0.0:
+ dependencies:
+ p-locate: 5.0.0
+
+ lodash.debounce@4.0.8: {}
+
+ lodash.merge@4.6.2: {}
+
+ lodash.throttle@4.1.1: {}
+
+ loose-envify@1.4.0:
+ dependencies:
+ js-tokens: 4.0.0
+
+ loupe@3.2.1: {}
+
+ lru-cache@10.4.3: {}
+
+ lru-cache@5.1.1:
+ dependencies:
+ yallist: 3.1.1
+
+ lz-string@1.5.0: {}
+
+ magic-string@0.30.21:
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+
+ math-intrinsics@1.1.0: {}
+
+ merge2@1.4.1: {}
+
+ micromatch@4.0.8:
+ dependencies:
+ braces: 3.0.3
+ picomatch: 2.3.1
+
+ mime-db@1.52.0: {}
+
+ mime-types@2.1.35:
+ dependencies:
+ mime-db: 1.52.0
+
+ minimatch@3.1.2:
+ dependencies:
+ brace-expansion: 1.1.12
+
+ minimatch@9.0.5:
+ dependencies:
+ brace-expansion: 2.0.2
+
+ minimist@1.2.8: {}
+
+ ms@2.1.3: {}
+
+ mz@2.7.0:
+ dependencies:
+ any-promise: 1.3.0
+ object-assign: 4.1.1
+ thenify-all: 1.6.0
+
+ nanoid@3.3.11: {}
+
+ napi-postinstall@0.3.4: {}
+
+ natural-compare@1.4.0: {}
+
+ next@16.1.4(@babel/core@7.28.6)(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
+ dependencies:
+ '@next/env': 16.1.4
+ '@swc/helpers': 0.5.15
+ baseline-browser-mapping: 2.9.16
+ caniuse-lite: 1.0.30001765
+ postcss: 8.4.31
+ react: 19.2.3
+ react-dom: 19.2.3(react@19.2.3)
+ styled-jsx: 5.1.6(@babel/core@7.28.6)(react@19.2.3)
+ optionalDependencies:
+ '@next/swc-darwin-arm64': 16.1.4
+ '@next/swc-darwin-x64': 16.1.4
+ '@next/swc-linux-arm64-gnu': 16.1.4
+ '@next/swc-linux-arm64-musl': 16.1.4
+ '@next/swc-linux-x64-gnu': 16.1.4
+ '@next/swc-linux-x64-musl': 16.1.4
+ '@next/swc-win32-arm64-msvc': 16.1.4
+ '@next/swc-win32-x64-msvc': 16.1.4
+ sharp: 0.34.5
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+
+ node-releases@2.0.27: {}
+
+ normalize-path@3.0.0: {}
+
+ nwsapi@2.2.23: {}
+
+ object-assign@4.1.1: {}
+
+ object-hash@3.0.0: {}
+
+ object-inspect@1.13.4: {}
+
+ object-keys@1.1.1: {}
+
+ object.assign@4.1.7:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+ has-symbols: 1.1.0
+ object-keys: 1.1.1
+
+ object.entries@1.1.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ object.fromentries@2.0.8:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-object-atoms: 1.1.1
+
+ object.groupby@1.0.3:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+
+ object.values@1.2.1:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ openapi-typescript-fetch@2.2.1: {}
+
+ optionator@0.9.4:
+ dependencies:
+ deep-is: 0.1.4
+ fast-levenshtein: 2.0.6
+ levn: 0.4.1
+ prelude-ls: 1.2.1
+ type-check: 0.4.0
+ word-wrap: 1.2.5
+
+ own-keys@1.0.1:
+ dependencies:
+ get-intrinsic: 1.3.0
+ object-keys: 1.1.1
+ safe-push-apply: 1.0.0
+
+ p-limit@2.3.0:
+ dependencies:
+ p-try: 2.2.0
+
+ p-limit@3.1.0:
+ dependencies:
+ yocto-queue: 0.1.0
+
+ p-locate@3.0.0:
+ dependencies:
+ p-limit: 2.3.0
+
+ p-locate@5.0.0:
+ dependencies:
+ p-limit: 3.1.0
+
+ p-try@2.2.0: {}
+
+ parent-module@1.0.1:
+ dependencies:
+ callsites: 3.1.0
+
+ parse5@7.3.0:
+ dependencies:
+ entities: 6.0.1
+
+ path-exists@3.0.0: {}
+
+ path-exists@4.0.0: {}
+
+ path-key@3.1.1: {}
+
+ path-parse@1.0.7: {}
+
+ pathe@2.0.3: {}
+
+ pathval@2.0.1: {}
+
+ picocolors@1.1.1: {}
+
+ picomatch@2.3.1: {}
+
+ picomatch@4.0.3: {}
+
+ pify@2.3.0: {}
+
+ pirates@4.0.7: {}
+
+ possible-typed-array-names@1.1.0: {}
+
+ postcss-import@15.1.0(postcss@8.5.6):
+ dependencies:
+ postcss: 8.5.6
+ postcss-value-parser: 4.2.0
+ read-cache: 1.0.0
+ resolve: 1.22.11
+
+ postcss-js@4.1.0(postcss@8.5.6):
+ dependencies:
+ camelcase-css: 2.0.1
+ postcss: 8.5.6
+
+ postcss-load-config@6.0.1(jiti@1.21.7)(postcss@8.5.6):
+ dependencies:
+ lilconfig: 3.1.3
+ optionalDependencies:
+ jiti: 1.21.7
+ postcss: 8.5.6
+
+ postcss-nested@6.2.0(postcss@8.5.6):
+ dependencies:
+ postcss: 8.5.6
+ postcss-selector-parser: 6.1.2
+
+ postcss-selector-parser@6.1.2:
+ dependencies:
+ cssesc: 3.0.0
+ util-deprecate: 1.0.2
+
+ postcss-value-parser@4.2.0: {}
+
+ postcss@8.4.31:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ postcss@8.5.6:
+ dependencies:
+ nanoid: 3.3.11
+ picocolors: 1.1.1
+ source-map-js: 1.2.1
+
+ prelude-ls@1.2.1: {}
+
+ pretty-format@27.5.1:
+ dependencies:
+ ansi-regex: 5.0.1
+ ansi-styles: 5.2.0
+ react-is: 17.0.2
+
+ prop-types@15.8.1:
+ dependencies:
+ loose-envify: 1.4.0
+ object-assign: 4.1.1
+ react-is: 16.13.1
+
+ proxy-from-env@1.1.0: {}
+
+ punycode@2.3.1: {}
+
+ queue-microtask@1.2.3: {}
+
+ react-dom@19.2.3(react@19.2.3):
+ dependencies:
+ react: 19.2.3
+ scheduler: 0.27.0
+
+ react-is@16.13.1: {}
+
+ react-is@17.0.2: {}
+
+ react-refresh@0.17.0: {}
+
+ react@19.2.3: {}
+
+ read-cache@1.0.0:
+ dependencies:
+ pify: 2.3.0
+
+ readdirp@3.6.0:
+ dependencies:
+ picomatch: 2.3.1
+
+ reflect.getprototypeof@1.0.10:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ get-proto: 1.0.1
+ which-builtin-type: 1.2.1
+
+ regexp.prototype.flags@1.5.4:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-errors: 1.3.0
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ set-function-name: 2.0.2
+
+ require-directory@2.1.1: {}
+
+ require-main-filename@2.0.0: {}
+
+ resolve-from@4.0.0: {}
+
+ resolve-pkg-maps@1.0.0: {}
+
+ resolve@1.22.11:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ resolve@2.0.0-next.5:
+ dependencies:
+ is-core-module: 2.16.1
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
+ reusify@1.1.0: {}
+
+ rollup@4.55.2:
+ dependencies:
+ '@types/estree': 1.0.8
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.55.2
+ '@rollup/rollup-android-arm64': 4.55.2
+ '@rollup/rollup-darwin-arm64': 4.55.2
+ '@rollup/rollup-darwin-x64': 4.55.2
+ '@rollup/rollup-freebsd-arm64': 4.55.2
+ '@rollup/rollup-freebsd-x64': 4.55.2
+ '@rollup/rollup-linux-arm-gnueabihf': 4.55.2
+ '@rollup/rollup-linux-arm-musleabihf': 4.55.2
+ '@rollup/rollup-linux-arm64-gnu': 4.55.2
+ '@rollup/rollup-linux-arm64-musl': 4.55.2
+ '@rollup/rollup-linux-loong64-gnu': 4.55.2
+ '@rollup/rollup-linux-loong64-musl': 4.55.2
+ '@rollup/rollup-linux-ppc64-gnu': 4.55.2
+ '@rollup/rollup-linux-ppc64-musl': 4.55.2
+ '@rollup/rollup-linux-riscv64-gnu': 4.55.2
+ '@rollup/rollup-linux-riscv64-musl': 4.55.2
+ '@rollup/rollup-linux-s390x-gnu': 4.55.2
+ '@rollup/rollup-linux-x64-gnu': 4.55.2
+ '@rollup/rollup-linux-x64-musl': 4.55.2
+ '@rollup/rollup-openbsd-x64': 4.55.2
+ '@rollup/rollup-openharmony-arm64': 4.55.2
+ '@rollup/rollup-win32-arm64-msvc': 4.55.2
+ '@rollup/rollup-win32-ia32-msvc': 4.55.2
+ '@rollup/rollup-win32-x64-gnu': 4.55.2
+ '@rollup/rollup-win32-x64-msvc': 4.55.2
+ fsevents: 2.3.3
+
+ rrweb-cssom@0.8.0: {}
+
+ run-parallel@1.2.0:
+ dependencies:
+ queue-microtask: 1.2.3
+
+ safe-array-concat@1.1.3:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ get-intrinsic: 1.3.0
+ has-symbols: 1.1.0
+ isarray: 2.0.5
+
+ safe-push-apply@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ isarray: 2.0.5
+
+ safe-regex-test@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-regex: 1.2.1
+
+ safer-buffer@2.1.2: {}
+
+ saxes@6.0.0:
+ dependencies:
+ xmlchars: 2.2.0
+
+ scheduler@0.27.0: {}
+
+ semver@6.3.1: {}
+
+ semver@7.7.3: {}
+
+ set-blocking@2.0.0: {}
+
+ set-function-length@1.2.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-property-descriptors: 1.0.2
+
+ set-function-name@2.0.2:
+ dependencies:
+ define-data-property: 1.1.4
+ es-errors: 1.3.0
+ functions-have-names: 1.2.3
+ has-property-descriptors: 1.0.2
+
+ set-proto@1.0.0:
+ dependencies:
+ dunder-proto: 1.0.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+
+ sharp@0.34.5:
+ dependencies:
+ '@img/colour': 1.0.0
+ detect-libc: 2.1.2
+ semver: 7.7.3
+ optionalDependencies:
+ '@img/sharp-darwin-arm64': 0.34.5
+ '@img/sharp-darwin-x64': 0.34.5
+ '@img/sharp-libvips-darwin-arm64': 1.2.4
+ '@img/sharp-libvips-darwin-x64': 1.2.4
+ '@img/sharp-libvips-linux-arm': 1.2.4
+ '@img/sharp-libvips-linux-arm64': 1.2.4
+ '@img/sharp-libvips-linux-ppc64': 1.2.4
+ '@img/sharp-libvips-linux-riscv64': 1.2.4
+ '@img/sharp-libvips-linux-s390x': 1.2.4
+ '@img/sharp-libvips-linux-x64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-arm64': 1.2.4
+ '@img/sharp-libvips-linuxmusl-x64': 1.2.4
+ '@img/sharp-linux-arm': 0.34.5
+ '@img/sharp-linux-arm64': 0.34.5
+ '@img/sharp-linux-ppc64': 0.34.5
+ '@img/sharp-linux-riscv64': 0.34.5
+ '@img/sharp-linux-s390x': 0.34.5
+ '@img/sharp-linux-x64': 0.34.5
+ '@img/sharp-linuxmusl-arm64': 0.34.5
+ '@img/sharp-linuxmusl-x64': 0.34.5
+ '@img/sharp-wasm32': 0.34.5
+ '@img/sharp-win32-arm64': 0.34.5
+ '@img/sharp-win32-ia32': 0.34.5
+ '@img/sharp-win32-x64': 0.34.5
+ optional: true
+
+ shebang-command@2.0.0:
+ dependencies:
+ shebang-regex: 3.0.0
+
+ shebang-regex@3.0.0: {}
+
+ side-channel-list@1.0.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-map@1.0.1:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+
+ side-channel-weakmap@1.0.2:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ get-intrinsic: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-map: 1.0.1
+
+ side-channel@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ object-inspect: 1.13.4
+ side-channel-list: 1.0.0
+ side-channel-map: 1.0.1
+ side-channel-weakmap: 1.0.2
+
+ siginfo@2.0.0: {}
+
+ source-map-js@1.2.1: {}
+
+ stable-hash@0.0.5: {}
+
+ stackback@0.0.2: {}
+
+ std-env@3.10.0: {}
+
+ stop-iteration-iterator@1.1.0:
+ dependencies:
+ es-errors: 1.3.0
+ internal-slot: 1.1.0
+
+ string-width@3.1.0:
+ dependencies:
+ emoji-regex: 7.0.3
+ is-fullwidth-code-point: 2.0.0
+ strip-ansi: 5.2.0
+
+ string.prototype.includes@2.0.1:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+
+ string.prototype.matchall@4.0.12:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-errors: 1.3.0
+ es-object-atoms: 1.1.1
+ get-intrinsic: 1.3.0
+ gopd: 1.2.0
+ has-symbols: 1.1.0
+ internal-slot: 1.1.0
+ regexp.prototype.flags: 1.5.4
+ set-function-name: 2.0.2
+ side-channel: 1.1.0
+
+ string.prototype.repeat@1.0.0:
+ dependencies:
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+
+ string.prototype.trim@1.2.10:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-data-property: 1.1.4
+ define-properties: 1.2.1
+ es-abstract: 1.24.1
+ es-object-atoms: 1.1.1
+ has-property-descriptors: 1.0.2
+
+ string.prototype.trimend@1.0.9:
+ dependencies:
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ string.prototype.trimstart@1.0.8:
+ dependencies:
+ call-bind: 1.0.8
+ define-properties: 1.2.1
+ es-object-atoms: 1.1.1
+
+ strip-ansi@5.2.0:
+ dependencies:
+ ansi-regex: 4.1.1
+
+ strip-bom@3.0.0: {}
+
+ strip-json-comments@3.1.1: {}
+
+ strip-literal@3.1.0:
+ dependencies:
+ js-tokens: 9.0.1
+
+ styled-jsx@5.1.6(@babel/core@7.28.6)(react@19.2.3):
+ dependencies:
+ client-only: 0.0.1
+ react: 19.2.3
+ optionalDependencies:
+ '@babel/core': 7.28.6
+
+ sucrase@3.35.1:
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ commander: 4.1.1
+ lines-and-columns: 1.2.4
+ mz: 2.7.0
+ pirates: 4.0.7
+ tinyglobby: 0.2.15
+ ts-interface-checker: 0.1.13
+
+ supports-color@7.2.0:
+ dependencies:
+ has-flag: 4.0.0
+
+ supports-preserve-symlinks-flag@1.0.0: {}
+
+ symbol-tree@3.2.4: {}
+
+ tailwindcss@3.4.19:
+ dependencies:
+ '@alloc/quick-lru': 5.2.0
+ arg: 5.0.2
+ chokidar: 3.6.0
+ didyoumean: 1.2.2
+ dlv: 1.1.3
+ fast-glob: 3.3.3
+ glob-parent: 6.0.2
+ is-glob: 4.0.3
+ jiti: 1.21.7
+ lilconfig: 3.1.3
+ micromatch: 4.0.8
+ normalize-path: 3.0.0
+ object-hash: 3.0.0
+ picocolors: 1.1.1
+ postcss: 8.5.6
+ postcss-import: 15.1.0(postcss@8.5.6)
+ postcss-js: 4.1.0(postcss@8.5.6)
+ postcss-load-config: 6.0.1(jiti@1.21.7)(postcss@8.5.6)
+ postcss-nested: 6.2.0(postcss@8.5.6)
+ postcss-selector-parser: 6.1.2
+ resolve: 1.22.11
+ sucrase: 3.35.1
+ transitivePeerDependencies:
+ - tsx
+ - yaml
+
+ thenify-all@1.6.0:
+ dependencies:
+ thenify: 3.3.1
+
+ thenify@3.3.1:
+ dependencies:
+ any-promise: 1.3.0
+
+ tinybench@2.9.0: {}
+
+ tinyexec@0.3.2: {}
+
+ tinyglobby@0.2.15:
+ dependencies:
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+
+ tinypool@1.1.1: {}
+
+ tinyrainbow@2.0.0: {}
+
+ tinyspy@4.0.4: {}
+
+ tldts-core@6.1.86: {}
+
+ tldts@6.1.86:
+ dependencies:
+ tldts-core: 6.1.86
+
+ to-regex-range@5.0.1:
+ dependencies:
+ is-number: 7.0.0
+
+ tough-cookie@5.1.2:
+ dependencies:
+ tldts: 6.1.86
+
+ tr46@5.1.1:
+ dependencies:
+ punycode: 2.3.1
+
+ ts-api-utils@2.4.0(typescript@5.9.3):
+ dependencies:
+ typescript: 5.9.3
+
+ ts-interface-checker@0.1.13: {}
+
+ tsconfig-paths@3.15.0:
+ dependencies:
+ '@types/json5': 0.0.29
+ json5: 1.0.2
+ minimist: 1.2.8
+ strip-bom: 3.0.0
+
+ tslib@2.8.1: {}
+
+ type-check@0.4.0:
+ dependencies:
+ prelude-ls: 1.2.1
+
+ typed-array-buffer@1.0.3:
+ dependencies:
+ call-bound: 1.0.4
+ es-errors: 1.3.0
+ is-typed-array: 1.1.15
+
+ typed-array-byte-length@1.0.3:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+
+ typed-array-byte-offset@1.0.4:
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ has-proto: 1.2.0
+ is-typed-array: 1.1.15
+ reflect.getprototypeof: 1.0.10
+
+ typed-array-length@1.0.7:
+ dependencies:
+ call-bind: 1.0.8
+ for-each: 0.3.5
+ gopd: 1.2.0
+ is-typed-array: 1.1.15
+ possible-typed-array-names: 1.1.0
+ reflect.getprototypeof: 1.0.10
+
+ typescript-eslint@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ '@typescript-eslint/parser': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ '@typescript-eslint/typescript-estree': 8.53.1(typescript@5.9.3)
+ '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)
+ eslint: 9.39.2(jiti@1.21.7)
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - supports-color
+
+ typescript@5.9.3: {}
+
+ unbox-primitive@1.1.0:
+ dependencies:
+ call-bound: 1.0.4
+ has-bigints: 1.1.0
+ has-symbols: 1.1.0
+ which-boxed-primitive: 1.1.1
+
+ undici-types@6.21.0: {}
+
+ unrs-resolver@1.11.1:
+ dependencies:
+ napi-postinstall: 0.3.4
+ optionalDependencies:
+ '@unrs/resolver-binding-android-arm-eabi': 1.11.1
+ '@unrs/resolver-binding-android-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-arm64': 1.11.1
+ '@unrs/resolver-binding-darwin-x64': 1.11.1
+ '@unrs/resolver-binding-freebsd-x64': 1.11.1
+ '@unrs/resolver-binding-linux-arm-gnueabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm-musleabihf': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-arm64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-ppc64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-riscv64-musl': 1.11.1
+ '@unrs/resolver-binding-linux-s390x-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-gnu': 1.11.1
+ '@unrs/resolver-binding-linux-x64-musl': 1.11.1
+ '@unrs/resolver-binding-wasm32-wasi': 1.11.1
+ '@unrs/resolver-binding-win32-arm64-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1
+ '@unrs/resolver-binding-win32-x64-msvc': 1.11.1
+
+ update-browserslist-db@1.2.3(browserslist@4.28.1):
+ dependencies:
+ browserslist: 4.28.1
+ escalade: 3.2.0
+ picocolors: 1.1.1
+
+ uri-js@4.4.1:
+ dependencies:
+ punycode: 2.3.1
+
+ util-deprecate@1.0.2: {}
+
+ vite-node@3.2.4(@types/node@22.19.7)(jiti@1.21.7):
+ dependencies:
+ cac: 6.7.14
+ debug: 4.4.3
+ es-module-lexer: 1.7.0
+ pathe: 2.0.3
+ vite: 7.3.1(@types/node@22.19.7)(jiti@1.21.7)
+ transitivePeerDependencies:
+ - '@types/node'
+ - jiti
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ vite@7.3.1(@types/node@22.19.7)(jiti@1.21.7):
+ dependencies:
+ esbuild: 0.27.2
+ fdir: 6.5.0(picomatch@4.0.3)
+ picomatch: 4.0.3
+ postcss: 8.5.6
+ rollup: 4.55.2
+ tinyglobby: 0.2.15
+ optionalDependencies:
+ '@types/node': 22.19.7
+ fsevents: 2.3.3
+ jiti: 1.21.7
+
+ vitest@3.2.4(@types/node@22.19.7)(jiti@1.21.7)(jsdom@26.1.0):
+ dependencies:
+ '@types/chai': 5.2.3
+ '@vitest/expect': 3.2.4
+ '@vitest/mocker': 3.2.4(vite@7.3.1(@types/node@22.19.7)(jiti@1.21.7))
+ '@vitest/pretty-format': 3.2.4
+ '@vitest/runner': 3.2.4
+ '@vitest/snapshot': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@vitest/utils': 3.2.4
+ chai: 5.3.3
+ debug: 4.4.3
+ expect-type: 1.3.0
+ magic-string: 0.30.21
+ pathe: 2.0.3
+ picomatch: 4.0.3
+ std-env: 3.10.0
+ tinybench: 2.9.0
+ tinyexec: 0.3.2
+ tinyglobby: 0.2.15
+ tinypool: 1.1.1
+ tinyrainbow: 2.0.0
+ vite: 7.3.1(@types/node@22.19.7)(jiti@1.21.7)
+ vite-node: 3.2.4(@types/node@22.19.7)(jiti@1.21.7)
+ why-is-node-running: 2.3.0
+ optionalDependencies:
+ '@types/node': 22.19.7
+ jsdom: 26.1.0
+ transitivePeerDependencies:
+ - jiti
+ - less
+ - lightningcss
+ - msw
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - tsx
+ - yaml
+
+ w3c-xmlserializer@5.0.0:
+ dependencies:
+ xml-name-validator: 5.0.0
+
+ webidl-conversions@7.0.0: {}
+
+ whatwg-encoding@3.1.1:
+ dependencies:
+ iconv-lite: 0.6.3
+
+ whatwg-mimetype@4.0.0: {}
+
+ whatwg-url@14.2.0:
+ dependencies:
+ tr46: 5.1.1
+ webidl-conversions: 7.0.0
+
+ which-boxed-primitive@1.1.1:
+ dependencies:
+ is-bigint: 1.1.0
+ is-boolean-object: 1.2.2
+ is-number-object: 1.1.1
+ is-string: 1.1.1
+ is-symbol: 1.1.1
+
+ which-builtin-type@1.2.1:
+ dependencies:
+ call-bound: 1.0.4
+ function.prototype.name: 1.1.8
+ has-tostringtag: 1.0.2
+ is-async-function: 2.1.1
+ is-date-object: 1.1.0
+ is-finalizationregistry: 1.1.1
+ is-generator-function: 1.1.2
+ is-regex: 1.2.1
+ is-weakref: 1.1.1
+ isarray: 2.0.5
+ which-boxed-primitive: 1.1.1
+ which-collection: 1.0.2
+ which-typed-array: 1.1.20
+
+ which-collection@1.0.2:
+ dependencies:
+ is-map: 2.0.3
+ is-set: 2.0.3
+ is-weakmap: 2.0.2
+ is-weakset: 2.0.4
+
+ which-module@2.0.1: {}
+
+ which-typed-array@1.1.20:
+ dependencies:
+ available-typed-arrays: 1.0.7
+ call-bind: 1.0.8
+ call-bound: 1.0.4
+ for-each: 0.3.5
+ get-proto: 1.0.1
+ gopd: 1.2.0
+ has-tostringtag: 1.0.2
+
+ which@2.0.2:
+ dependencies:
+ isexe: 2.0.0
+
+ why-is-node-running@2.3.0:
+ dependencies:
+ siginfo: 2.0.0
+ stackback: 0.0.2
+
+ word-wrap@1.2.5: {}
+
+ wrap-ansi@5.1.0:
+ dependencies:
+ ansi-styles: 3.2.1
+ string-width: 3.1.0
+ strip-ansi: 5.2.0
+
+ ws@8.19.0: {}
+
+ xml-name-validator@5.0.0: {}
+
+ xmlchars@2.2.0: {}
+
+ y18n@4.0.3: {}
+
+ yallist@3.1.1: {}
+
+ yargs-parser@13.1.2:
+ dependencies:
+ camelcase: 5.3.1
+ decamelize: 1.2.0
+
+ yargs@13.3.2:
+ dependencies:
+ cliui: 5.0.0
+ find-up: 3.0.0
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ require-main-filename: 2.0.0
+ set-blocking: 2.0.0
+ string-width: 3.1.0
+ which-module: 2.0.1
+ y18n: 4.0.3
+ yargs-parser: 13.1.2
+
+ yocto-queue@0.1.0: {}
+
+ zod-validation-error@4.0.2(zod@4.3.5):
+ dependencies:
+ zod: 4.3.5
+
+ zod@4.3.5: {}
diff --git a/mta-sign-ui/postcss.config.js b/mta-sign-ui/postcss.config.js
new file mode 100644
index 0000000..33ad091
--- /dev/null
+++ b/mta-sign-ui/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/mta-sign-ui/public/images/RPI-LOGO.png b/mta-sign-ui/public/images/RPI-LOGO.png
new file mode 100644
index 0000000..c38e5e8
Binary files /dev/null and b/mta-sign-ui/public/images/RPI-LOGO.png differ
diff --git a/mta-sign-ui/public/images/lines/1.svg b/mta-sign-ui/public/images/lines/1.svg
new file mode 100644
index 0000000..4f649cc
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/1.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/2.svg b/mta-sign-ui/public/images/lines/2.svg
new file mode 100644
index 0000000..8e00cfa
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/2.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/3.svg b/mta-sign-ui/public/images/lines/3.svg
new file mode 100644
index 0000000..e803a46
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/3.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/4.svg b/mta-sign-ui/public/images/lines/4.svg
new file mode 100644
index 0000000..1e05694
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/4.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/5.svg b/mta-sign-ui/public/images/lines/5.svg
new file mode 100644
index 0000000..343e842
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/5.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/6.svg b/mta-sign-ui/public/images/lines/6.svg
new file mode 100644
index 0000000..349ce0b
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/6.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/6D.svg b/mta-sign-ui/public/images/lines/6D.svg
new file mode 100644
index 0000000..0973081
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/6D.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/7.svg b/mta-sign-ui/public/images/lines/7.svg
new file mode 100644
index 0000000..051272a
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/7.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/7D.svg b/mta-sign-ui/public/images/lines/7D.svg
new file mode 100644
index 0000000..e2d817a
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/7D.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/A.svg b/mta-sign-ui/public/images/lines/A.svg
new file mode 100644
index 0000000..6b40c76
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/A.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/B.svg b/mta-sign-ui/public/images/lines/B.svg
new file mode 100644
index 0000000..e73116a
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/B.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/C.svg b/mta-sign-ui/public/images/lines/C.svg
new file mode 100644
index 0000000..fc8114a
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/C.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/D.svg b/mta-sign-ui/public/images/lines/D.svg
new file mode 100644
index 0000000..4edad9c
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/D.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/E.svg b/mta-sign-ui/public/images/lines/E.svg
new file mode 100644
index 0000000..a9565bc
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/E.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/F.svg b/mta-sign-ui/public/images/lines/F.svg
new file mode 100644
index 0000000..c70d702
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/F.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/G.svg b/mta-sign-ui/public/images/lines/G.svg
new file mode 100644
index 0000000..a5b1f03
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/G.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/H.svg b/mta-sign-ui/public/images/lines/H.svg
new file mode 100644
index 0000000..1a4ed89
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/H.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/J.svg b/mta-sign-ui/public/images/lines/J.svg
new file mode 100644
index 0000000..1c1b87b
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/J.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/L.svg b/mta-sign-ui/public/images/lines/L.svg
new file mode 100644
index 0000000..e13f035
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/L.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/M.svg b/mta-sign-ui/public/images/lines/M.svg
new file mode 100644
index 0000000..12b4c5e
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/M.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/N.svg b/mta-sign-ui/public/images/lines/N.svg
new file mode 100644
index 0000000..418012b
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/N.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/Q.svg b/mta-sign-ui/public/images/lines/Q.svg
new file mode 100644
index 0000000..ba9ae09
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/Q.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/R.svg b/mta-sign-ui/public/images/lines/R.svg
new file mode 100644
index 0000000..83a5996
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/R.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/S.svg b/mta-sign-ui/public/images/lines/S.svg
new file mode 100644
index 0000000..f2b9946
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/S.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/SF.svg b/mta-sign-ui/public/images/lines/SF.svg
new file mode 100644
index 0000000..5a35ac8
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/SF.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mta-sign-ui/public/images/lines/SIR.svg b/mta-sign-ui/public/images/lines/SIR.svg
new file mode 100644
index 0000000..640d6c6
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/SIR.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mta-sign-ui/public/images/lines/SR.svg b/mta-sign-ui/public/images/lines/SR.svg
new file mode 100644
index 0000000..714a1df
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/SR.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mta-sign-ui/public/images/lines/T.svg b/mta-sign-ui/public/images/lines/T.svg
new file mode 100644
index 0000000..aaf911a
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/T.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/W.svg b/mta-sign-ui/public/images/lines/W.svg
new file mode 100644
index 0000000..c1a7991
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/W.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/images/lines/Z.svg b/mta-sign-ui/public/images/lines/Z.svg
new file mode 100644
index 0000000..5e74122
--- /dev/null
+++ b/mta-sign-ui/public/images/lines/Z.svg
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/mta-sign-ui/public/next.svg b/mta-sign-ui/public/next.svg
new file mode 100644
index 0000000..5174b28
--- /dev/null
+++ b/mta-sign-ui/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mta-sign-ui/public/vercel.svg b/mta-sign-ui/public/vercel.svg
new file mode 100644
index 0000000..d2f8422
--- /dev/null
+++ b/mta-sign-ui/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/mta-sign-ui/tailwind.config.js b/mta-sign-ui/tailwind.config.js
new file mode 100644
index 0000000..895faf7
--- /dev/null
+++ b/mta-sign-ui/tailwind.config.js
@@ -0,0 +1,18 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: [
+ './pages/**/*.{js,ts,jsx,tsx,mdx}',
+ './components/**/*.{js,ts,jsx,tsx,mdx}',
+ './mta_sign_server/**/*.{js,ts,jsx,tsx,mdx}',
+ ],
+ theme: {
+ extend: {
+ backgroundImage: {
+ 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
+ 'gradient-conic':
+ 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
+ },
+ },
+ },
+ plugins: [],
+}
diff --git a/mta-sign-ui/tests/config.test.ts b/mta-sign-ui/tests/config.test.ts
new file mode 100644
index 0000000..c24a4c6
--- /dev/null
+++ b/mta-sign-ui/tests/config.test.ts
@@ -0,0 +1,74 @@
+import { describe, it, expect } from 'vitest'
+import { AppConfig, StationConfig, CONFIG_VERSION } from '@/types/config'
+
+describe('Config Types', () => {
+ it('CONFIG_VERSION is defined', () => {
+ expect(CONFIG_VERSION).toBeDefined()
+ expect(typeof CONFIG_VERSION).toBe('number')
+ })
+
+ it('StationConfig has correct shape', () => {
+ const config: StationConfig = {
+ stationId: '127',
+ stationName: 'Times Sq-42 St',
+ showNorth: true,
+ showSouth: false,
+ selectedLines: ['A', 'C', 'E'],
+ }
+
+ expect(config.stationId).toBe('127')
+ expect(config.stationName).toBe('Times Sq-42 St')
+ expect(config.showNorth).toBe(true)
+ expect(config.showSouth).toBe(false)
+ expect(config.selectedLines).toEqual(['A', 'C', 'E'])
+ })
+
+ it('AppConfig has correct shape', () => {
+ const appConfig: AppConfig = {
+ version: CONFIG_VERSION,
+ stations: [
+ {
+ stationId: '127',
+ stationName: 'Times Sq-42 St',
+ showNorth: true,
+ showSouth: true,
+ selectedLines: ['A', 'C', 'E'],
+ },
+ ],
+ }
+
+ expect(appConfig.version).toBe(CONFIG_VERSION)
+ expect(appConfig.stations).toHaveLength(1)
+ expect(appConfig.stations[0].stationId).toBe('127')
+ })
+
+ it('AppConfig can serialize to JSON and back', () => {
+ const appConfig: AppConfig = {
+ version: CONFIG_VERSION,
+ stations: [
+ {
+ stationId: '127',
+ stationName: 'Times Sq-42 St',
+ showNorth: true,
+ showSouth: false,
+ selectedLines: ['1', '2', '3'],
+ },
+ {
+ stationId: 'A27',
+ stationName: '42 St-Port Authority',
+ showNorth: false,
+ showSouth: true,
+ selectedLines: ['A', 'C', 'E'],
+ },
+ ],
+ }
+
+ const json = JSON.stringify(appConfig)
+ const parsed = JSON.parse(json) as AppConfig
+
+ expect(parsed.version).toBe(appConfig.version)
+ expect(parsed.stations).toHaveLength(2)
+ expect(parsed.stations[0]).toEqual(appConfig.stations[0])
+ expect(parsed.stations[1]).toEqual(appConfig.stations[1])
+ })
+})
diff --git a/mta-sign-ui/tests/setup.ts b/mta-sign-ui/tests/setup.ts
new file mode 100644
index 0000000..bd6540c
--- /dev/null
+++ b/mta-sign-ui/tests/setup.ts
@@ -0,0 +1 @@
+import '@testing-library/react'
diff --git a/mta-sign-ui/tsconfig.json b/mta-sign-ui/tsconfig.json
new file mode 100644
index 0000000..f73299e
--- /dev/null
+++ b/mta-sign-ui/tsconfig.json
@@ -0,0 +1,42 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/mta-sign-ui/types/config.ts b/mta-sign-ui/types/config.ts
new file mode 100644
index 0000000..2513f81
--- /dev/null
+++ b/mta-sign-ui/types/config.ts
@@ -0,0 +1,15 @@
+export interface StationConfig {
+ id: string
+ stationId: string
+ stationName: string
+ showNorth: boolean
+ showSouth: boolean
+ selectedLines: string[]
+}
+
+export interface AppConfig {
+ version: number
+ stations: StationConfig[]
+}
+
+export const CONFIG_VERSION = 1
diff --git a/mta-sign-ui/vitest.config.ts b/mta-sign-ui/vitest.config.ts
new file mode 100644
index 0000000..44cb334
--- /dev/null
+++ b/mta-sign-ui/vitest.config.ts
@@ -0,0 +1,17 @@
+import { defineConfig } from 'vitest/config'
+import react from '@vitejs/plugin-react'
+import path from 'path'
+
+export default defineConfig({
+ plugins: [react()],
+ test: {
+ environment: 'jsdom',
+ globals: true,
+ setupFiles: ['./tests/setup.ts'],
+ },
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './'),
+ },
+ },
+})
diff --git a/mta_api_client/__init__.py b/mta_api_client/__init__.py
new file mode 100644
index 0000000..1236195
--- /dev/null
+++ b/mta_api_client/__init__.py
@@ -0,0 +1,5 @@
+from .mta import MTA
+
+from .train import Train
+from .feed import Feed
+from .route import Route
diff --git a/mta_api_client/feed.py b/mta_api_client/feed.py
new file mode 100644
index 0000000..c91c8f1
--- /dev/null
+++ b/mta_api_client/feed.py
@@ -0,0 +1,17 @@
+from enum import Enum
+
+
+class Feed(Enum):
+ ACE = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-ace"
+ BDFM = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-bdfm"
+ G = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-bdfm"
+ JZ = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-jz"
+ NQRW = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-nqrw"
+ L = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-l"
+ N1234567 = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs"
+ SIR = "https://api-endpoint.mta.info/Dataservice/mtagtfsfeeds/nyct%2Fgtfs-si"
+
+
+ALL_FEEDS = [
+ member for member in Feed
+]
diff --git a/mta_api_client/mta.py b/mta_api_client/mta.py
new file mode 100644
index 0000000..553073c
--- /dev/null
+++ b/mta_api_client/mta.py
@@ -0,0 +1,50 @@
+import requests
+
+from google.transit import gtfs_realtime_pb2
+from .train import Train
+from .feed import Feed, ALL_FEEDS
+from .route import Route
+
+
+class MTA(object):
+ def __init__(self, api_key: str, feeds: [Feed] = ALL_FEEDS, stations: [str] = [],
+ max_arrival_time: int = 30):
+ self.header = {
+ "x-api-key": api_key
+ }
+ self.feeds = feeds
+ self.stations = stations
+ self.max_arrival_time = max_arrival_time
+ self.trains: [Train] = []
+
+ def stop_updates(self):
+ self.is_running = False
+
+ def update_trains(self) -> [Train]:
+ trains = []
+ for feed in self.feeds:
+ r = requests.get(feed.value, headers=self.header)
+ feed = gtfs_realtime_pb2.FeedMessage()
+ feed.ParseFromString(r.content)
+ trains.extend([train for train in [Train(train) for train in feed.entity] if
+ train.has_trips()])
+ self.trains = trains
+ return trains
+
+ def get_trains(self) -> [Train]:
+ return self.trains
+
+ def get_arrival_times(self, route: Route, station: str) -> [int]:
+ arrival_times = []
+ for train in self.trains:
+ if train.get_route() is route:
+ arrival = train.get_arrival_at(station)
+ if arrival is not None and arrival < self.max_arrival_time and arrival > 0:
+ arrival_times.append(arrival)
+ return sorted(arrival_times)
+
+ def add_station_id(self, station_id: str):
+ self.stations.append(station_id)
+
+ def remove_station_id(self, station_id: str):
+ self.stations.remove(station_id)
diff --git a/mta_api_client/route.py b/mta_api_client/route.py
new file mode 100644
index 0000000..f4086d7
--- /dev/null
+++ b/mta_api_client/route.py
@@ -0,0 +1,40 @@
+from enum import Enum
+
+
+class Route(Enum):
+ A = "A"
+ C = "C"
+ E = "E"
+
+ B = "B"
+ D = "D"
+ F = "F"
+ M = "M"
+
+ G = "G"
+
+ J = "J"
+ Z = "Z"
+
+ N = "N"
+ Q = "Q"
+ R = "R"
+ W = "W"
+
+ N1 = "1"
+ N2 = "2"
+ N3 = "3"
+ N4 = "4"
+ N5 = "5"
+ N6 = "6"
+ N7 = "7"
+
+ L = "L"
+ SIR = "SIR"
+
+
+_routes = set(item.value for item in Route)
+
+
+def is_valid_route(route: str) -> bool:
+ return route in _routes
diff --git a/mta_api_client/stop.py b/mta_api_client/stop.py
new file mode 100644
index 0000000..1aface0
--- /dev/null
+++ b/mta_api_client/stop.py
@@ -0,0 +1,7 @@
+from datetime import datetime
+from google.transit import gtfs_realtime_pb2
+from math import trunc
+
+
+def trip_arrival_in_minutes(stop_time_update: gtfs_realtime_pb2.TripUpdate):
+ return trunc(((datetime.fromtimestamp(stop_time_update.arrival.time) - datetime.now()).total_seconds()) / 60)
diff --git a/mta_api_client/train.py b/mta_api_client/train.py
new file mode 100644
index 0000000..c3e57d4
--- /dev/null
+++ b/mta_api_client/train.py
@@ -0,0 +1,33 @@
+from google.transit import gtfs_realtime_pb2
+from .stop import trip_arrival_in_minutes
+from .route import Route, is_valid_route
+
+
+class Train(object):
+ def __init__(self, train_proto: gtfs_realtime_pb2.FeedEntity):
+ self.train_proto: gtfs_realtime_pb2.FeedEntity = train_proto
+
+ def get_arrival_at(self, stop_id) -> int | None:
+ """
+ returns the routes stop time at a given stop ID in minutes
+ if not found, returns None
+ :param stop_id: stop ID of arrival station
+ :return: arrival time in minutes
+ """
+ for stop_time_update in self.train_proto.trip_update.stop_time_update:
+ if stop_time_update.stop_id == stop_id:
+ return trip_arrival_in_minutes(stop_time_update)
+ return None
+
+ def _get_route(self) -> str:
+ return self.train_proto.trip_update.trip.route_id
+
+ def get_route(self) -> Route:
+ return Route(self.train_proto.trip_update.trip.route_id)
+
+ def has_trips(self) -> bool:
+ return self.train_proto.trip_update is not None \
+ and len(self.train_proto.trip_update.stop_time_update) > 0 and is_valid_route(self._get_route())
+
+ def __str__(self):
+ return f"{self.train_proto}"
diff --git a/mta_manager/mta.py b/mta_manager/mta.py
deleted file mode 100644
index 0b4c6f2..0000000
--- a/mta_manager/mta.py
+++ /dev/null
@@ -1,115 +0,0 @@
-import asyncio
-import requests
-import json
-
-from google.transit import gtfs_realtime_pb2
-from protobuf_to_dict import protobuf_to_dict
-from time import time
-from .train import Train
-
-
-class MTA(object):
- # Create a data filter object.
- # Then be able to update that object on the fly.
- # This filter should return all possible trains and stations by default.
- # If anything is added it gets filtered out.
- def __init__(self, api_key: str, routes, station_ids, timing_callbacks=None, alert_callbacks=None,
- endpoints_file="./endpoints.json", callback_frequency=10, max_arrival_time=30):
- self.header = {
- "x-api-key": api_key
- }
- self.routes = routes
- self.station_ids = station_ids
- self.timing_callbacks = timing_callbacks if timing_callbacks else []
- self.is_running = False
- self.callback_frequency = callback_frequency
- self.max_arrival_time = max_arrival_time
- with open(endpoints_file, "r") as f:
- self.endpoints = json.load(f)
- self.set_valid_endpoints()
-
- def set_valid_endpoints(self):
- self.valid_endpoints = {}
- for key, value in self.endpoints.items():
- valid_routes = [x for x in self.routes if x in key]
- if valid_routes:
- self.valid_endpoints[value] = valid_routes
- print(self.valid_endpoints)
-
- def start_updates(self):
- print("starting updates")
- loop = asyncio.new_event_loop()
- asyncio.set_event_loop(loop)
- loop.run_until_complete(self._get_updates())
-
- def stop_updates(self):
- self.is_running = False
-
- async def get_data(self):
- trains = []
- for endpoint, valid_lines in self.valid_endpoints.items():
- r = requests.get(endpoint, headers=self.header)
- feed = gtfs_realtime_pb2.FeedMessage()
- feed.ParseFromString(r.content)
- subway_feed = protobuf_to_dict(feed)['entity']
- trains.extend([train for train in [Train.get_train_from_dict(train_dict) for train_dict in subway_feed] if
- train is not None])
- return trains
-
- @staticmethod
- def get_trains_for_routes(routes, trains):
- return [train for train in trains if train.route in routes]
-
- @staticmethod
- def get_trains_for_route(route, trains):
- return MTA.get_trains_for_routes([route], trains)
-
- async def get_train_information(self):
- valid_trains = [train for train in await self.get_data() if True]
- return valid_trains
-
- async def _get_updates(self):
- self.is_running = True
- while (self.is_running):
- t = time()
- data = self.get_train_information()
- data = await data
- await self.process_callbacks(data)
- await asyncio.sleep(self.callback_frequency - (time() - t))
-
- async def process_callbacks(self, data):
- for callback in self.timing_callbacks:
- await callback(data)
-
- def add_train_line(self, train_line: str):
- self.routes.append(train_line)
- self.set_valid_endpoints()
-
- def remove_train_line(self, train_line: str):
- self.routes.remove(train_line)
- self.set_valid_endpoints()
-
- def add_station_id(self, station_id: str):
- self.station_ids.append(station_id)
-
- def remove_station_id(self, station_id: str):
- self.station_ids.remove(station_id)
-
- def add_callback(self, callback_func):
- self.timing_callbacks.append(callback_func)
-
- def remove_callback(self, callback_func):
- self.timing_callbacks.remove(callback_func)
-
- def get_time_arriving_at_stations(self, trains):
- station_first = {}
- for station_id in self.station_ids:
- line_first = {}
- for route in self.routes:
- valid_trains = [train.get_arrival_at(station_id) for train in MTA.get_trains_for_route(route, trains) if
- train.arriving_at_station_in_time(station_id, self.max_arrival_time)]
- if valid_trains:
- line_first[route] = valid_trains
- if line_first:
- station_first[station_id] = line_first
- return station_first
diff --git a/mta_manager/stop.py b/mta_manager/stop.py
deleted file mode 100644
index 634e5a3..0000000
--- a/mta_manager/stop.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from datetime import datetime
-from math import trunc
-
-
-class Stop(object):
- def __init__(self, id, arrival_time, departure_time, ):
- self.id = id
- self.arrival_time = arrival_time
- self.departure_time = departure_time
-
- def arrival_minutes(self):
- return trunc(((datetime.fromtimestamp(self.arrival_time) - datetime.now()).total_seconds()) / 60)
-
- def __str__(self):
- now = datetime.now()
- time = datetime.fromtimestamp(self.arrival_time)
- time_minutes = trunc(((time - now).total_seconds()) / 60)
- return f"stop_id:{self.id}| arr:{time_minutes}| dep:{self.departure_time}"
-
- @staticmethod
- def get_stop_from_dict(obj):
- if "arrival" in obj and "departure" in obj and "stop_id" in obj:
- return Stop(obj["stop_id"], obj["arrival"]["time"], obj["departure"]["time"])
- return None
diff --git a/mta_manager/train.py b/mta_manager/train.py
deleted file mode 100644
index a53dfd2..0000000
--- a/mta_manager/train.py
+++ /dev/null
@@ -1,42 +0,0 @@
-from .stop import Stop
-
-class Train(object):
- def __init__(self, id, route, stops):
- self.id = id
- self.route = route
- self.stops = stops
-
- def get_arrival_at(self, stop_id):
- """
- returns the routes stop time at a given stop ID in minutes
- if not found, returns None
- :param stop_id: stop ID of arrival station
- :return: arrival time in minutes
- """
- for stop in self.stops:
- if stop.id == stop_id:
- return stop.arrival_minutes()
- return None
-
- def arriving_at_station_in_time(self, station_id, max_time):
- for stop in self.stops:
- minutes_to_arrival = stop.arrival_minutes()
- if stop.id == station_id:
- if minutes_to_arrival > 0 and minutes_to_arrival < max_time:
- return True
-
- def __str__(self):
- formatted_stops = '\n'.join([str(stop) for stop in self.stops])
- return f"train_id:{self.id} | line_name:{self.route}| stops:\n {formatted_stops}"
-
- @staticmethod
- def get_train_from_dict(obj):
- if "trip_update" in obj and "stop_time_update" in obj["trip_update"]:
- # data we need is here create object
- id = obj["id"]
- route = obj["trip_update"]["trip"]["route_id"]
- all_stops = [Stop.get_stop_from_dict(x) for x in obj["trip_update"]["stop_time_update"]]
- valid_stops = [valid_stop for valid_stop in all_stops if valid_stop is not None]
- return Train(id, route, valid_stops)
- else:
- return None
\ No newline at end of file
diff --git a/mta_manager/__init__.py b/mta_sign_server/__init__.py
similarity index 100%
rename from mta_manager/__init__.py
rename to mta_sign_server/__init__.py
diff --git a/mta_sign_server/config/__init__.py b/mta_sign_server/config/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/mta_sign_server/config/router.py b/mta_sign_server/config/router.py
new file mode 100644
index 0000000..ab94d67
--- /dev/null
+++ b/mta_sign_server/config/router.py
@@ -0,0 +1,56 @@
+import csv
+import logging
+from pathlib import Path
+
+from fastapi import APIRouter
+
+from mta_api_client import Route
+from mta_sign_server.config.schemas import Station, StationsResponse, LinesResponse
+
+router = APIRouter(
+ tags=["config"],
+)
+
+logger = logging.getLogger("config_router")
+
+STOPS_FILE = Path(__file__).parent.parent.parent / "stops.txt"
+
+
+@router.get("/api/config")
+def get_all():
+ return {"config": "goes here"}
+
+
+@router.get("/api/stations", response_model=StationsResponse)
+def get_stations(search: str | None = None):
+ """Get list of all stations, optionally filtered by search term. Deduplicates by station name."""
+ stations_dict = {}
+
+ if STOPS_FILE.exists():
+ with open(STOPS_FILE, "r") as f:
+ reader = csv.DictReader(f)
+ for row in reader:
+ # Only include parent stations (location_type == 1)
+ if row.get("location_type") == "1":
+ station_name = row["stop_name"]
+ station_id = row["stop_id"]
+
+ # Only add first occurrence of each station name to deduplicate
+ if station_name not in stations_dict:
+ station = Station(id=station_id, name=station_name)
+
+ # Filter by search term if provided
+ if search:
+ if search.lower() in station.name.lower() or search in station.id:
+ stations_dict[station_name] = station
+ else:
+ stations_dict[station_name] = station
+
+ return StationsResponse(stations=list(stations_dict.values()))
+
+
+@router.get("/api/lines", response_model=LinesResponse)
+def get_lines():
+ """Get list of all available train lines."""
+ lines = [route.value for route in Route]
+ return LinesResponse(lines=sorted(lines))
diff --git a/mta_sign_server/config/schemas.py b/mta_sign_server/config/schemas.py
new file mode 100644
index 0000000..cfbbc9c
--- /dev/null
+++ b/mta_sign_server/config/schemas.py
@@ -0,0 +1,14 @@
+from pydantic import BaseModel
+
+
+class Station(BaseModel):
+ id: str
+ name: str
+
+
+class StationsResponse(BaseModel):
+ stations: list[Station]
+
+
+class LinesResponse(BaseModel):
+ lines: list[str]
diff --git a/mta_sign_server/mta/__init__.py b/mta_sign_server/mta/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/mta_sign_server/mta/router.py b/mta_sign_server/mta/router.py
new file mode 100644
index 0000000..514a490
--- /dev/null
+++ b/mta_sign_server/mta/router.py
@@ -0,0 +1,134 @@
+import csv
+import logging
+import os
+from pathlib import Path
+from collections import defaultdict
+
+from fastapi import APIRouter, HTTPException
+from fastapi_utils.tasks import repeat_every
+from starlette import status
+
+from mta_api_client import Route, MTA
+from mta_api_client.feed import ALL_FEEDS
+from mta_sign_server.mta.schemas import StationResponse, RouteResponse, AllStationResponse
+
+router = APIRouter(
+ tags=["mta-data"],
+)
+
+logger = logging.getLogger("mta")
+
+api_key = os.getenv('MTA_API_KEY', '')
+
+mtaController = MTA(
+ api_key,
+ feeds=ALL_FEEDS
+)
+
+ROUTES = [member for member in Route]
+STATION_STOP_IDs = ["127S", "127N", "A27N", "A27S"]
+STOPS_FILE = Path(__file__).parent.parent.parent / "stops.txt"
+
+# Build mappings for station resolution
+_station_name_to_ids = None
+_station_id_to_name = None
+
+
+def _load_station_mapping():
+ global _station_name_to_ids, _station_id_to_name
+ if _station_name_to_ids is not None:
+ return
+
+ _station_name_to_ids = defaultdict(set)
+ _station_id_to_name = {}
+
+ if STOPS_FILE.exists():
+ with open(STOPS_FILE, "r") as f:
+ reader = csv.DictReader(f)
+ for row in reader:
+ if row.get("location_type") == "1": # Parent stations only
+ station_name = row["stop_name"]
+ station_id = row["stop_id"]
+ _station_name_to_ids[station_name].add(station_id)
+ _station_id_to_name[station_id] = station_name
+
+
+def _resolve_base_station_ids(stop_id: str) -> list[str]:
+ """Resolve a stop_id to a list of all base parent station IDs (without direction) that share the same station name."""
+ _load_station_mapping()
+
+ # Remove direction suffix to get base ID
+ base_id = stop_id.rstrip("NS")
+
+ # Look up the station name for this ID
+ if base_id in _station_id_to_name:
+ station_name = _station_id_to_name[base_id]
+ # Return all base station IDs with this name
+ return sorted(list(_station_name_to_ids[station_name]))
+
+ # If not found, just return the base ID
+ return [base_id]
+
+
+@router.post("/api/mta/{stop_id}/{route}", response_model=RouteResponse, status_code=status.HTTP_200_OK)
+def get_route(stop_id: str, route: Route):
+ arrival_times = mtaController.get_arrival_times(route, stop_id)
+ if len(arrival_times) > 0:
+ return RouteResponse(routeId=route, arrival_times=arrival_times)
+ raise HTTPException(status_code=404, detail="no stops found for route and stop id")
+
+
+@router.post("/api/mta/{stop_id}", response_model=StationResponse, status_code=status.HTTP_200_OK)
+def get_station(stop_id: str):
+ routes_dict = {} # Use dict to avoid duplicates
+ base_station_ids = _resolve_base_station_ids(stop_id)
+
+ # Extract the requested direction
+ requested_direction = ""
+ if stop_id.endswith("N"):
+ requested_direction = "N"
+ elif stop_id.endswith("S"):
+ requested_direction = "S"
+
+ # Only query the requested direction for each base station ID
+ for base_id in base_station_ids:
+ station_id_with_direction = f"{base_id}{requested_direction}"
+ for route in ROUTES:
+ arrival_times = mtaController.get_arrival_times(route, station_id_with_direction)
+ if len(arrival_times) > 0:
+ route_key = route.value
+ if route_key not in routes_dict:
+ routes_dict[route_key] = (route, arrival_times)
+ else:
+ # Combine arrival times from different station IDs
+ routes_dict[route_key] = (route, sorted(list(set(routes_dict[route_key][1] + arrival_times))))
+
+ routes = [RouteResponse(routeId=route, arrival_times=times) for route, times in routes_dict.values()]
+
+ if routes:
+ return StationResponse(stationId=stop_id, routes=routes)
+ raise HTTPException(status_code=404, detail="no trains or routes found for stop id")
+
+
+@router.post("/api/mta", response_model=AllStationResponse, status_code=status.HTTP_200_OK)
+def get_all():
+ print("HELLO WORLD")
+ all_stations = []
+ for stop_id in STATION_STOP_IDs:
+ routes = []
+ for route in ROUTES:
+ arrival_times = mtaController.get_arrival_times(route, stop_id)
+ if len(arrival_times) > 0:
+ routes.append(RouteResponse(routeId=route, arrival_times=arrival_times))
+ all_stations.append(StationResponse(stationId=stop_id, routes=routes))
+ print(all_stations)
+ if all_stations:
+ return AllStationResponse(stations=all_stations)
+ raise HTTPException(status_code=404, detail="no arriving trains found for all configured routes")
+
+
+@router.on_event("startup")
+@repeat_every(seconds=10)
+def update_trains():
+ logger.info("UPDATING TRAINS")
+ mtaController.update_trains()
diff --git a/mta_sign_server/mta/schemas.py b/mta_sign_server/mta/schemas.py
new file mode 100644
index 0000000..e808720
--- /dev/null
+++ b/mta_sign_server/mta/schemas.py
@@ -0,0 +1,18 @@
+from pydantic import BaseModel
+from typing import List
+
+from mta_api_client import Route
+
+
+class RouteResponse(BaseModel):
+ routeId: Route
+ arrival_times: List[int]
+
+
+class StationResponse(BaseModel):
+ stationId: str
+ routes: List[RouteResponse]
+
+
+class AllStationResponse(BaseModel):
+ stations: List[StationResponse]
diff --git a/mta_sign_server/router.py b/mta_sign_server/router.py
new file mode 100644
index 0000000..463c296
--- /dev/null
+++ b/mta_sign_server/router.py
@@ -0,0 +1,12 @@
+from datetime import datetime
+
+from fastapi import APIRouter, status
+
+router = APIRouter(
+ tags=["start"],
+)
+
+start_time = datetime.now()
+@router.post("/api/start_time", status_code=status.HTTP_200_OK)
+def get_start_time():
+ return start_time.isoformat()
diff --git a/mta_test.py b/mta_test.py
deleted file mode 100644
index a0cf048..0000000
--- a/mta_test.py
+++ /dev/null
@@ -1,62 +0,0 @@
-import os
-from dotenv import load_dotenv
-from mta_manager import MTA
-import threading
-
-from time import sleep
-from pprint import pprint
-
-load_dotenv()
-
-api_key = os.getenv('MTA_API_KEY', '')
-mtaController = MTA(
- api_key,
- ["A", "C", "E", "1", "2", "3"],
- ["127S", "127N", "A27N", "A27S"]
-)
-
-
-async def mta_callback(trains):
- print("We are inside of the call back now")
- print(len(trains))
- pprint([str(route) for route in trains])
- pprint(mtaController.get_time_arriving_at_stations(trains))
-
-
-class Threadwrapper(threading.Thread):
- def __init__(self, run):
- threading.Thread.__init__(self)
- self.run = run
-
- def run(self):
- self.run()
-
-
-def start_mta():
- mtaController.add_callback(mta_callback)
- mtaController.start_updates()
-
-
-def stop_mta():
- sleep(10)
- mtaController.stop_updates()
-
-
-threadLock = threading.Lock()
-threads = []
-
-# Create new threads
-thread1 = Threadwrapper(start_mta)
-thread2 = Threadwrapper(stop_mta)
-
-thread1.start()
-thread2.start()
-
-# Add threads to thread list
-threads.append(thread1)
-threads.append(thread2)
-
-# Wait for all threads to complete
-for t in threads:
- t.join()
-print("Exiting Main Thread")
diff --git a/node_modules/.yarn-integrity b/node_modules/.yarn-integrity
new file mode 100644
index 0000000..553cf2e
--- /dev/null
+++ b/node_modules/.yarn-integrity
@@ -0,0 +1,10 @@
+{
+ "systemParams": "linux-x64-115",
+ "modulesFolders": [],
+ "flags": [],
+ "linkedModules": [],
+ "topLevelPatterns": [],
+ "lockfileEntries": {},
+ "files": [],
+ "artifacts": {}
+}
\ No newline at end of file
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..c1b0c2d
--- /dev/null
+++ b/package.json
@@ -0,0 +1,3 @@
+{
+ "packageManager": "yarn@4.1.0"
+}
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..8b2795c
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,77 @@
+[project]
+name = "pi-mta-sign"
+version = "0.1.0"
+description = ""
+authors = [{ name = "Lucas Oskorep", email = "lucas.oskorep@gmail.com" }]
+license = "MIT"
+readme = "README.md"
+requires-python = ">=3.14"
+dependencies = [
+ "requests>=2.31.0",
+ "fastapi>=0.100.0",
+ "uvicorn>=0.22.0",
+ "python-dotenv>=1.0.0",
+ "fastapi-utils>=0.2.1",
+ "gtfs-realtime-bindings>=1.0.0",
+ "typing_inspect>=0.9.0",
+]
+
+[dependency-groups]
+dev = [
+ "ruff>=0.0.277",
+ "pytest>=8.0.0",
+ "httpx>=0.27.0",
+]
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["mta_api_client", "mta_sign_server"]
+
+[tool.ruff]
+# Exclude a variety of commonly ignored directories.
+exclude = [
+ ".bzr",
+ ".direnv",
+ ".eggs",
+ ".git",
+ ".git-rewrite",
+ ".hg",
+ ".mypy_cache",
+ ".nox",
+ ".pants.d",
+ ".pytype",
+ ".ruff_cache",
+ ".svn",
+ ".tox",
+ ".venv",
+ "__pypackages__",
+ "_build",
+ "buck-out",
+ "build",
+ "dist",
+ "node_modules",
+ "venv",
+]
+# Same as Black.
+line-length = 120
+
+# Target Python 3.14.
+target-version = "py314"
+
+[tool.ruff.lint]
+# Enable the pycodestyle (`E`) and Pyflakes (`F`) rules by default.
+select = ["E", "F"]
+ignore = []
+
+# Allow autofix for all enabled rules (when `--fix`) is provided.
+fixable = ["ALL"]
+unfixable = []
+
+# Allow unused variables when underscore-prefixed.
+dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+
+[tool.ruff.lint.per-file-ignores]
+"__init__.py" = ["F401"]
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index b5dd8ae..0000000
Binary files a/requirements.txt and /dev/null differ
diff --git a/ruff.toml b/ruff.toml
deleted file mode 100644
index 9471f8a..0000000
--- a/ruff.toml
+++ /dev/null
@@ -1,38 +0,0 @@
-# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
-select = ["E", "F"]
-ignore = []
-
-# Allow autofix for all enabled rules (when `--fix`) is provided.
-fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
-unfixable = []
-
-# Exclude a variety of commonly ignored directories.
-exclude = [
- ".bzr",
- ".direnv",
- ".eggs",
- ".git",
- ".git-rewrite",
- ".hg",
- ".mypy_cache",
- ".nox",
- ".pants.d",
- ".pytype",
- ".ruff_cache",
- ".svn",
- ".tox",
- ".venv",
- "__pypackages__",
- "_build",
- "buck-out",
- "build",
- "dist",
- "node_modules",
- "venv",
-]
-
-line-length = 120
-
-dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
-
-target-version = "py311"
diff --git a/server.py b/server.py
deleted file mode 100644
index 775e408..0000000
--- a/server.py
+++ /dev/null
@@ -1,136 +0,0 @@
-import os
-import threading
-import pandas as pd
-
-from deepdiff import DeepDiff
-from datetime import datetime
-from dotenv import load_dotenv
-from flask import Flask, jsonify, render_template, request, abort
-from mta_manager import MTA
-
-load_dotenv()
-
-app = Flask(__name__)
-app.secret_key = "SuperSecretDontEvenTryToGuessMeGGEZNoRe"
-app._static_folder = os.path.abspath("templates/static/")
-
-stops = pd.read_csv("stops.txt")
-stop_ids = ["127S", "127N", "A27N", "A27S"]
-
-start_time = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
-
-
-def link_to_station(data) -> {}:
- linked_data = {}
- for key, value in data.items():
- stop_name = stops.loc[stops["stop_id"] == key]
- stop_name = stop_name["stop_name"].values[0]
- if stop_name not in linked_data:
- linked_data[stop_name] = {}
- if "N" in key:
- linked_data[stop_name]["North"] = value
- elif "S" in key:
- linked_data[stop_name]["South"] = value
- return linked_data
-
-
-@app.route("/", methods=["GET"])
-def index():
- # TODO: Shove this into a sqlite database
- station_names = sorted(list(set(stops["stop_name"].to_list())))
- return render_template(
- "layouts/index.html",
- station_names=station_names,
- station_1="42 St-Port Authority Bus Terminal",
- station_2="Times Sq-42 St"
- )
-
-
-@app.route("/start_time", methods=["GET"])
-def get_start_time():
- return start_time
-
-
-@app.route("/mta_data", methods=["POST"])
-def get_mta_data():
- global subway_data
- station = request.json["station"]
- if station in subway_data:
- mta_data = subway_data[station]
- mta_data["LastUpdated"] = subway_data["LastUpdated"]
- return jsonify(
- mta_data
- )
- else:
- abort(404)
-
-
-@app.route("/stops", methods=["GET"])
-def get_routes():
- return jsonify()
-
-
-@app.route("/get_stop_id", methods=["POST"])
-def get_stop_id():
- stop_name = request.json["stop_name"]
- stops.loc[stops["stop_name"] == stop_name]
- return jsonify({"station_changed": True})
-
-
-if __name__ == "__main__":
- api_key = os.getenv('MTA_API_KEY', '')
-
- old_data = None
- last_updated = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
-
-
- async def mta_callback(trains):
- global subway_data, old_data, last_updated
- subway_data = link_to_station(mtaController.get_time_arriving_at_stations(trains))
- subway_data["LastUpdated"] = last_updated
- if old_data is None:
- old_data = subway_data
- data_diff = DeepDiff(old_data, subway_data, ignore_order=True)
- if data_diff != {}:
- old_data = subway_data
- last_updated = datetime.now().strftime("%d/%m/%Y %H:%M:%S")
- app.logger.info(f"Updated Subway Data - {subway_data}")
-
-
- class threadWrapper(threading.Thread):
- def __init__(self, run):
- threading.Thread.__init__(self)
- self.run = run
-
- def run(self):
- self.run()
-
-
- mtaController = MTA(
- api_key,
- ["A", "C", "E", "1", "2", "3"],
- ["127S", "127N", "A27N", "A27S"]
- )
- mtaController.add_callback(mta_callback)
-
-
- def start_mta():
- while True:
- try:
- mtaController.start_updates()
- except Exception as e:
- app.logger.info(f"Exception found in update function - {e}")
-
-
- threadLock = threading.Lock()
- threads = [threadWrapper(start_mta)]
-
- for t in threads:
- t.start()
-
- debug = os.getenv("DEBUG", 'False').lower() in ('true', '1', 't')
- app.run(host="localhost", debug=True, port=5000)
-
- for t in threads:
- t.join()
- print("Exiting Main Thread")
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/test_config_api.py b/tests/test_config_api.py
new file mode 100644
index 0000000..0bfce97
--- /dev/null
+++ b/tests/test_config_api.py
@@ -0,0 +1,76 @@
+import pytest
+from fastapi.testclient import TestClient
+
+from main import app
+
+
+@pytest.fixture
+def client():
+ return TestClient(app)
+
+
+class TestStationsEndpoint:
+ def test_get_stations_returns_list(self, client):
+ response = client.get("/api/stations")
+ assert response.status_code == 200
+ data = response.json()
+ assert "stations" in data
+ assert isinstance(data["stations"], list)
+
+ def test_get_stations_returns_station_objects(self, client):
+ response = client.get("/api/stations")
+ assert response.status_code == 200
+ data = response.json()
+ if len(data["stations"]) > 0:
+ station = data["stations"][0]
+ assert "id" in station
+ assert "name" in station
+
+ def test_get_stations_search_filters_by_name(self, client):
+ response = client.get("/api/stations", params={"search": "Times"})
+ assert response.status_code == 200
+ data = response.json()
+ for station in data["stations"]:
+ assert "times" in station["name"].lower() or "Times" in station["id"]
+
+ def test_get_stations_search_filters_by_id(self, client):
+ response = client.get("/api/stations", params={"search": "127"})
+ assert response.status_code == 200
+ data = response.json()
+ assert len(data["stations"]) > 0
+ found = any(s["id"] == "127" for s in data["stations"])
+ assert found
+
+
+class TestLinesEndpoint:
+ def test_get_lines_returns_list(self, client):
+ response = client.get("/api/lines")
+ assert response.status_code == 200
+ data = response.json()
+ assert "lines" in data
+ assert isinstance(data["lines"], list)
+
+ def test_get_lines_contains_expected_lines(self, client):
+ response = client.get("/api/lines")
+ assert response.status_code == 200
+ data = response.json()
+ lines = data["lines"]
+ # Check for some known lines
+ assert "A" in lines
+ assert "C" in lines
+ assert "E" in lines
+ assert "1" in lines
+ assert "L" in lines
+
+ def test_get_lines_are_sorted(self, client):
+ response = client.get("/api/lines")
+ assert response.status_code == 200
+ data = response.json()
+ lines = data["lines"]
+ assert lines == sorted(lines)
+
+
+class TestConfigEndpoint:
+ def test_get_config_returns_response(self, client):
+ response = client.get("/api/config")
+ assert response.status_code == 200
diff --git a/uv.lock b/uv.lock
new file mode 100644
index 0000000..88b2ea8
--- /dev/null
+++ b/uv.lock
@@ -0,0 +1,476 @@
+version = 1
+revision = 3
+requires-python = ">=3.14"
+
+[[package]]
+name = "annotated-doc"
+version = "0.0.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/57/ba/046ceea27344560984e26a590f90bc7f4a75b06701f653222458922b558c/annotated_doc-0.0.4.tar.gz", hash = "sha256:fbcda96e87e9c92ad167c2e53839e57503ecfda18804ea28102353485033faa4", size = 7288, upload-time = "2025-11-10T22:07:42.062Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/d3/26bf1008eb3d2daa8ef4cacc7f3bfdc11818d111f7e2d0201bc6e3b49d45/annotated_doc-0.0.4-py3-none-any.whl", hash = "sha256:571ac1dc6991c450b25a9c2d84a3705e2ae7a53467b5d111c24fa8baabbed320", size = 5303, upload-time = "2025-11-10T22:07:40.673Z" },
+]
+
+[[package]]
+name = "annotated-types"
+version = "0.7.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
+]
+
+[[package]]
+name = "anyio"
+version = "4.12.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" },
+]
+
+[[package]]
+name = "certifi"
+version = "2026.1.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" },
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.4.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" },
+ { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" },
+ { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" },
+ { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" },
+ { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" },
+ { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" },
+ { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" },
+ { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" },
+ { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" },
+ { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" },
+ { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" },
+ { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" },
+ { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" },
+ { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" },
+ { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" },
+ { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
+]
+
+[[package]]
+name = "click"
+version = "8.3.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/3d/fa/656b739db8587d7b5dfa22e22ed02566950fbfbcdc20311993483657a5c0/click-8.3.1.tar.gz", hash = "sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a", size = 295065, upload-time = "2025-11-15T20:45:42.706Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/98/78/01c019cdb5d6498122777c1a43056ebb3ebfeef2076d9d026bfe15583b2b/click-8.3.1-py3-none-any.whl", hash = "sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6", size = 108274, upload-time = "2025-11-15T20:45:41.139Z" },
+]
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
+]
+
+[[package]]
+name = "fastapi"
+version = "0.128.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-doc" },
+ { name = "pydantic" },
+ { name = "starlette" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/52/08/8c8508db6c7b9aae8f7175046af41baad690771c9bcde676419965e338c7/fastapi-0.128.0.tar.gz", hash = "sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a", size = 365682, upload-time = "2025-12-27T15:21:13.714Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5c/05/5cbb59154b093548acd0f4c7c474a118eda06da25aa75c616b72d8fcd92a/fastapi-0.128.0-py3-none-any.whl", hash = "sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d", size = 103094, upload-time = "2025-12-27T15:21:12.154Z" },
+]
+
+[[package]]
+name = "fastapi-utils"
+version = "0.8.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "fastapi" },
+ { name = "psutil" },
+ { name = "pydantic" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/dd/af/57c949675176acf389d94fbccd369b486579a952637fc6fb104f1bc3d0c3/fastapi_utils-0.8.0.tar.gz", hash = "sha256:eca834e80c09f85df30004fe5e861981262b296f60c93d5a1a1416fe4c784140", size = 16496, upload-time = "2024-11-11T08:30:03.852Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/43/8b/cef8cfed7ed77d52fc772b1c7b966ba019a3f50b65a2b3625a0f3b7f6f53/fastapi_utils-0.8.0-py3-none-any.whl", hash = "sha256:6c4d507a76bab9a016cee0c4fa3a4638c636b2b2689e39c62254b1b2e4e81825", size = 18495, upload-time = "2024-11-11T08:30:01.914Z" },
+]
+
+[[package]]
+name = "gtfs-realtime-bindings"
+version = "2.0.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "protobuf" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/6b/9b/c33d7889ff8d24cc9e9ae82a83fb9defba3f6595312f056cb62937dd1b33/gtfs_realtime_bindings-2.0.0.tar.gz", hash = "sha256:861a9dcf4c40f9a59520044d870e336b00894ad5638bcf2c4a9b998923543b42", size = 6231, upload-time = "2025-12-03T19:19:40.273Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/91/d7/a5a71c655fd10c98fadb00d4db080195ced839445f410684fa6dfb901c28/gtfs_realtime_bindings-2.0.0-py3-none-any.whl", hash = "sha256:e66e581dfccad20e3b9eaed36aae106f945c2f5e506b03a63d37070096b8de39", size = 5303, upload-time = "2025-12-03T19:19:38.845Z" },
+]
+
+[[package]]
+name = "h11"
+version = "0.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
+]
+
+[[package]]
+name = "httpcore"
+version = "1.0.9"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "h11" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
+]
+
+[[package]]
+name = "httpx"
+version = "0.28.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+ { name = "certifi" },
+ { name = "httpcore" },
+ { name = "idna" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
+]
+
+[[package]]
+name = "idna"
+version = "3.11"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
+]
+
+[[package]]
+name = "iniconfig"
+version = "2.3.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
+]
+
+[[package]]
+name = "mypy-extensions"
+version = "1.1.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
+]
+
+[[package]]
+name = "packaging"
+version = "25.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" },
+]
+
+[[package]]
+name = "pi-mta-sign"
+version = "0.1.0"
+source = { editable = "." }
+dependencies = [
+ { name = "fastapi" },
+ { name = "fastapi-utils" },
+ { name = "gtfs-realtime-bindings" },
+ { name = "python-dotenv" },
+ { name = "requests" },
+ { name = "typing-inspect" },
+ { name = "uvicorn" },
+]
+
+[package.dev-dependencies]
+dev = [
+ { name = "httpx" },
+ { name = "pytest" },
+ { name = "ruff" },
+]
+
+[package.metadata]
+requires-dist = [
+ { name = "fastapi", specifier = ">=0.100.0" },
+ { name = "fastapi-utils", specifier = ">=0.2.1" },
+ { name = "gtfs-realtime-bindings", specifier = ">=1.0.0" },
+ { name = "python-dotenv", specifier = ">=1.0.0" },
+ { name = "requests", specifier = ">=2.31.0" },
+ { name = "typing-inspect", specifier = ">=0.9.0" },
+ { name = "uvicorn", specifier = ">=0.22.0" },
+]
+
+[package.metadata.requires-dev]
+dev = [
+ { name = "httpx", specifier = ">=0.27.0" },
+ { name = "pytest", specifier = ">=8.0.0" },
+ { name = "ruff", specifier = ">=0.0.277" },
+]
+
+[[package]]
+name = "pluggy"
+version = "1.6.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
+]
+
+[[package]]
+name = "protobuf"
+version = "6.33.4"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/53/b8/cda15d9d46d03d4aa3a67cb6bffe05173440ccf86a9541afaf7ac59a1b6b/protobuf-6.33.4.tar.gz", hash = "sha256:dc2e61bca3b10470c1912d166fe0af67bfc20eb55971dcef8dfa48ce14f0ed91", size = 444346, upload-time = "2026-01-12T18:33:40.109Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e0/be/24ef9f3095bacdf95b458543334d0c4908ccdaee5130420bf064492c325f/protobuf-6.33.4-cp310-abi3-win32.whl", hash = "sha256:918966612c8232fc6c24c78e1cd89784307f5814ad7506c308ee3cf86662850d", size = 425612, upload-time = "2026-01-12T18:33:29.656Z" },
+ { url = "https://files.pythonhosted.org/packages/31/ad/e5693e1974a28869e7cd244302911955c1cebc0161eb32dfa2b25b6e96f0/protobuf-6.33.4-cp310-abi3-win_amd64.whl", hash = "sha256:8f11ffae31ec67fc2554c2ef891dcb561dae9a2a3ed941f9e134c2db06657dbc", size = 436962, upload-time = "2026-01-12T18:33:31.345Z" },
+ { url = "https://files.pythonhosted.org/packages/66/15/6ee23553b6bfd82670207ead921f4d8ef14c107e5e11443b04caeb5ab5ec/protobuf-6.33.4-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2fe67f6c014c84f655ee06f6f66213f9254b3a8b6bda6cda0ccd4232c73c06f0", size = 427612, upload-time = "2026-01-12T18:33:32.646Z" },
+ { url = "https://files.pythonhosted.org/packages/2b/48/d301907ce6d0db75f959ca74f44b475a9caa8fcba102d098d3c3dd0f2d3f/protobuf-6.33.4-cp39-abi3-manylinux2014_aarch64.whl", hash = "sha256:757c978f82e74d75cba88eddec479df9b99a42b31193313b75e492c06a51764e", size = 324484, upload-time = "2026-01-12T18:33:33.789Z" },
+ { url = "https://files.pythonhosted.org/packages/92/1c/e53078d3f7fe710572ab2dcffd993e1e3b438ae71cfc031b71bae44fcb2d/protobuf-6.33.4-cp39-abi3-manylinux2014_s390x.whl", hash = "sha256:c7c64f259c618f0bef7bee042075e390debbf9682334be2b67408ec7c1c09ee6", size = 339256, upload-time = "2026-01-12T18:33:35.231Z" },
+ { url = "https://files.pythonhosted.org/packages/e8/8e/971c0edd084914f7ee7c23aa70ba89e8903918adca179319ee94403701d5/protobuf-6.33.4-cp39-abi3-manylinux2014_x86_64.whl", hash = "sha256:3df850c2f8db9934de4cf8f9152f8dc2558f49f298f37f90c517e8e5c84c30e9", size = 323311, upload-time = "2026-01-12T18:33:36.305Z" },
+ { url = "https://files.pythonhosted.org/packages/75/b1/1dc83c2c661b4c62d56cc081706ee33a4fc2835bd90f965baa2663ef7676/protobuf-6.33.4-py3-none-any.whl", hash = "sha256:1fe3730068fcf2e595816a6c34fe66eeedd37d51d0400b72fabc848811fdc1bc", size = 170532, upload-time = "2026-01-12T18:33:39.199Z" },
+]
+
+[[package]]
+name = "psutil"
+version = "5.9.8"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/90/c7/6dc0a455d111f68ee43f27793971cf03fe29b6ef972042549db29eec39a2/psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c", size = 503247, upload-time = "2024-01-19T20:47:09.517Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/e7/e3/07ae864a636d70a8a6f58da27cb1179192f1140d5d1da10886ade9405797/psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81", size = 248702, upload-time = "2024-01-19T20:47:36.303Z" },
+ { url = "https://files.pythonhosted.org/packages/b3/bd/28c5f553667116b2598b9cc55908ec435cb7f77a34f2bff3e3ca765b0f78/psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421", size = 285242, upload-time = "2024-01-19T20:47:39.65Z" },
+ { url = "https://files.pythonhosted.org/packages/c5/4f/0e22aaa246f96d6ac87fe5ebb9c5a693fbe8877f537a1022527c47ca43c5/psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4", size = 288191, upload-time = "2024-01-19T20:47:43.078Z" },
+ { url = "https://files.pythonhosted.org/packages/6e/f5/2aa3a4acdc1e5940b59d421742356f133185667dd190b166dbcfcf5d7b43/psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0", size = 251252, upload-time = "2024-01-19T20:47:52.88Z" },
+ { url = "https://files.pythonhosted.org/packages/93/52/3e39d26feae7df0aa0fd510b14012c3678b36ed068f7d78b8d8784d61f0e/psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf", size = 255090, upload-time = "2024-01-19T20:47:56.019Z" },
+ { url = "https://files.pythonhosted.org/packages/05/33/2d74d588408caedd065c2497bdb5ef83ce6082db01289a1e1147f6639802/psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8", size = 249898, upload-time = "2024-01-19T20:47:59.238Z" },
+]
+
+[[package]]
+name = "pydantic"
+version = "2.12.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "annotated-types" },
+ { name = "pydantic-core" },
+ { name = "typing-extensions" },
+ { name = "typing-inspection" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" },
+]
+
+[[package]]
+name = "pydantic-core"
+version = "2.41.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" },
+ { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" },
+ { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" },
+ { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" },
+ { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" },
+ { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" },
+ { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" },
+ { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" },
+ { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" },
+ { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" },
+ { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" },
+ { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" },
+ { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" },
+ { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" },
+ { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" },
+ { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" },
+ { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" },
+ { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" },
+ { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" },
+ { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" },
+ { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" },
+ { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" },
+ { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" },
+ { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" },
+ { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" },
+ { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" },
+ { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" },
+]
+
+[[package]]
+name = "pygments"
+version = "2.19.2"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
+]
+
+[[package]]
+name = "pytest"
+version = "9.0.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "colorama", marker = "sys_platform == 'win32'" },
+ { name = "iniconfig" },
+ { name = "packaging" },
+ { name = "pluggy" },
+ { name = "pygments" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
+]
+
+[[package]]
+name = "python-dotenv"
+version = "1.2.1"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" },
+]
+
+[[package]]
+name = "requests"
+version = "2.32.5"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "certifi" },
+ { name = "charset-normalizer" },
+ { name = "idna" },
+ { name = "urllib3" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
+]
+
+[[package]]
+name = "ruff"
+version = "0.14.13"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/50/0a/1914efb7903174b381ee2ffeebb4253e729de57f114e63595114c8ca451f/ruff-0.14.13.tar.gz", hash = "sha256:83cd6c0763190784b99650a20fec7633c59f6ebe41c5cc9d45ee42749563ad47", size = 6059504, upload-time = "2026-01-15T20:15:16.918Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/c3/ae/0deefbc65ca74b0ab1fd3917f94dc3b398233346a74b8bbb0a916a1a6bf6/ruff-0.14.13-py3-none-linux_armv6l.whl", hash = "sha256:76f62c62cd37c276cb03a275b198c7c15bd1d60c989f944db08a8c1c2dbec18b", size = 13062418, upload-time = "2026-01-15T20:14:50.779Z" },
+ { url = "https://files.pythonhosted.org/packages/47/df/5916604faa530a97a3c154c62a81cb6b735c0cb05d1e26d5ad0f0c8ac48a/ruff-0.14.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:914a8023ece0528d5cc33f5a684f5f38199bbb566a04815c2c211d8f40b5d0ed", size = 13442344, upload-time = "2026-01-15T20:15:07.94Z" },
+ { url = "https://files.pythonhosted.org/packages/4c/f3/e0e694dd69163c3a1671e102aa574a50357536f18a33375050334d5cd517/ruff-0.14.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d24899478c35ebfa730597a4a775d430ad0d5631b8647a3ab368c29b7e7bd063", size = 12354720, upload-time = "2026-01-15T20:15:09.854Z" },
+ { url = "https://files.pythonhosted.org/packages/c3/e8/67f5fcbbaee25e8fc3b56cc33e9892eca7ffe09f773c8e5907757a7e3bdb/ruff-0.14.13-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9aaf3870f14d925bbaf18b8a2347ee0ae7d95a2e490e4d4aea6813ed15ebc80e", size = 12774493, upload-time = "2026-01-15T20:15:20.908Z" },
+ { url = "https://files.pythonhosted.org/packages/6b/ce/d2e9cb510870b52a9565d885c0d7668cc050e30fa2c8ac3fb1fda15c083d/ruff-0.14.13-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac5b7f63dd3b27cc811850f5ffd8fff845b00ad70e60b043aabf8d6ecc304e09", size = 12815174, upload-time = "2026-01-15T20:15:05.74Z" },
+ { url = "https://files.pythonhosted.org/packages/88/00/c38e5da58beebcf4fa32d0ddd993b63dfacefd02ab7922614231330845bf/ruff-0.14.13-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78d2b1097750d90ba82ce4ba676e85230a0ed694178ca5e61aa9b459970b3eb9", size = 13680909, upload-time = "2026-01-15T20:15:14.537Z" },
+ { url = "https://files.pythonhosted.org/packages/61/61/cd37c9dd5bd0a3099ba79b2a5899ad417d8f3b04038810b0501a80814fd7/ruff-0.14.13-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:7d0bf87705acbbcb8d4c24b2d77fbb73d40210a95c3903b443cd9e30824a5032", size = 15144215, upload-time = "2026-01-15T20:15:22.886Z" },
+ { url = "https://files.pythonhosted.org/packages/56/8a/85502d7edbf98c2df7b8876f316c0157359165e16cdf98507c65c8d07d3d/ruff-0.14.13-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3eb5da8e2c9e9f13431032fdcbe7681de9ceda5835efee3269417c13f1fed5c", size = 14706067, upload-time = "2026-01-15T20:14:48.271Z" },
+ { url = "https://files.pythonhosted.org/packages/7e/2f/de0df127feb2ee8c1e54354dc1179b4a23798f0866019528c938ba439aca/ruff-0.14.13-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:642442b42957093811cd8d2140dfadd19c7417030a7a68cf8d51fcdd5f217427", size = 14133916, upload-time = "2026-01-15T20:14:57.357Z" },
+ { url = "https://files.pythonhosted.org/packages/0d/77/9b99686bb9fe07a757c82f6f95e555c7a47801a9305576a9c67e0a31d280/ruff-0.14.13-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4acdf009f32b46f6e8864af19cbf6841eaaed8638e65c8dac845aea0d703c841", size = 13859207, upload-time = "2026-01-15T20:14:55.111Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/46/2bdcb34a87a179a4d23022d818c1c236cb40e477faf0d7c9afb6813e5876/ruff-0.14.13-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:591a7f68860ea4e003917d19b5c4f5ac39ff558f162dc753a2c5de897fd5502c", size = 14043686, upload-time = "2026-01-15T20:14:52.841Z" },
+ { url = "https://files.pythonhosted.org/packages/1a/a9/5c6a4f56a0512c691cf143371bcf60505ed0f0860f24a85da8bd123b2bf1/ruff-0.14.13-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:774c77e841cc6e046fc3e91623ce0903d1cd07e3a36b1a9fe79b81dab3de506b", size = 12663837, upload-time = "2026-01-15T20:15:18.921Z" },
+ { url = "https://files.pythonhosted.org/packages/fe/bb/b920016ece7651fa7fcd335d9d199306665486694d4361547ccb19394c44/ruff-0.14.13-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:61f4e40077a1248436772bb6512db5fc4457fe4c49e7a94ea7c5088655dd21ae", size = 12805867, upload-time = "2026-01-15T20:14:59.272Z" },
+ { url = "https://files.pythonhosted.org/packages/7d/b3/0bd909851e5696cd21e32a8fc25727e5f58f1934b3596975503e6e85415c/ruff-0.14.13-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6d02f1428357fae9e98ac7aa94b7e966fd24151088510d32cf6f902d6c09235e", size = 13208528, upload-time = "2026-01-15T20:15:03.732Z" },
+ { url = "https://files.pythonhosted.org/packages/3b/3b/e2d94cb613f6bbd5155a75cbe072813756363eba46a3f2177a1fcd0cd670/ruff-0.14.13-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e399341472ce15237be0c0ae5fbceca4b04cd9bebab1a2b2c979e015455d8f0c", size = 13929242, upload-time = "2026-01-15T20:15:11.918Z" },
+ { url = "https://files.pythonhosted.org/packages/6a/c5/abd840d4132fd51a12f594934af5eba1d5d27298a6f5b5d6c3be45301caf/ruff-0.14.13-py3-none-win32.whl", hash = "sha256:ef720f529aec113968b45dfdb838ac8934e519711da53a0456038a0efecbd680", size = 12919024, upload-time = "2026-01-15T20:14:43.647Z" },
+ { url = "https://files.pythonhosted.org/packages/c2/55/6384b0b8ce731b6e2ade2b5449bf07c0e4c31e8a2e68ea65b3bafadcecc5/ruff-0.14.13-py3-none-win_amd64.whl", hash = "sha256:6070bd026e409734b9257e03e3ef18c6e1a216f0435c6751d7a8ec69cb59abef", size = 14097887, upload-time = "2026-01-15T20:15:01.48Z" },
+ { url = "https://files.pythonhosted.org/packages/4d/e1/7348090988095e4e39560cfc2f7555b1b2a7357deba19167b600fdf5215d/ruff-0.14.13-py3-none-win_arm64.whl", hash = "sha256:7ab819e14f1ad9fe39f246cfcc435880ef7a9390d81a2b6ac7e01039083dd247", size = 13080224, upload-time = "2026-01-15T20:14:45.853Z" },
+]
+
+[[package]]
+name = "starlette"
+version = "0.50.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "anyio" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/ba/b8/73a0e6a6e079a9d9cfa64113d771e421640b6f679a52eeb9b32f72d871a1/starlette-0.50.0.tar.gz", hash = "sha256:a2a17b22203254bcbc2e1f926d2d55f3f9497f769416b3190768befe598fa3ca", size = 2646985, upload-time = "2025-11-01T15:25:27.516Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/d9/52/1064f510b141bd54025f9b55105e26d1fa970b9be67ad766380a3c9b74b0/starlette-0.50.0-py3-none-any.whl", hash = "sha256:9e5391843ec9b6e472eed1365a78c8098cfceb7a74bfd4d6b1c0c0095efb3bca", size = 74033, upload-time = "2025-11-01T15:25:25.461Z" },
+]
+
+[[package]]
+name = "typing-extensions"
+version = "4.15.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
+]
+
+[[package]]
+name = "typing-inspect"
+version = "0.9.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "mypy-extensions" },
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/dc/74/1789779d91f1961fa9438e9a8710cdae6bd138c80d7303996933d117264a/typing_inspect-0.9.0.tar.gz", hash = "sha256:b23fc42ff6f6ef6954e4852c1fb512cdd18dbea03134f91f856a95ccc9461f78", size = 13825, upload-time = "2023-05-24T20:25:47.612Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl", hash = "sha256:9ee6fc59062311ef8547596ab6b955e1b8aa46242d854bfc78f4f6b0eff35f9f", size = 8827, upload-time = "2023-05-24T20:25:45.287Z" },
+]
+
+[[package]]
+name = "typing-inspection"
+version = "0.4.2"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "typing-extensions" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
+]
+
+[[package]]
+name = "urllib3"
+version = "2.6.3"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" },
+]
+
+[[package]]
+name = "uvicorn"
+version = "0.40.0"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "click" },
+ { name = "h11" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/c3/d1/8f3c683c9561a4e6689dd3b1d345c815f10f86acd044ee1fb9a4dcd0b8c5/uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea", size = 81761, upload-time = "2025-12-21T14:16:22.45Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/3d/d8/2083a1daa7439a66f3a48589a57d576aa117726762618f6bb09fe3798796/uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee", size = 68502, upload-time = "2025-12-21T14:16:21.041Z" },
+]