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 5AM

 

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 5AM

 

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 AvOzone 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 AvOzone 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)} + /> + ))} + + +
+
+ ) +} 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 ( + + ) +} 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') && ( + + )} + + {availableDirections.has('South') && ( + + )} + +
+ {availableLines.map(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 ( +
+
+ {`${routeId} +
+

+ {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" }, +]