diff --git a/docs/auth-design.md b/docs/auth-design.md new file mode 100644 index 00000000..4df5d4d7 --- /dev/null +++ b/docs/auth-design.md @@ -0,0 +1,163 @@ +# Auth Design + +## Overview + +Two plugins handle all auth/CSRF injection globally — no per-callsite wiring needed. + +| Plugin | Runs on | Does what | +|---|---|---| +| `csrf.client` | Browser | Wraps `$fetch` and `fetch` to add CSRF header to same-origin requests | +| `auth.server` | SSR | Wraps `$fetch` and `fetch` to add JWT + API key to backend requests | + +Both plugins wrap `globalThis.$fetch` (ofetch) and `globalThis.fetch` (native), so all request mechanisms — `useFetch`, `$fetch`, and Apollo's `createUploadLink` — get headers injected automatically. + +## Request Flows + +### Browser → proxy → backend + +1. Browser sends session cookie automatically (`credentials: 'same-origin'`) +2. CSRF header added globally by `csrf.client` +3. Request hits `/api/proxy/{backend}/...` on the same origin (e.g., `/api/proxy/default/query`) +4. `nuxt-csurf` validates the CSRF token +5. Proxy extracts backend name from path, looks up `proxyBase` config +6. Proxy extracts JWT from session cookie via `useAuth0Session(event)` +7. If logged in: forwards JWT + API key to backend +8. If anonymous: forwards API key only + +### SSR → backend (direct) + +1. `auth.server` plugin injects JWT + API key into both `$fetch` and `fetch` +2. Requests go directly to backend (via `proxyBase` URL), bypassing the proxy +3. If logged in: JWT from the original request's session +4. If anonymous: API key only + +## Composables + +- `useUser` — reads auth0-nuxt session state + enriched roles from GraphQL +- `useLogin` — navigates to `/auth/login` +- `useLogout` — navigates to `/auth/logout` + +## User Enrichment + +The `/api/auth/session` endpoint returns the auth0-nuxt session claims enriched with roles and identity from the GraphQL `me` endpoint (if a backend is configured). This is a single server-side request that combines auth0 identity with application-level data. + +`auth/plugin.client` is a global route middleware that: +1. Checks if `useState('auth0_user')` is populated (it will be during SSR via auth0-nuxt's server middleware) +2. If not (e.g., `ssr: false`), fetches `/api/auth/session` to populate it +3. Reads `tlv2_roles` and `tlv2_id` from the session response and stores them in `useState` +4. Caches for 10 minutes before re-checking + +During SSR, roles are not yet available — only identity (name, email, sub) from the auth0-nuxt session is present. Role-gated UI renders after client-side hydration. A future improvement is to cache the `me` response in a server-side KV store so roles are available during SSR. + +## CSRF + +CSRF protection is provided by `nuxt-csurf` and applies to all requests, including anonymous ones. The CSRF token prevents other websites from using the proxy as an open relay — either with a logged-in user's session cookie (classic CSRF) or with the module's API key (anonymous abuse). + +The `csrf.client` plugin wraps both `globalThis.$fetch` (ofetch) and `globalThis.fetch` (native) so that same-origin client-side requests automatically include the CSRF header. Cross-origin requests (e.g., map tiles) are excluded to avoid triggering CORS preflights. No per-callsite injection is needed. + +## Anonymous Access + +Anonymous users (no auth0 session) can access public data through the proxy. The proxy forwards these requests with the API key only (no JWT). The backend decides what data to serve based on the presence or absence of a JWT. + +## Auth0 Integration + +Authentication is handled entirely by `@auth0/auth0-nuxt`, which manages server-side sessions using HTTP-only encrypted cookies. The user's JWT never touches client-side JavaScript. Login and logout are server-side routes (`/auth/login`, `/auth/logout`) provided by auth0-nuxt. + +## Key Files + +| File | Purpose | +|---|---| +| `src/module.ts` | Installs `nuxt-csurf` and `@auth0/auth0-nuxt`, registers plugins | +| `src/runtime/plugins/csrf.client.ts` | Global CSRF header injection (browser) | +| `src/runtime/plugins/auth.server.ts` | Global JWT + API key injection (SSR) | +| `src/runtime/plugins/apollo.ts` | Apollo client setup (no auth awareness — handled by plugins) | +| `src/runtime/plugins/proxy.ts` | `/api/proxy/{backend}/**` handler, routes to configured proxyBase | +| `src/runtime/lib/util/proxy.ts` | Proxy implementation, forwards to backend with auth headers | +| `src/runtime/server/api/auth/session.get.ts` | Session endpoint, returns auth0 claims + enriched roles | +| `src/runtime/auth/plugin.client.ts` | Route middleware that populates user state from session endpoint | +| `src/runtime/auth/useUser.ts` | `useUser` composable (reads session + enriched roles) | +| `src/runtime/auth/useLogin.ts` | `useLogin` composable (redirects to `/auth/login`) | +| `src/runtime/auth/useLogout.ts` | `useLogout` composable (redirects to `/auth/logout`) | +| `src/runtime/auth/types.ts` | `TlUser` interface | +| `src/runtime/server/useSession.ts` | `useAuth0Session` — single entry point for all server-side auth0 calls | + +## Migration Guide for Existing Consumers + +### Auth0 Configuration + +Consumer apps must switch from Auth0 SPA application credentials to a **Regular Web Application** in the Auth0 console. + +1. Create or reconfigure an Auth0 application as "Regular Web Application" +2. Set Allowed Callback URLs to `https:///auth/callback` +3. Set Allowed Logout URLs to `https://` +4. Ensure the Auth0 API has "Allow Offline Access" enabled (for refresh tokens) +5. If using a custom Auth0 domain (e.g., `auth.example.com`), use that as the domain — not the raw `*.auth0.com` tenant domain — so the JWT `iss` claim matches what the backend expects + +### Environment Variables + +Replace the old SPA-style Auth0 config with server-side env vars: + +``` +# Remove these (no longer used) +# NUXT_PUBLIC_TLV2_AUTH0_CLIENT_ID +# NUXT_PUBLIC_TLV2_AUTH0_DOMAIN +# NUXT_PUBLIC_TLV2_AUTH0_AUDIENCE +# NUXT_PUBLIC_TLV2_AUTH0_SCOPE +# NUXT_PUBLIC_TLV2_AUTH0_REDIRECT_URI +# NUXT_PUBLIC_TLV2_AUTH0_LOGOUT_URI + +# Add these (server-side only, never exposed to client) +NUXT_AUTH0_DOMAIN=auth.example.com +NUXT_AUTH0_CLIENT_ID=... +NUXT_AUTH0_CLIENT_SECRET=... +NUXT_AUTH0_SESSION_SECRET= +NUXT_AUTH0_APP_BASE_URL=https://your-app.example.com +NUXT_AUTH0_AUDIENCE=https://api.transit.land +``` + +### Module Options + +Remove these options from your `nuxt.config.ts` module config: + +- `authMode` — no longer exists, server mode is the only mode +- `auth0ClientId`, `auth0Domain`, `auth0Audience`, `auth0Scope`, `auth0RedirectUri`, `auth0LogoutUri` — replaced by `NUXT_AUTH0_*` env vars +- `apiBase` — no longer used, client routes through `/api/proxy/{backend}` proxy +- `useProxy` — removed, proxy is always active + +### Code Changes + +- **Remove `useAuthHeaders()` calls.** CSRF and auth headers are injected globally. Delete any manual header injection in `onRequest` callbacks or fetch options. +- **`useUser()`, `useLogin()`, `useLogout()`** — API is unchanged, no code changes needed. +- **`clearUser()`** — removed. Logout navigates to `/auth/logout` which clears the session server-side. +- **Direct imports from `tlv2-ui/lib/auth`** — `useUser` and `TlUser` are still exported. `clearUser` and the `User` class are removed. + +### User Impact + +All existing user sessions will be invalidated on deployment. Users will need to log in again — the old SPA tokens (stored in browser memory/localStorage) are not compatible with the new server-side session cookies. Users who authenticated via Google or other social providers can log in again with one click. Users with email/password accounts can use Auth0's "Forgot Password" flow if needed. + +## Proxy Routing + +The proxy routes client-side requests to backend services based on the URL path: + +``` +/api/proxy/{backend}/... → proxyBase.{backend} + /... +``` + +For example, with this config: +``` +proxyBase.default = https://api.transit.land/api/v2 +proxyBase.stationEditor = https://station-api.example.com +``` + +- `/api/proxy/default/query` → `https://api.transit.land/api/v2/query` +- `/api/proxy/stationEditor/query` → `https://station-api.example.com/query` + +`useApiEndpoint(path, clientName)` generates the correct URL for each context: +- Server-side (SSR): returns the direct `proxyBase` URL +- Client-side: returns `/api/proxy/{clientName}` to route through the proxy + +If a backend name is not found in the config, the proxy responds with a 404. + +## Future Work + +- **Server-side role caching.** Cache the GraphQL `me` response in a KV store so roles are available during SSR without a round-trip on every request. diff --git a/package.json b/package.json index e28aeaae..e4780ec5 100644 --- a/package.json +++ b/package.json @@ -33,37 +33,17 @@ "types": "./dist/runtime/lib/config/index.d.ts", "import": "./dist/runtime/lib/config/index.js" }, - "./lib/geom": { - "types": "./dist/runtime/lib/geom/index.d.ts", - "import": "./dist/runtime/lib/geom/index.js" + "./lib/testutil": { + "types": "./dist/runtime/lib/testutil/index.d.ts", + "import": "./dist/runtime/lib/testutil/index.js" }, "./lib/gtfs": { "types": "./dist/runtime/lib/gtfs/index.d.ts", "import": "./dist/runtime/lib/gtfs/index.js" }, - "./lib/pathways": { - "types": "./dist/runtime/lib/pathways/index.d.ts", - "import": "./dist/runtime/lib/pathways/index.js" - }, - "./lib/testutil": { - "types": "./dist/runtime/lib/testutil/index.d.ts", - "import": "./dist/runtime/lib/testutil/index.js" - }, "./lib/util": { "types": "./dist/runtime/lib/util/index.d.ts", "import": "./dist/runtime/lib/util/index.js" - }, - "./apps/admin": { - "types": "./dist/runtime/apps/admin/index.d.ts", - "import": "./dist/runtime/apps/admin/index.js" - }, - "./apps/stations": { - "types": "./dist/runtime/apps/stations/index.d.ts", - "import": "./dist/runtime/apps/stations/index.js" - }, - "./apps/transfers": { - "types": "./dist/runtime/apps/transfers/index.d.ts", - "import": "./dist/runtime/apps/transfers/index.js" } }, "main": "./dist/module.mjs", @@ -75,29 +55,26 @@ "access": "restricted" }, "peerDependencies": { - "nuxt": "4.2.0", - "vue": "3.5.22" + "defu": ">=6.0.0", + "h3": ">=1.0.0", + "nuxt": "^4.0.0" }, "devDependencies": { "@nuxt/cli": "3.30.0", "@nuxt/devtools": "3.0.1", "@nuxt/eslint": "1.10.0", "@nuxt/eslint-config": "1.10.0", - "@nuxt/kit": "4.2.0", + "@nuxt/kit": "^4.2.0", "@nuxt/module-builder": "1.0.2", - "@nuxt/schema": "4.2.0", + "@nuxt/schema": "^4.2.0", "@nuxt/test-utils": "3.20.1", "@nuxt/types": "2.18.1", "@pollyjs/adapter-fetch": "6.0.7", "@pollyjs/core": "6.0.6", "@pollyjs/persister-fs": "6.0.6", "@stylistic/eslint-plugin": "5.5.0", - "@types/cytoscape": "3.21.9", - "@types/cytoscape-fcose": "2.2.4", - "@types/d3-scale-chromatic": "3.1.0", "@types/geojson": "7946.0.16", "@types/jsdom": "21.1.7", - "@types/mapbox__mapbox-gl-draw": "1.4.8", "@types/node": "latest", "@types/pg": "8.15.4", "@vitejs/plugin-vue": "6.0.1", @@ -109,7 +86,7 @@ "happy-dom": "18.0.1", "jsdom": "26.1.0", "nuxi": "3.30.0", - "nuxt": "4.2.0", + "nuxt": "^4.2.0", "playwright-core": "1.54.2", "sass": "1.86.0", "tsx": "4.20.6", @@ -117,48 +94,31 @@ "typescript-eslint": "8.46.3", "vite": "7.2.2", "vitest": "3.2.4", - "vue": "3.5.22", + "vue": "^3.5.0", "vue-eslint-parser": "10.2.0", - "vue-tsc": "3.1.3" + "vue-tsc": "3.2.6" }, "dependencies": { "@apollo/client": "3.13.4", - "@auth0/auth0-spa-js": "2.1.3", - "@mapbox/mapbox-gl-draw": "1.4.3", - "@maplibre/maplibre-gl-geocoder": "1.9.0", + "@auth0/auth0-nuxt": "^1.0.1", "@mdi/font": "7.4.47", - "@observablehq/plot": "0.6.17", - "@turf/centroid": "7.3.0", "@vue/apollo-composable": "4.2.2", "@vue/apollo-option": "4.2.2", - "@vueuse/core": "14.0.0", + "@vueuse/core": "14.2.1", "apollo-upload-client": "18.0.1", "bulma": "1.0.4", - "commander": "14.0.0", "csv-stringify": "6.6.0", - "cytoscape-fcose": "2.2.0", - "cytoscape": "3.31.1", - "d3-scale-chromatic": "3.1.0", "date-fns": "4.1.0", - "dayjs": "1.11.19", - "defu": "6.1.4", - "destr": "2.0.3", - "graphql-tag": "2.12.6", "graphql": "16.10.0", - "h3": "1.15.1", - "maplibre-gl": "5.2.0", + "graphql-tag": "2.12.6", "mixpanel-browser": "2.61.2", - "nuxt-csurf": "1.6.5", + "nuxt-csurf": "^1.6.5", "protomaps-themes-base": "1.3.1", - "tiny-emitter": "2.1.0", - "unstorage": "1.15.0", - "vega-embed": "7.1.0", - "vega-lite": "6.4.1", - "vega": "6.2.0", "vue-json-pretty": "2.6.0" }, "packageManager": "pnpm@10.21.0+sha512.da3337267e400fdd3d479a6c68079ac6db01d8ca4f67572083e722775a796788a7a9956613749e000fac20d424b594f7a791a5f4e2e13581c5ef947f26968a40", "pnpm": { + "minimumReleaseAge": 10080, "onlyBuiltDependencies": [ "@parcel/watcher", "esbuild", diff --git a/playground/app/pages/apps/graphql-test.vue b/playground/app/pages/apps/graphql-test.vue index 9b3f48be..677192cc 100644 --- a/playground/app/pages/apps/graphql-test.vue +++ b/playground/app/pages/apps/graphql-test.vue @@ -12,14 +12,17 @@ Not logged in. Sign in to test authenticated requests. -
- +
- - {{ errorMsg }} + + me: {{ meErrorMsg }}
@@ -44,6 +47,27 @@
+ + + feeds: {{ feedsErrorMsg }} + + +
+ + + + + + + + + + + + + +
IDonestop_id
{{ feed.id }}{{ feed.onestop_id }}
+
@@ -55,7 +79,8 @@ import { useQuery } from '@vue/apollo-composable' import { useUser } from '../../../../src/runtime/composables/useUser' const user = useUser() -const enabled = ref(false) +const meEnabled = ref(false) +const feedsEnabled = ref(false) const meQuery = gql` query { @@ -68,18 +93,42 @@ const meQuery = gql` } ` -const { result, loading, error, refetch } = useQuery(meQuery, null, () => ({ - enabled: enabled.value, +const feedsQuery = gql` + query { + feeds { + id + onestop_id + } + } +` + +const { result: meResult, loading: meLoading, error: meError, refetch: meRefetch } = useQuery(meQuery, null, () => ({ + enabled: meEnabled.value, + fetchPolicy: 'no-cache' +})) +const meData = computed(() => meResult.value?.me || null) +const meErrorMsg = computed(() => meError.value?.message || '') + +const { result: feedsResult, loading: feedsLoading, error: feedsError, refetch: feedsRefetch } = useQuery(feedsQuery, null, () => ({ + enabled: feedsEnabled.value, fetchPolicy: 'no-cache' })) -const meData = computed(() => result.value?.me || null) -const errorMsg = computed(() => error.value?.message || '') +const feedsData = computed(() => feedsResult.value?.feeds || null) +const feedsErrorMsg = computed(() => feedsError.value?.message || '') + +function runMeQuery () { + if (meEnabled.value) { + meRefetch() + } else { + meEnabled.value = true + } +} -function runQuery () { - if (enabled.value) { - refetch() +function runFeedsQuery () { + if (feedsEnabled.value) { + feedsRefetch() } else { - enabled.value = true + feedsEnabled.value = true } } diff --git a/playground/app/pages/auth.vue b/playground/app/pages/auth.vue new file mode 100644 index 00000000..40ee1ec5 --- /dev/null +++ b/playground/app/pages/auth.vue @@ -0,0 +1,64 @@ + + + diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index 1d794c95..96d6e123 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -1,13 +1,22 @@ import 'dotenv/config' export default defineNuxtConfig({ - modules: [['../src/module', { useProxy: true }]], + modules: [['../src/module', {}]], ssr: false, devtools: { enabled: true }, runtimeConfig: { + // Auth0 server-side config (use NUXT_AUTH0_* env vars) + auth0: { + domain: '', + clientId: '', + clientSecret: '', + sessionSecret: '', + appBaseUrl: '', + audience: '', + }, tlv2: { graphqlApikey: '', proxyBase: { @@ -17,18 +26,8 @@ export default defineNuxtConfig({ }, public: { tlv2: { - useProxy: true, - apiBase: { - default: '', - feedManagement: '', - }, - auth0Domain: '', - auth0ClientId: '', - auth0Audience: '', - auth0Scope: 'profile email openid', - auth0RedirectUri: '', loginGate: true, - requireLogin: true, + requireLogin: false, routes: { 'apps-admin-groups': 'admin-groups', 'apps-admin-groups-groupKey': 'admin-groups-groupKey', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 27dade22..dc410e0a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,24 +11,12 @@ importers: '@apollo/client': specifier: 3.13.4 version: 3.13.4(graphql@16.10.0) - '@auth0/auth0-spa-js': - specifier: 2.1.3 - version: 2.1.3 - '@mapbox/mapbox-gl-draw': - specifier: 1.4.3 - version: 1.4.3 - '@maplibre/maplibre-gl-geocoder': - specifier: 1.9.0 - version: 1.9.0(maplibre-gl@5.2.0) + '@auth0/auth0-nuxt': + specifier: ^1.0.1 + version: 1.0.1 '@mdi/font': specifier: 7.4.47 version: 7.4.47 - '@observablehq/plot': - specifier: 0.6.17 - version: 0.6.17 - '@turf/centroid': - specifier: 7.3.0 - version: 7.3.0 '@vue/apollo-composable': specifier: 4.2.2 version: 4.2.2(@apollo/client@3.13.4(graphql@16.10.0))(graphql@16.10.0)(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3)) @@ -36,41 +24,23 @@ importers: specifier: 4.2.2 version: 4.2.2(@apollo/client@3.13.4(graphql@16.10.0))(vue@3.5.22(typescript@5.9.3)) '@vueuse/core': - specifier: 14.0.0 - version: 14.0.0(vue@3.5.22(typescript@5.9.3)) + specifier: 14.2.1 + version: 14.2.1(vue@3.5.22(typescript@5.9.3)) apollo-upload-client: specifier: 18.0.1 version: 18.0.1(@apollo/client@3.13.4(graphql@16.10.0))(graphql@16.10.0) bulma: specifier: 1.0.4 version: 1.0.4 - commander: - specifier: 14.0.0 - version: 14.0.0 csv-stringify: specifier: 6.6.0 version: 6.6.0 - cytoscape: - specifier: 3.31.1 - version: 3.31.1 - cytoscape-fcose: - specifier: 2.2.0 - version: 2.2.0(cytoscape@3.31.1) - d3-scale-chromatic: - specifier: 3.1.0 - version: 3.1.0 date-fns: specifier: 4.1.0 version: 4.1.0 - dayjs: - specifier: 1.11.19 - version: 1.11.19 defu: - specifier: 6.1.4 + specifier: '>=6.0.0' version: 6.1.4 - destr: - specifier: 2.0.3 - version: 2.0.3 graphql: specifier: 16.10.0 version: 16.10.0 @@ -78,35 +48,17 @@ importers: specifier: 2.12.6 version: 2.12.6(graphql@16.10.0) h3: - specifier: 1.15.1 - version: 1.15.1 - maplibre-gl: - specifier: 5.2.0 - version: 5.2.0 + specifier: '>=1.0.0' + version: 1.15.10 mixpanel-browser: specifier: 2.61.2 version: 2.61.2 nuxt-csurf: - specifier: 1.6.5 + specifier: ^1.6.5 version: 1.6.5(magicast@0.5.1) protomaps-themes-base: specifier: 1.3.1 version: 1.3.1 - tiny-emitter: - specifier: 2.1.0 - version: 2.1.0 - unstorage: - specifier: 1.15.0 - version: 1.15.0(db0@0.3.4)(ioredis@5.8.2) - vega: - specifier: 6.2.0 - version: 6.2.0 - vega-embed: - specifier: 7.1.0 - version: 7.1.0(vega-lite@6.4.1(vega@6.2.0))(vega@6.2.0) - vega-lite: - specifier: 6.4.1 - version: 6.4.1(vega@6.2.0) vue-json-pretty: specifier: 2.6.0 version: 2.6.0(vue@3.5.22(typescript@5.9.3)) @@ -124,13 +76,13 @@ importers: specifier: 1.10.0 version: 1.10.0(@typescript-eslint/utils@8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.24)(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@nuxt/kit': - specifier: 4.2.0 - version: 4.2.0(magicast@0.5.1) + specifier: ^4.2.0 + version: 4.2.1(magicast@0.5.1) '@nuxt/module-builder': specifier: 1.0.2 - version: 1.0.2(@nuxt/cli@3.30.0(magicast@0.5.1))(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(sass@1.86.0)(typescript@5.9.3)(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) + version: 1.0.2(@nuxt/cli@3.30.0(magicast@0.5.1))(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(sass@1.86.0)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) '@nuxt/schema': - specifier: 4.2.0 + specifier: ^4.2.0 version: 4.2.0 '@nuxt/test-utils': specifier: 3.20.1 @@ -150,24 +102,12 @@ importers: '@stylistic/eslint-plugin': specifier: 5.5.0 version: 5.5.0(eslint@9.39.1(jiti@2.6.1)) - '@types/cytoscape': - specifier: 3.21.9 - version: 3.21.9 - '@types/cytoscape-fcose': - specifier: 2.2.4 - version: 2.2.4 - '@types/d3-scale-chromatic': - specifier: 3.1.0 - version: 3.1.0 '@types/geojson': specifier: 7946.0.16 version: 7946.0.16 '@types/jsdom': specifier: 21.1.7 version: 21.1.7 - '@types/mapbox__mapbox-gl-draw': - specifier: 1.4.8 - version: 1.4.8 '@types/node': specifier: latest version: 24.10.0 @@ -202,8 +142,8 @@ importers: specifier: 3.30.0 version: 3.30.0 nuxt: - specifier: 4.2.0 - version: 4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1) + specifier: ^4.2.0 + version: 4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1) playwright-core: specifier: 1.54.2 version: 1.54.2 @@ -226,14 +166,14 @@ importers: specifier: 3.2.4 version: 3.2.4(@types/node@24.10.0)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) vue: - specifier: 3.5.22 + specifier: ^3.5.0 version: 3.5.22(typescript@5.9.3) vue-eslint-parser: specifier: 10.2.0 version: 10.2.0(eslint@9.39.1(jiti@2.6.1)) vue-tsc: - specifier: 3.1.3 - version: 3.1.3(typescript@5.9.3) + specifier: 3.2.6 + version: 3.2.6(typescript@5.9.3) packages: @@ -267,8 +207,14 @@ packages: '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - '@auth0/auth0-spa-js@2.1.3': - resolution: {integrity: sha512-NMTBNuuG4g3rame1aCnNS5qFYIzsTUV5qTFPRfTyYFS1feS6jsCBR+eTq9YkxCp1yuoM2UIcjunPaoPl77U9xQ==} + '@auth0/auth0-auth-js@1.6.0': + resolution: {integrity: sha512-/WYYNlsqhWA6I60pMVLFVeOgjOUCLdJThEAsjN8pAgYY09BTxbPaRIEVDgGu6ckoJpkmKvEYlHPO/vwRNrvX6w==} + + '@auth0/auth0-nuxt@1.0.1': + resolution: {integrity: sha512-idWDFouULyDD8y84vn1GUitPiDbBghtWTYLytp6dCD/qK4K3DzSXtW8K4i4Nf7Wsm02+jdEdGOSMR7Gj9kC4GQ==} + + '@auth0/auth0-server-js@1.3.0': + resolution: {integrity: sha512-UgvRR+x2xBq9QLYktw01UQDdoiuDOQFNVdulJl+SH0nJP3J5qxbRFFognGlWqn+yBj50eWtaMJhYJ5oES6vE4Q==} '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} @@ -722,74 +668,11 @@ packages: '@kwsites/promise-deferred@1.1.1': resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} - '@mapbox/extent@0.4.0': - resolution: {integrity: sha512-MSoKw3qPceGuupn04sdaJrFeLKvcSETVLZCGS8JA9x6zXQL3FWiKaIXYIZEDXd5jpXpWlRxinCZIN49yRy0C9A==} - - '@mapbox/geojson-area@0.2.2': - resolution: {integrity: sha512-bBqqFn1kIbLBfn7Yq1PzzwVkPYQr9lVUeT8Dhd0NL5n76PBuXzOcuLV7GOSbEB1ia8qWxH4COCvFpziEu/yReA==} - - '@mapbox/geojson-coords@0.0.2': - resolution: {integrity: sha512-YuVzpseee/P1T5BWyeVVPppyfmuXYHFwZHmybkqaMfu4BWlOf2cmMGKj2Rr92MwfSTOCSUA0PAsVGRG8akY0rg==} - - '@mapbox/geojson-extent@1.0.1': - resolution: {integrity: sha512-hh8LEO3djT4fqfr8sSC6wKt+p0TMiu+KOLMBUiFOyj+zGq7+IXwQGl0ppCVDkyzCewyd9LoGe9zAvDxXrLfhLw==} - hasBin: true - - '@mapbox/geojson-normalize@0.0.1': - resolution: {integrity: sha512-82V7YHcle8lhgIGqEWwtXYN5cy0QM/OHq3ypGhQTbvHR57DF0vMHMjjVSQKFfVXBe/yWCBZTyOuzvK7DFFnx5Q==} - hasBin: true - - '@mapbox/geojson-rewind@0.5.2': - resolution: {integrity: sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==} - hasBin: true - - '@mapbox/jsonlint-lines-primitives@2.0.2': - resolution: {integrity: sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==} - engines: {node: '>= 0.6'} - - '@mapbox/mapbox-gl-draw@1.4.3': - resolution: {integrity: sha512-03qIJgyGmm0IoTZbV/cfODru9jRGogi4LcQ3maxIJDKccq1gY3ofgt2UYPkeU143ElxitZahEythNQv1NpsLhg==} - - '@mapbox/mapbox-gl-supported@3.0.0': - resolution: {integrity: sha512-2XghOwu16ZwPJLOFVuIOaLbN0iKMn867evzXFyf0P22dqugezfJwLmdanAgU25ITvz1TvOfVP4jsDImlDJzcWg==} - '@mapbox/node-pre-gyp@2.0.0': resolution: {integrity: sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg==} engines: {node: '>=18'} hasBin: true - '@mapbox/point-geometry@0.1.0': - resolution: {integrity: sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==} - - '@mapbox/point-geometry@1.1.0': - resolution: {integrity: sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ==} - - '@mapbox/tiny-sdf@2.0.7': - resolution: {integrity: sha512-25gQLQMcpivjOSA40g3gO6qgiFPDpWRoMfd+G/GoppPIeP6JDaMMkMrEJnMZhKyyS6iKwVt5YKu02vCUyJM3Ug==} - - '@mapbox/unitbezier@0.0.1': - resolution: {integrity: sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==} - - '@mapbox/vector-tile@1.3.1': - resolution: {integrity: sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==} - - '@mapbox/vector-tile@2.0.4': - resolution: {integrity: sha512-AkOLcbgGTdXScosBWwmmD7cDlvOjkg/DetGva26pIRiZPdeJYjYKarIlb4uxVzi6bwHO6EWH82eZ5Nuv4T5DUg==} - - '@mapbox/whoots-js@3.1.0': - resolution: {integrity: sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==} - engines: {node: '>=6.0.0'} - - '@maplibre/maplibre-gl-geocoder@1.9.0': - resolution: {integrity: sha512-3jGxHQu5u/N76YNsqp9FaosGXSmFw6nwZS2wuAIVLtfoixfF6OHy6ZjWTcSkxFVtBsKG8Sd/GS7Rnnjcol+C8w==} - engines: {node: '>=18'} - peerDependencies: - maplibre-gl: '>=4.0.0' - - '@maplibre/maplibre-gl-style-spec@23.3.0': - resolution: {integrity: sha512-IGJtuBbaGzOUgODdBRg66p8stnwj9iDXkgbYKoYcNiiQmaez5WVRfXm4b03MCDwmZyX93csbfHFWEJJYHnn5oA==} - hasBin: true - '@mdi/font@7.4.47': resolution: {integrity: sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==} @@ -982,10 +865,6 @@ packages: rolldown: optional: true - '@observablehq/plot@0.6.17': - resolution: {integrity: sha512-/qaXP/7mc4MUS0s4cPPFASDRjtsWp85/TbfsciqDgU1HwYixbSbbytNuInD8AcTYC3xaxACgVX06agdfQy9W+g==} - engines: {node: '>=12'} - '@one-ini/wasm@0.1.1': resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} @@ -1600,15 +1479,6 @@ packages: peerDependencies: eslint: '>=9.0.0' - '@turf/centroid@7.3.0': - resolution: {integrity: sha512-6skXlwv6fCkdKsrkniizpEuC1IsAYQEyZG4XIzK5d3FGQTM/lVInLQP+wd9I6FLtW8b/6UbZcIjSU9wP/MMbTA==} - - '@turf/helpers@7.3.0': - resolution: {integrity: sha512-5kWdgwI6e2vGbkt2qOD+Z2BiKQ7dfKN/PtWRLCpvzyOO59rk19R53CHi8nUT/Y1vQLgWmT6eNpiKwsWwPZGIdg==} - - '@turf/meta@7.3.0': - resolution: {integrity: sha512-fTLqdQqRm8qA2zHHUbBMY++YT9LDQejLG7OD70XF2dwg9nPiF9mUxO7nrsDp2IY8vNmH9OTAiMtlIjb0ssYccg==} - '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} @@ -1639,15 +1509,6 @@ packages: '@types/css-font-loading-module@0.0.7': resolution: {integrity: sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==} - '@types/cytoscape-fcose@2.2.4': - resolution: {integrity: sha512-QwWtnT8HI9h+DHhG5krGc1ZY0Ex+cn85MvX96ZNAjSxuXiZDnjIZW/ypVkvvubTjIY4rSdkJY1D/Nsn8NDpmAw==} - - '@types/cytoscape@3.21.9': - resolution: {integrity: sha512-JyrG4tllI6jvuISPjHK9j2Xv/LTbnLekLke5otGStjFluIyA9JjgnvgZrSBsp8cEDpiTjwgZUZwpPv8TSBcoLw==} - - '@types/d3-scale-chromatic@3.1.0': - resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} - '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -1666,9 +1527,6 @@ packages: '@types/file-loader@5.0.4': resolution: {integrity: sha512-aB4X92oi5D2nIGI8/kolnJ47btRM2MQjQS4eJgA/VnCD12x0+kP5v7b5beVQWKHLOcquwUXvv6aMt8PmMy9uug==} - '@types/geojson-vt@3.2.5': - resolution: {integrity: sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==} - '@types/geojson@7946.0.16': resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} @@ -1687,15 +1545,6 @@ packages: '@types/less@3.0.6': resolution: {integrity: sha512-PecSzorDGdabF57OBeQO/xFbAkYWo88g4Xvnsx7LRwqLC17I7OoKtA3bQB9uXkY6UkMWCOsA8HSVpaoitscdXw==} - '@types/mapbox__mapbox-gl-draw@1.4.8': - resolution: {integrity: sha512-700zPikQXfFMB2vtkJdXSROiqS5F19guf6QdYqvlgCdaMxGmdlLITRq6/zFpzfVQDrgpWex5M8vLtbwjZfup8g==} - - '@types/mapbox__point-geometry@0.1.4': - resolution: {integrity: sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==} - - '@types/mapbox__vector-tile@1.3.4': - resolution: {integrity: sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==} - '@types/node@16.18.126': resolution: {integrity: sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==} @@ -1712,9 +1561,6 @@ packages: resolution: {integrity: sha512-EULJ8LApcVEPbrfND0cRQqutIOdiIgJ1Mgrhpy755r14xMohPTEpkV/k28SJvuOs9bHRFW8x+KeDAEPiGQPB9Q==} deprecated: This is a stub types definition. parse-path provides its own type definitions, so you do not need this installed. - '@types/pbf@3.0.5': - resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==} - '@types/pg@8.15.4': resolution: {integrity: sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg==} @@ -1742,9 +1588,6 @@ packages: '@types/source-list-map@0.1.6': resolution: {integrity: sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==} - '@types/supercluster@7.1.3': - resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} - '@types/tapable@1.0.12': resolution: {integrity: sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==} @@ -2041,14 +1884,14 @@ packages: '@vitest/utils@3.2.4': resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - '@volar/language-core@2.4.23': - resolution: {integrity: sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==} + '@volar/language-core@2.4.28': + resolution: {integrity: sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==} - '@volar/source-map@2.4.23': - resolution: {integrity: sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q==} + '@volar/source-map@2.4.28': + resolution: {integrity: sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==} - '@volar/typescript@2.4.23': - resolution: {integrity: sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag==} + '@volar/typescript@2.4.28': + resolution: {integrity: sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==} '@vue-macros/common@3.1.1': resolution: {integrity: sha512-afW2DMjgCBVs33mWRlz7YsGHzoEEupnl0DK5ZTKsgziAlLh5syc5m+GM7eqeYrgiQpwMaVxa1fk73caCvPxyAw==} @@ -2130,13 +1973,8 @@ packages: '@vue/devtools-shared@7.7.7': resolution: {integrity: sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==} - '@vue/language-core@3.1.3': - resolution: {integrity: sha512-KpR1F/eGAG9D1RZ0/T6zWJs6dh/pRLfY5WupecyYKJ1fjVmDMgTPw9wXmKv2rBjo4zCJiOSiyB8BDP1OUwpMEA==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true + '@vue/language-core@3.2.6': + resolution: {integrity: sha512-xYYYX3/aVup576tP/23sEUpgiEnujrENaoNRbaozC1/MA9I6EGFQRJb4xrt/MmUCAGlxTKL2RmT8JLTPqagCkg==} '@vue/reactivity@3.5.22': resolution: {integrity: sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==} @@ -2161,16 +1999,16 @@ packages: '@vue/test-utils@2.4.6': resolution: {integrity: sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==} - '@vueuse/core@14.0.0': - resolution: {integrity: sha512-d6tKRWkZE8IQElX2aHBxXOMD478fHIYV+Dzm2y9Ag122ICBpNKtGICiXKOhWU3L1kKdttDD9dCMS4bGP3jhCTQ==} + '@vueuse/core@14.2.1': + resolution: {integrity: sha512-3vwDzV+GDUNpdegRY6kzpLm4Igptq+GA0QkJ3W61Iv27YWwW/ufSlOfgQIpN6FZRMG0mkaz4gglJRtq5SeJyIQ==} peerDependencies: vue: ^3.5.0 - '@vueuse/metadata@14.0.0': - resolution: {integrity: sha512-6yoGqbJcMldVCevkFiHDBTB1V5Hq+G/haPlGIuaFZHpXC0HADB0EN1ryQAAceiW+ryS3niUwvdFbGiqHqBrfVA==} + '@vueuse/metadata@14.2.1': + resolution: {integrity: sha512-1ButlVtj5Sb/HDtIy1HFr1VqCP4G6Ypqt5MAo0lCgjokrk2mvQKsK2uuy0vqu/Ks+sHfuHo0B9Y9jn9xKdjZsw==} - '@vueuse/shared@14.0.0': - resolution: {integrity: sha512-mTCA0uczBgurRlwVaQHfG0Ja7UdGe4g9mwffiJmvLiTtp1G4AQyIjej6si/k8c8pUwTfVpNufck+23gXptPAkw==} + '@vueuse/shared@14.2.1': + resolution: {integrity: sha512-shTJncjV9JTI4oVNyF1FQonetYAiTBd+Qj7cY89SWbXSkx7gyhrgtEdF2ZAVWS1S3SHlaROO6F2IesJxQEkZBw==} peerDependencies: vue: ^3.5.0 @@ -2280,17 +2118,9 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - array-buffer-byte-length@1.0.2: - resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} - engines: {node: '>= 0.4'} - array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - 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'} @@ -2303,10 +2133,6 @@ packages: resolution: {integrity: sha512-cbdCP0PGOBq0ASG+sjnKIoYkWMKhhz+F/h9pRexUdX2Hd38+WOlBkRKlqkGOSm0YQpcFMQBJeK4WspUAkwsEdg==} engines: {node: '>=20.19.0'} - async-function@1.0.0: - resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} - engines: {node: '>= 0.4'} - async-sema@3.1.1: resolution: {integrity: sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==} @@ -2320,10 +2146,6 @@ packages: peerDependencies: postcss: ^8.1.0 - available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - b4a@1.7.3: resolution: {integrity: sha512-5Q2mfq2WfGuFp3uS//0s6baOJLMoVduPYVeNmDYxu5OUA1/cBfvr2RIS7vi62LdNj/urk1hfmj867I3qt6uZ7Q==} peerDependencies: @@ -2358,9 +2180,6 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} - binary-search-bounds@2.0.5: - resolution: {integrity: sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==} - bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} @@ -2442,10 +2261,6 @@ packages: 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'} @@ -2471,9 +2286,6 @@ packages: change-case@5.4.4: resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} - cheap-ruler@4.0.0: - resolution: {integrity: sha512-0BJa8f4t141BYKQyn9NSQt1PguFQXMXwZiA5shfoaBYHAb2fFk2RAX+tiWMoQU+Agtzt3mdt0JtuyshAXqZ+Vw==} - check-error@2.1.1: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} @@ -2505,10 +2317,6 @@ packages: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} - cliui@9.0.1: - resolution: {integrity: sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==} - engines: {node: '>=20'} - cluster-key-slot@1.1.2: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} @@ -2531,17 +2339,9 @@ packages: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} - commander@14.0.0: - resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} - engines: {node: '>=20'} - commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -2613,9 +2413,6 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} - cose-base@2.2.0: - resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} - crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -2657,9 +2454,6 @@ packages: resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} engines: {node: '>= 6'} - csscolorparser@1.0.3: - resolution: {integrity: sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==} - cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2697,169 +2491,13 @@ packages: csv-stringify@6.6.0: resolution: {integrity: sha512-YW32lKOmIBgbxtu3g5SaiqWNwa/9ISQt2EcgOq0+RAIFufFp9is6tqNnKahqE5kuKvrnYAzs28r+s6pXJR8Vcw==} - cytoscape-fcose@2.2.0: - resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} - peerDependencies: - cytoscape: ^3.2.0 - - cytoscape@3.31.1: - resolution: {integrity: sha512-Hx5Mtb1+hnmAKaZZ/7zL1Y5HTFYOjdDswZy/jD+1WINRU8KVi1B7+vlHdsTwY+VCFucTreoyu1RDzQJ9u0d2Hw==} - engines: {node: '>=0.10'} - - d3-array@3.2.4: - resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} - engines: {node: '>=12'} - - d3-axis@3.0.0: - resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} - engines: {node: '>=12'} - - d3-brush@3.0.0: - resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} - engines: {node: '>=12'} - - d3-chord@3.0.1: - resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} - engines: {node: '>=12'} - - d3-color@3.1.0: - resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} - engines: {node: '>=12'} - - d3-contour@4.0.2: - resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} - engines: {node: '>=12'} - - d3-delaunay@6.0.4: - resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} - engines: {node: '>=12'} - - d3-dispatch@3.0.1: - resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} - engines: {node: '>=12'} - - d3-drag@3.0.0: - resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} - engines: {node: '>=12'} - - d3-dsv@3.0.1: - resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} - engines: {node: '>=12'} - hasBin: true - - d3-ease@3.0.1: - resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} - engines: {node: '>=12'} - - d3-fetch@3.0.1: - resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} - engines: {node: '>=12'} - - d3-force@3.0.0: - resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} - engines: {node: '>=12'} - - d3-format@3.1.0: - resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} - engines: {node: '>=12'} - - d3-geo-projection@4.0.0: - resolution: {integrity: sha512-p0bK60CEzph1iqmnxut7d/1kyTmm3UWtPlwdkM31AU+LW+BXazd5zJdoCn7VFxNCHXRngPHRnsNn5uGjLRGndg==} - engines: {node: '>=12'} - hasBin: true - - d3-geo@3.1.1: - resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} - engines: {node: '>=12'} - - d3-hierarchy@3.1.2: - resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} - engines: {node: '>=12'} - - d3-interpolate@3.0.1: - resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} - engines: {node: '>=12'} - - d3-path@3.1.0: - resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} - engines: {node: '>=12'} - - d3-polygon@3.0.1: - resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} - engines: {node: '>=12'} - - d3-quadtree@3.0.1: - resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} - engines: {node: '>=12'} - - d3-random@3.0.1: - resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} - engines: {node: '>=12'} - - d3-scale-chromatic@3.1.0: - resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} - engines: {node: '>=12'} - - d3-scale@4.0.2: - resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} - engines: {node: '>=12'} - - d3-selection@3.0.0: - resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} - engines: {node: '>=12'} - - d3-shape@3.2.0: - resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} - engines: {node: '>=12'} - - d3-time-format@4.1.0: - resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} - engines: {node: '>=12'} - - d3-time@3.1.0: - resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} - engines: {node: '>=12'} - - d3-timer@3.0.1: - resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} - engines: {node: '>=12'} - - d3-transition@3.0.1: - resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} - engines: {node: '>=12'} - peerDependencies: - d3-selection: 2 - 3 - - d3-zoom@3.0.0: - resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} - engines: {node: '>=12'} - - d3@7.9.0: - resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} - engines: {node: '>=12'} - 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'} - date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} - dayjs@1.11.19: - resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} - db0@0.3.4: resolution: {integrity: sha512-RiXXi4WaNzPTHEOu8UPQKMooIbqOEyqA1t7Z6MsdxSCeb8iUC9ko3LcmsLmeUt2SM5bctfArZKkRQggKZz7JNw==} peerDependencies: @@ -2922,10 +2560,6 @@ packages: resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} engines: {node: '>=18'} - define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - define-lazy-prop@2.0.0: resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} engines: {node: '>=8'} @@ -2934,16 +2568,9 @@ packages: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} - define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - delaunator@5.0.1: - resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==} - denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -3010,9 +2637,6 @@ packages: duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} - earcut@3.0.2: - resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -3027,9 +2651,6 @@ packages: electron-to-chromium@1.5.250: resolution: {integrity: sha512-/5UMj9IiGDMOFBnN4i7/Ry5onJrAGSbOGo3s9FEKmwobGq6xw832ccET0CE3CkkMBZ8GJSlUIesZofpyurqDXw==} - emoji-regex@10.6.0: - resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -3058,10 +2679,6 @@ packages: errx@0.1.0: resolution: {integrity: sha512-fZmsRiDNv07K6s2KkKFTiD2aIvECa7++PKyD5NC32tpRw46qZA3sOz+aM+/V9V0GDHxVTKLziveV4JhzBHDp9Q==} - es-abstract@1.24.0: - resolution: {integrity: sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==} - engines: {node: '>= 0.4'} - es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -3077,14 +2694,6 @@ packages: 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-to-primitive@1.3.0: - resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} - engines: {node: '>= 0.4'} - esbuild@0.25.12: resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} engines: {node: '>=18'} @@ -3293,9 +2902,6 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} - fast-json-patch@3.1.1: - resolution: {integrity: sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -3361,10 +2967,6 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - for-each@0.3.5: - resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} - engines: {node: '>= 0.4'} - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} @@ -3396,43 +2998,18 @@ packages: 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==} - fuse.js@7.1.0: resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==} engines: {node: '>=10'} - fuzzy@0.1.3: - resolution: {integrity: sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==} - engines: {node: '>= 0.6.0'} - - 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'} - geojson-flatten@1.1.1: - resolution: {integrity: sha512-k/6BCd0qAt7vdqdM1LkLfAy72EsLDy0laNwX0x2h49vfYCiQkRc4PSra8DNEdJ10EKRpwEvDXMb0dBknTJuWpQ==} - - geojson-vt@4.0.2: - resolution: {integrity: sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==} - get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.4.0: - resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==} - engines: {node: '>=18'} - get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -3444,18 +3021,10 @@ packages: resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} engines: {node: '>= 0.4'} - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} - 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==} @@ -3469,9 +3038,6 @@ packages: git-url-parse@16.1.0: resolution: {integrity: sha512-cPLz4HuK86wClEW7iDdeAKcCVlWXmrLpb2L+G9goW0Z1dtpNS6BXXSOckUTlJT/LDQViE1QZKstNORzHsLnobw==} - gl-matrix@3.4.4: - resolution: {integrity: sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -3488,10 +3054,6 @@ packages: resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} engines: {node: '>=18'} - global-prefix@4.0.0: - resolution: {integrity: sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==} - engines: {node: '>=16'} - globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -3500,10 +3062,6 @@ packages: resolution: {integrity: sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==} engines: {node: '>=18'} - globalthis@1.0.4: - resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} - engines: {node: '>= 0.4'} - globby@15.0.0: resolution: {integrity: sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==} engines: {node: '>=20'} @@ -3528,53 +3086,29 @@ packages: resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - grid-index@1.1.0: - resolution: {integrity: sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==} - gzip-size@7.0.0: resolution: {integrity: sha512-O1Ld7Dr+nqPnmGpdhzLmMTQ4vAsD+rHwMm1NLUmoUFFymBOMKxCCrtDxqdBRYXdeEPEi3SyoR4TizJLQrnKBNA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - h3@1.15.1: - resolution: {integrity: sha512-+ORaOBttdUm1E2Uu/obAyCguiI7MbBvsLTndc3gyK3zU+SYLoZXlyCP9Xgy0gikkGufFLTZXCXD6+4BsufnmHA==} - - h3@1.15.4: - resolution: {integrity: sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==} + h3@1.15.10: + resolution: {integrity: sha512-YzJeWSkDZxAhvmp8dexjRK5hxziRO7I9m0N53WhvYL5NiWfkUkzssVzY9jvGu0HBoLFW6+duYmNSn6MaZBCCtg==} happy-dom@18.0.1: resolution: {integrity: sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA==} engines: {node: '>=20.0.0'} - 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'} - hat@0.0.3: - resolution: {integrity: sha512-zpImx2GoKXy42fVDSEad2BPKuSQdLcqsCYa48K3zHSzM/ugWuYjLDr8IXxpVuL7uCLHw56eaiLxCRthhOzf5ug==} - hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -3665,21 +3199,6 @@ packages: resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - ini@4.1.3: - resolution: {integrity: sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - - internal-slot@1.1.0: - resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} - engines: {node: '>= 0.4'} - - internmap@2.0.3: - resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} - engines: {node: '>=12'} - - interval-tree-1d@1.0.4: - resolution: {integrity: sha512-wY8QJH+6wNI0uh4pDQzMvl+478Qh7Rl4qLmqiluxALlNvl+I+o5x38Pw3/z7mDPTPS1dQalZJXsmbvxx5gclhQ==} - ioredis@5.8.2: resolution: {integrity: sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q==} engines: {node: '>=12.22.0'} @@ -3695,42 +3214,14 @@ packages: resolution: {integrity: sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==} engines: {node: '>=8'} - 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-boolean-object@1.2.2: - resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} - engines: {node: '>= 0.4'} - is-builtin-module@5.0.0: resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} engines: {node: '>=18.20'} - 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-docker@2.2.1: resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} engines: {node: '>=8'} @@ -3745,18 +3236,10 @@ packages: 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@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - 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'} @@ -3770,21 +3253,9 @@ packages: resolution: {integrity: sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==} engines: {node: '>=18'} - is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - is-module@1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} - 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'} @@ -3803,18 +3274,6 @@ packages: is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} - 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-ssh@1.4.1: resolution: {integrity: sha512-JNeu1wQsHjyHgn9NcWTaXq6zWSR6hqE0++zhfZlkFBbScNkyvxCdeV8sRkSBaeLKxmbpR21brail63ACNxJ0Tg==} @@ -3826,30 +3285,6 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - 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'} - is-what@5.5.0: resolution: {integrity: sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==} engines: {node: '>=18'} @@ -3869,9 +3304,6 @@ packages: isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -3879,9 +3311,6 @@ packages: resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} engines: {node: '>=16'} - isoformat@0.2.1: - resolution: {integrity: sha512-tFLRAygk9NqrRPhJSnNGh7g7oaVWDwR0wKh/GM2LgmPa50Eg4UfyaCO4I8k6EqJHl1/uh2RAD6g06n5ygEnrjQ==} - jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -3893,6 +3322,9 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + jose@6.2.2: + resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} + js-beautify@1.15.4: resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} engines: {node: '>=14'} @@ -3946,9 +3378,6 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - json-stringify-pretty-compact@4.0.0: - resolution: {integrity: sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==} - json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} @@ -3957,16 +3386,9 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} - kdbush@4.0.2: - resolution: {integrity: sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -3985,9 +3407,6 @@ packages: launch-editor@2.12.0: resolution: {integrity: sha512-giOHXoOtifjdHqUamwKq6c49GzBdLjvxrd2D+Q4V6uOHopJv7p9VJxikDsQ/CBXZbEITgUqSVHXLTG3VhPP1Dg==} - layout-base@2.0.1: - resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} - lazystream@1.0.1: resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} engines: {node: '>= 0.6.3'} @@ -4027,19 +3446,12 @@ packages: lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} - lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - lodash.defaults@4.2.0: resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - deprecated: This package is deprecated. Use require('node:util').isDeepStrictEqual instead. - lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -4085,16 +3497,6 @@ packages: magicast@0.5.1: resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==} - mapbox-gl@3.16.0: - resolution: {integrity: sha512-rluV1Zp/0oHf1Y9BV+nePRNnKyTdljko3E19CzO5rBqtQaNUYS0ePCMPRtxOuWRwSdKp3f9NWJkOCjemM8nmjw==} - - maplibre-gl@5.2.0: - resolution: {integrity: sha512-9zZKD0M80qtDsqBet+EDuAhoCeA/cnAuZAA0p3hcGKGbyjM/SH+R6wQvnBEgvJz9UhDynnkoKdUwhI+fUkHoXQ==} - engines: {node: '>=16.14.0', npm: '>=8.1.0'} - - martinez-polygon-clipping@0.7.4: - resolution: {integrity: sha512-jBEwrKtA0jTagUZj2bnmb4Yg2s4KnJGRePStgI7bAVjtcipKiF39R4LZ2V/UT61jMYWrTcBhPazexeqd6JAVtw==} - math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} @@ -4181,9 +3583,6 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} @@ -4242,9 +3641,6 @@ packages: muggle-string@0.4.1: resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} - murmurhash-js@1.0.0: - resolution: {integrity: sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==} - nanoid@3.3.11: resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -4310,6 +3706,9 @@ packages: node-mock-http@1.0.3: resolution: {integrity: sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==} + node-mock-http@1.0.4: + resolution: {integrity: sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ==} + node-releases@2.0.27: resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} @@ -4371,6 +3770,9 @@ packages: engines: {node: ^14.16.0 || >=16.10.0} hasBin: true + oauth4webapi@3.8.5: + resolution: {integrity: sha512-A8jmyUckVhRJj5lspguklcl90Ydqk61H3dcU0oLhH3Yv13KpAliKTt5hknpGGPZSSfOwGyraNEFmofDYH+1kSg==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -4382,14 +3784,6 @@ packages: 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'} - ofetch@1.5.1: resolution: {integrity: sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==} @@ -4424,6 +3818,9 @@ packages: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} + openid-client@6.8.2: + resolution: {integrity: sha512-uOvTCndr4udZsKihJ68H9bUICrriHdUVJ6Az+4Ns6cW55rwM5h0bjVIzDz2SxgOI84LKjFyjOFvERLzdTUROGA==} + optimism@0.18.1: resolution: {integrity: sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==} @@ -4431,10 +3828,6 @@ packages: 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'} - oxc-minify@0.95.0: resolution: {integrity: sha512-3k//447vscNk5JZXVnr2qv0QONjUU7F8Y6ewAPFVQNgdvYh3gCLYCRjQ/DR5kVkqxFgVa8R/FFBV3X5jlztSzw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -4541,14 +3934,6 @@ packages: resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} engines: {node: '>= 14.16'} - pbf@3.3.0: - resolution: {integrity: sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==} - hasBin: true - - pbf@4.0.1: - resolution: {integrity: sha512-SuLdBvS42z33m8ejRbInMapQe8n0D3vN/Xd5fmWM3tufNgRQFBpaW2YVJxQZV4iPNqb0vEFvssMEo5w9c6BTIA==} - hasBin: true - perfect-debounce@1.0.0: resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} @@ -4592,10 +3977,6 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} - possible-typed-array-names@1.1.0: - resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} - engines: {node: '>= 0.4'} - postcss-calc@10.1.1: resolution: {integrity: sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw==} engines: {node: ^18.12 || ^20.9 || >=22.0} @@ -4795,9 +4176,6 @@ packages: resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} engines: {node: '>=0.10.0'} - potpack@2.1.0: - resolution: {integrity: sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -4823,9 +4201,6 @@ packages: proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - protocol-buffers-schema@3.6.0: - resolution: {integrity: sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==} - protocols@2.0.2: resolution: {integrity: sha512-hHVTzba3wboROl0/aWRRG9dMytgH6ow//STBZh43l/wQgmMhYhOFi0EHWAPtoCz9IAUymsyP0TSBHkhgMEGNnQ==} @@ -4858,9 +4233,6 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - quickselect@3.0.0: - resolution: {integrity: sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==} - radix3@1.1.2: resolution: {integrity: sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==} @@ -4907,10 +4279,6 @@ packages: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - reflect.getprototypeof@1.0.10: - resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} - engines: {node: '>= 0.4'} - regexp-ast-analysis@0.7.1: resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -4919,10 +4287,6 @@ packages: resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true - regexp.prototype.flags@1.5.4: - resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} - engines: {node: '>= 0.4'} - regjsparser@0.13.0: resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} hasBin: true @@ -4960,9 +4324,6 @@ packages: resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - resolve-protobuf-schema@2.1.0: - resolution: {integrity: sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==} - resolve@1.22.11: resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} engines: {node: '>= 0.4'} @@ -4975,12 +4336,6 @@ packages: rfdc@1.4.1: resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - robust-predicates@2.0.4: - resolution: {integrity: sha512-l4NwboJM74Ilm4VKfbAtFeGq7aEjWL+5kVFcmgFA2MrdnQWx9iE/tUGvxY5HyMI7o/WpSIUFLbC5fbeaHgSCYg==} - - robust-predicates@3.0.2: - resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} - rollup-plugin-dts@6.2.3: resolution: {integrity: sha512-UgnEsfciXSPpASuOelix7m4DrmyQgiaWBnvI0TM4GxuDh5FkqW8E5hu57bCxXB90VvR1WNfLV80yEDN18UogSA==} engines: {node: '>=16'} @@ -5028,30 +4383,12 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - rw@0.1.4: - resolution: {integrity: sha512-vSj3D96kMcjNyqPcp65wBRIDImGSrUuMxngNNxvw8MQaO+aQ6llzRPH7XcJy5zrpb3wU++045+Uz/IDIM684iw==} - - rw@1.3.3: - resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - - safe-array-concat@1.1.3: - resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} - engines: {node: '>=0.4'} - safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - 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==} @@ -5094,10 +4431,6 @@ packages: serialize-javascript@6.0.2: resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - serialize-to-js@3.1.2: - resolution: {integrity: sha512-owllqNuDDEimQat7EPG0tH7JjO090xKNzUtYz6X+Sk2BXDnOCilDdNLwjWeFywG9xkJul1ULvtUQa9O4pUaY0w==} - engines: {node: '>=4.0.0'} - seroval@1.3.2: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} @@ -5116,18 +4449,6 @@ packages: set-cookie-parser@2.7.2: resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} - 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'} - setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -5215,9 +4536,6 @@ packages: resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} engines: {node: '>=0.10.0'} - splaytree@0.1.4: - resolution: {integrity: sha512-D50hKrjZgBzqD3FT2Ek53f2dcDLAQT8SSGrzj3vidNH5ISRgceeGVJ2dQIthKOuayqFXfFjXheHNo4bbt9LhRQ==} - srvx@0.9.5: resolution: {integrity: sha512-nQsA2c8q3XwbSn6kTxVQjz0zS096rV+Be2pzJwrYEAdtnYszLw4MTy8JWJjz1XEGBZwP0qW51SUIX3WdjdRemQ==} engines: {node: '>=20.16.0'} @@ -5244,10 +4562,6 @@ packages: 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'} - streamx@2.23.0: resolution: {integrity: sha512-kn+e44esVfn2Fa/O0CPFcex27fjIL6MkVae0Mm6q+E6f0hWv578YCERbv+4m02cjxvDsPKLnmxral/rR6lBMAg==} @@ -5259,22 +4573,6 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} - engines: {node: '>=18'} - - 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'} - string_decoder@1.1.1: resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} @@ -5313,15 +4611,6 @@ packages: peerDependencies: postcss: ^8.4.32 - subtag@0.5.0: - resolution: {integrity: sha512-CaIBcTSb/nyk4xiiSOtZYz1B+F12ZxW8NEp54CdT+84vmh/h4sUnHGC6+KQXUfED8u22PQjCYWfZny8d2ELXwg==} - - suggestions-list@0.0.2: - resolution: {integrity: sha512-Yw0fdq14c6RQWQIfE1/8WEi9Dp8rjyCD6FhYA/Tit2/ADbE9Y4ADG4ezlvivsa8Civ5nz++pyVVBMjOMlgIUJw==} - - supercluster@8.0.1: - resolution: {integrity: sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==} - superjson@2.2.5: resolution: {integrity: sha512-zWPTX96LVsA/eVYnqOM2+ofcdPqdS1dAF1LN4TS2/MWuUpfitd9ctTa87wt4xrYnZnkLtS69xpBdSxVBP5Rm6w==} engines: {node: '>=16'} @@ -5364,6 +4653,7 @@ packages: tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me terser@4.8.1: resolution: {integrity: sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==} @@ -5382,9 +4672,6 @@ packages: resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} engines: {node: '>=12.22'} - tiny-emitter@2.1.0: - resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -5406,12 +4693,6 @@ packages: resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} - tinyqueue@1.2.3: - resolution: {integrity: sha512-Qz9RgWuO9l8lT+Y9xvbzhPT2efIUIFd69N7eF7tJ9lnQl0iLj1M7peK7IoUGZL9DJHw9XftqLreccfxcQgYLxA==} - - tinyqueue@3.0.0: - resolution: {integrity: sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==} - tinyrainbow@2.0.0: resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} engines: {node: '>=14.0.0'} @@ -5442,10 +4723,6 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - topojson-client@3.1.0: - resolution: {integrity: sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==} - hasBin: true - totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} @@ -5461,10 +4738,6 @@ packages: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} - traverse@0.6.11: - resolution: {integrity: sha512-vxXDZg8/+p3gblxB6BhhG5yWVn1kGRlaL8O78UDXc3wRnPizB5g83dcvWV1jpDMIPnjZjOFuxlMmE82XJ4407w==} - engines: {node: '>= 0.4'} - ts-api-utils@2.1.0: resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} @@ -5516,26 +4789,6 @@ packages: type-level-regexp@0.1.17: resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} - 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'} - - typedarray.prototype.slice@1.0.5: - resolution: {integrity: sha512-q7QNVDGTdl702bVFiI5eY4l/HkgCM6at9KhcFbgUAzezHFbOVy4+0O/lCjsABEQwbZPravVfBIiBVGo89yzHFg==} - engines: {node: '>= 0.4'} - typescript-eslint@8.46.3: resolution: {integrity: sha512-bAfgMavTuGo+8n6/QQDVQz4tZ4f7Soqg53RbrlZQEoAltYop/XR4RAts/I0BrO3TTClTSTFJ0wYbla+P8cEWJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -5551,13 +4804,12 @@ packages: ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} + ufo@1.6.3: + resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} + ultrahtml@1.6.0: resolution: {integrity: sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==} - unbox-primitive@1.1.0: - resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} - engines: {node: '>= 0.4'} - unbuild@3.6.1: resolution: {integrity: sha512-+U5CdtrdjfWkZhuO4N9l5UhyiccoeMEXIc2Lbs30Haxb+tRwB3VwB8AoZRxlAzORXunenSo+j6lh45jx+xkKgg==} hasBin: true @@ -5618,6 +4870,7 @@ packages: unplugin-vue-router@0.16.1: resolution: {integrity: sha512-7A7gUVzLIYMBrBPKk8l4lZoZXDOrO8+etw6/RTrqG3OzpLUUZEXJFUW7+OyMIpQK93sEbdkR2z9ZNNl/r32FMw==} + deprecated: 'Merged into vuejs/router. Migrate: https://router.vuejs.org/guide/migration/v4-to-v5.html' peerDependencies: '@vue/compiler-sfc': ^3.5.17 vue-router: ^4.6.0 @@ -5632,65 +4885,6 @@ packages: unrs-resolver@1.11.1: resolution: {integrity: sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==} - unstorage@1.15.0: - resolution: {integrity: sha512-m40eHdGY/gA6xAPqo8eaxqXgBuzQTlAKfmB1iF7oCKXE1HfwHwzDJBywK+qQGn52dta+bPlZluPF7++yR3p/bg==} - peerDependencies: - '@azure/app-configuration': ^1.8.0 - '@azure/cosmos': ^4.2.0 - '@azure/data-tables': ^13.3.0 - '@azure/identity': ^4.6.0 - '@azure/keyvault-secrets': ^4.9.0 - '@azure/storage-blob': ^12.26.0 - '@capacitor/preferences': ^6.0.3 - '@deno/kv': '>=0.9.0' - '@netlify/blobs': ^6.5.0 || ^7.0.0 || ^8.1.0 - '@planetscale/database': ^1.19.0 - '@upstash/redis': ^1.34.3 - '@vercel/blob': '>=0.27.1' - '@vercel/kv': ^1.0.1 - aws4fetch: ^1.0.20 - db0: '>=0.2.1' - idb-keyval: ^6.2.1 - ioredis: ^5.4.2 - uploadthing: ^7.4.4 - peerDependenciesMeta: - '@azure/app-configuration': - optional: true - '@azure/cosmos': - optional: true - '@azure/data-tables': - optional: true - '@azure/identity': - optional: true - '@azure/keyvault-secrets': - optional: true - '@azure/storage-blob': - optional: true - '@capacitor/preferences': - optional: true - '@deno/kv': - optional: true - '@netlify/blobs': - optional: true - '@planetscale/database': - optional: true - '@upstash/redis': - optional: true - '@vercel/blob': - optional: true - '@vercel/kv': - optional: true - aws4fetch: - optional: true - db0: - optional: true - idb-keyval: - optional: true - ioredis: - optional: true - uploadthing: - optional: true - unstorage@1.17.2: resolution: {integrity: sha512-cKEsD6iBWJgOMJ6vW1ID/SYuqNf8oN4yqRk8OYqaVQ3nnkJXOT1PSpaMh2QfzLs78UN5kSNRD2c/mgjT8tX7+w==} peerDependencies: @@ -5793,124 +4987,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vega-canvas@2.0.0: - resolution: {integrity: sha512-9x+4TTw/USYST5nx4yN272sy9WcqSRjAR0tkQYZJ4cQIeon7uVsnohvoPQK1JZu7K1QXGUqzj08z0u/UegBVMA==} - - vega-crossfilter@5.1.0: - resolution: {integrity: sha512-EmVhfP3p6AM7o/lPan/QAoqjblI19BxWUlvl2TSs0xjQd8KbaYYbS4Ixt3cmEvl0QjRdBMF6CdJJ/cy9DTS4Fw==} - - vega-dataflow@6.1.0: - resolution: {integrity: sha512-JxumGlODtFbzoQ4c/jQK8Tb/68ih0lrexlCozcMfTAwQ12XhTqCvlafh7MAKKTMBizjOfaQTHm4Jkyb1H5CfyQ==} - - vega-embed@7.1.0: - resolution: {integrity: sha512-ZmEIn5XJrQt7fSh2lwtSdXG/9uf3yIqZnvXFEwBJRppiBgrEWZcZbj6VK3xn8sNTFQ+sQDXW5sl/6kmbAW3s5A==} - peerDependencies: - vega: '*' - vega-lite: '*' - - vega-encode@5.1.0: - resolution: {integrity: sha512-q26oI7B+MBQYcTQcr5/c1AMsX3FvjZLQOBi7yI0vV+GEn93fElDgvhQiYrgeYSD4Exi/jBPeUXuN6p4bLz16kA==} - - vega-event-selector@4.0.0: - resolution: {integrity: sha512-CcWF4m4KL/al1Oa5qSzZ5R776q8lRxCj3IafCHs5xipoEHrkgu1BWa7F/IH5HrDNXeIDnqOpSV1pFsAWRak4gQ==} - - vega-expression@6.1.0: - resolution: {integrity: sha512-hHgNx/fQ1Vn1u6vHSamH7lRMsOa/yQeHGGcWVmh8fZafLdwdhCM91kZD9p7+AleNpgwiwzfGogtpATFaMmDFYg==} - - vega-force@5.1.0: - resolution: {integrity: sha512-wdnchOSeXpF9Xx8Yp0s6Do9F7YkFeOn/E/nENtsI7NOcyHpICJ5+UkgjUo9QaQ/Yu+dIDU+sP/4NXsUtq6SMaQ==} - - vega-format@2.1.0: - resolution: {integrity: sha512-i9Ht33IgqG36+S1gFDpAiKvXCPz+q+1vDhDGKK8YsgMxGOG4PzinKakI66xd7SdV4q97FgpR7odAXqtDN2wKqw==} - - vega-functions@6.1.1: - resolution: {integrity: sha512-Due6jP0y0FfsGMTrHnzUGnEwXPu7VwE+9relfo+LjL/tRPYnnKqwWvzt7n9JkeBuZqjkgYjMzm/WucNn6Hkw5A==} - - vega-geo@5.1.0: - resolution: {integrity: sha512-H8aBBHfthc3rzDbz/Th18+Nvp00J73q3uXGAPDQqizioDm/CoXCK8cX4pMePydBY9S6ikBiGJrLKFDa80wI20g==} - - vega-hierarchy@5.1.0: - resolution: {integrity: sha512-rZlU8QJNETlB6o73lGCPybZtw2fBBsRIRuFE77aCLFHdGsh6wIifhplVarqE9icBqjUHRRUOmcEYfzwVIPr65g==} - - vega-interpreter@2.2.1: - resolution: {integrity: sha512-o+4ZEme2mdFLewlpF76dwPWW2VkZ3TAF3DMcq75/NzA5KPvnN4wnlCM8At2FVawbaHRyGdVkJSS5ROF5KwpHPQ==} - - vega-label@2.1.0: - resolution: {integrity: sha512-/hgf+zoA3FViDBehrQT42Lta3t8In6YwtMnwjYlh72zNn1p3c7E3YUBwqmAqTM1x+tudgzMRGLYig+bX1ewZxQ==} - - vega-lite@6.4.1: - resolution: {integrity: sha512-KO3ybHNouRK4A0al/+2fN9UqgTEfxrd/ntGLY933Hg5UOYotDVQdshR3zn7OfXwQ7uj0W96Vfa5R+QxO8am3IQ==} - engines: {node: '>=18'} - hasBin: true - peerDependencies: - vega: ^6.0.0 - - vega-loader@5.1.0: - resolution: {integrity: sha512-GaY3BdSPbPNdtrBz8SYUBNmNd8mdPc3mtdZfdkFazQ0RD9m+Toz5oR8fKnTamNSk9fRTJX0Lp3uEqxrAlQVreg==} - - vega-parser@7.1.0: - resolution: {integrity: sha512-g0lrYxtmYVW8G6yXpIS4J3Uxt9OUSkc0bLu5afoYDo4rZmoOOdll3x3ebActp5LHPW+usZIE+p5nukRS2vEc7Q==} - - vega-projection@2.1.0: - resolution: {integrity: sha512-EjRjVSoMR5ibrU7q8LaOQKP327NcOAM1+eZ+NO4ANvvAutwmbNVTmfA1VpPH+AD0AlBYc39ND/wnRk7SieDiXA==} - - vega-regression@2.1.0: - resolution: {integrity: sha512-HzC7MuoEwG1rIxRaNTqgcaYF03z/ZxYkQR2D5BN0N45kLnHY1HJXiEcZkcffTsqXdspLjn47yLi44UoCwF5fxQ==} - - vega-runtime@7.1.0: - resolution: {integrity: sha512-mItI+WHimyEcZlZrQ/zYR3LwHVeyHCWwp7MKaBjkU8EwkSxEEGVceyGUY9X2YuJLiOgkLz/6juYDbMv60pfwYA==} - - vega-scale@8.1.0: - resolution: {integrity: sha512-VEgDuEcOec8+C8+FzLcnAmcXrv2gAJKqQifCdQhkgnsLa978vYUgVfCut/mBSMMHbH8wlUV1D0fKZTjRukA1+A==} - - vega-scenegraph@5.1.0: - resolution: {integrity: sha512-4gA89CFIxkZX+4Nvl8SZF2MBOqnlj9J5zgdPh/HPx+JOwtzSlUqIhxFpFj7GWYfwzr/PyZnguBLPihPw1Og/cA==} - - vega-schema-url-parser@3.0.2: - resolution: {integrity: sha512-xAnR7KAvNPYewI3O0l5QGdT8Tv0+GCZQjqfP39cW/hbe/b3aYMAQ39vm8O2wfXUHzm04xTe7nolcsx8WQNVLRQ==} - - vega-selections@6.1.2: - resolution: {integrity: sha512-xJ+V4qdd46nk2RBdwIRrQm2iSTMHdlu/omhLz1pqRL3jZDrkqNBXimrisci2kIKpH2WBpA1YVagwuZEKBmF2Qw==} - - vega-statistics@2.0.0: - resolution: {integrity: sha512-dGPfDXnBlgXbZF3oxtkb8JfeRXd5TYHx25Z/tIoaa9jWua4Vf/AoW2wwh8J1qmMy8J03/29aowkp1yk4DOPazQ==} - - vega-themes@3.0.0: - resolution: {integrity: sha512-1iFiI3BNmW9FrsLnDLx0ZKEddsCitRY3XmUAwp6qmp+p+IXyJYc9pfjlVj9E6KXBPfm4cQyU++s0smKNiWzO4g==} - peerDependencies: - vega: '*' - vega-lite: '*' - - vega-time@3.1.0: - resolution: {integrity: sha512-G93mWzPwNa6UYQRkr8Ujur9uqxbBDjDT/WpXjbDY0yygdSkRT+zXF+Sb4gjhW0nPaqdiwkn0R6kZcSPMj1bMNA==} - - vega-tooltip@1.0.0: - resolution: {integrity: sha512-P1R0JP29v0qnTuwzCQ0SPJlkjAzr6qeyj+H4VgUFSykHmHc1OBxda//XBaFDl/bZgIscEMvjKSjZpXd84x3aZQ==} - - vega-transforms@5.1.0: - resolution: {integrity: sha512-mj/sO2tSuzzpiXX8JSl4DDlhEmVwM/46MTAzTNQUQzJPMI/n4ChCjr/SdEbfEyzlD4DPm1bjohZGjLc010yuMg==} - - vega-typings@2.1.0: - resolution: {integrity: sha512-zdis4Fg4gv37yEvTTSZEVMNhp8hwyEl7GZ4X4HHddRVRKxWFsbyKvZx/YW5Z9Ox4sjxVA2qHzEbod4Fdx+SEJA==} - - vega-util@2.1.0: - resolution: {integrity: sha512-PGfp0m0QCufDmcxKJCWQy4Ov23FoF8DSXmoJwSezi3itQaa2hbxK0+xwsTMP2vy4PR16Pu25HMzgMwXVW1+33w==} - - vega-view-transforms@5.1.0: - resolution: {integrity: sha512-fpigh/xn/32t+An1ShoY3MLeGzNdlbAp2+HvFKzPpmpMTZqJEWkk/J/wHU7Swyc28Ta7W1z3fO+8dZkOYO5TWQ==} - - vega-view@6.1.0: - resolution: {integrity: sha512-hmHDm/zC65lb23mb9Tr9Gx0wkxP0TMS31LpMPYxIZpvInxvUn7TYitkOtz1elr63k2YZrgmF7ztdGyQ4iCQ5fQ==} - - vega-voronoi@5.1.0: - resolution: {integrity: sha512-uKdsoR9x60mz7eYtVG+NhlkdQXeVdMr6jHNAHxs+W+i6kawkUp5S9jp1xf1FmW/uZvtO1eqinHQNwATcDRsiUg==} - - vega-wordcloud@5.1.0: - resolution: {integrity: sha512-sSdNmT8y2D7xXhM2h76dKyaYn3PA4eV49WUUkfYfqHz/vpcu10GSAoFxLhQQTkbZXR+q5ZB63tFUow9W2IFo6g==} - - vega@6.2.0: - resolution: {integrity: sha512-BIwalIcEGysJdQDjeVUmMWB3e50jPDNAMfLJscjEvpunU9bSt7X1OYnQxkg3uBwuRRI4nWfFZO9uIW910nLeGw==} - vite-dev-rpc@1.1.0: resolution: {integrity: sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==} peerDependencies: @@ -6053,9 +5129,6 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - vt-pbf@3.1.3: - resolution: {integrity: sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==} - vue-bundle-renderer@2.2.0: resolution: {integrity: sha512-sz/0WEdYH1KfaOm0XaBmRZOWgYTEvUDt6yPYaUzl4E52qzgWLlknaPPTTZmp6benaPTlQAI/hN1x3tAzZygycg==} @@ -6101,8 +5174,8 @@ packages: esbuild: '*' vue: ^3.5.13 - vue-tsc@3.1.3: - resolution: {integrity: sha512-StMNfZHwPIXQgY3KxPKM0Jsoc8b46mDV3Fn2UlHCBIwRJApjqrSwqeMYgWf0zpN+g857y74pv7GWuBm+UqQe1w==} + vue-tsc@3.2.6: + resolution: {integrity: sha512-gYW/kWI0XrwGzd0PKc7tVB/qpdeAkIZLNZb10/InizkQjHjnT8weZ/vBarZoj4kHKbUTZT/bAVgoOr8x4NsQ/Q==} hasBin: true peerDependencies: typescript: '>=5.0.0' @@ -6129,9 +5202,6 @@ packages: webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - wgs84@0.0.0: - resolution: {integrity: sha512-ANHlY4Rb5kHw40D0NJ6moaVfOCMrp9Gpd1R/AIQYg2ko4/jzcJ+TVXYYF6kXJqQwITvEZP4yEthjM7U6rYlljQ==} - whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -6151,32 +5221,11 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - 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-typed-array@1.1.19: - resolution: {integrity: sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==} - engines: {node: '>= 0.4'} - which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - which@4.0.0: - resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} - engines: {node: ^16.13.0 || >=18.0.0} - hasBin: true - which@5.0.0: resolution: {integrity: sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==} engines: {node: ^18.17.0 || >=20.5.0} @@ -6199,10 +5248,6 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} - wrap-ansi@9.0.2: - resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} - engines: {node: '>=18'} - ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} engines: {node: '>=10.0.0'} @@ -6254,18 +5299,10 @@ packages: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} - yargs-parser@22.0.0: - resolution: {integrity: sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} - yargs@18.0.0: - resolution: {integrity: sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==} - engines: {node: ^20.19.0 || ^22.12.0 || >=23} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -6329,7 +5366,20 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 - '@auth0/auth0-spa-js@2.1.3': {} + '@auth0/auth0-auth-js@1.6.0': + dependencies: + jose: 6.2.2 + openid-client: 6.8.2 + + '@auth0/auth0-nuxt@1.0.1': + dependencies: + '@auth0/auth0-server-js': 1.3.0 + h3: 1.15.10 + + '@auth0/auth0-server-js@1.3.0': + dependencies: + '@auth0/auth0-auth-js': 1.6.0 + jose: 6.2.2 '@babel/code-frame@7.27.1': dependencies: @@ -6536,7 +5586,7 @@ snapshots: '@dxup/nuxt@0.2.1(magicast@0.5.1)': dependencies: '@dxup/unimport': 0.1.1 - '@nuxt/kit': 4.2.0(magicast@0.5.1) + '@nuxt/kit': 4.2.1(magicast@0.5.1) chokidar: 4.0.3 pathe: 2.0.3 tinyglobby: 0.2.15 @@ -6686,7 +5736,7 @@ snapshots: eslint: 9.39.1(jiti@2.6.1) find-up: 7.0.0 get-port-please: 3.2.0 - h3: 1.15.4 + h3: 1.15.10 mlly: 1.8.0 mrmime: 2.0.1 open: 10.2.0 @@ -6792,45 +5842,6 @@ snapshots: '@kwsites/promise-deferred@1.1.1': {} - '@mapbox/extent@0.4.0': {} - - '@mapbox/geojson-area@0.2.2': - dependencies: - wgs84: 0.0.0 - - '@mapbox/geojson-coords@0.0.2': - dependencies: - '@mapbox/geojson-normalize': 0.0.1 - geojson-flatten: 1.1.1 - - '@mapbox/geojson-extent@1.0.1': - dependencies: - '@mapbox/extent': 0.4.0 - '@mapbox/geojson-coords': 0.0.2 - rw: 0.1.4 - traverse: 0.6.11 - - '@mapbox/geojson-normalize@0.0.1': {} - - '@mapbox/geojson-rewind@0.5.2': - dependencies: - get-stream: 6.0.1 - minimist: 1.2.8 - - '@mapbox/jsonlint-lines-primitives@2.0.2': {} - - '@mapbox/mapbox-gl-draw@1.4.3': - dependencies: - '@mapbox/geojson-area': 0.2.2 - '@mapbox/geojson-extent': 1.0.1 - '@mapbox/geojson-normalize': 0.0.1 - '@mapbox/point-geometry': 0.1.0 - hat: 0.0.3 - lodash.isequal: 4.5.0 - xtend: 4.0.2 - - '@mapbox/mapbox-gl-supported@3.0.0': {} - '@mapbox/node-pre-gyp@2.0.0': dependencies: consola: 3.4.2 @@ -6844,45 +5855,6 @@ snapshots: - encoding - supports-color - '@mapbox/point-geometry@0.1.0': {} - - '@mapbox/point-geometry@1.1.0': {} - - '@mapbox/tiny-sdf@2.0.7': {} - - '@mapbox/unitbezier@0.0.1': {} - - '@mapbox/vector-tile@1.3.1': - dependencies: - '@mapbox/point-geometry': 0.1.0 - - '@mapbox/vector-tile@2.0.4': - dependencies: - '@mapbox/point-geometry': 1.1.0 - '@types/geojson': 7946.0.16 - pbf: 4.0.1 - - '@mapbox/whoots-js@3.1.0': {} - - '@maplibre/maplibre-gl-geocoder@1.9.0(maplibre-gl@5.2.0)': - dependencies: - events: 3.3.0 - lodash.debounce: 4.0.8 - maplibre-gl: 5.2.0 - subtag: 0.5.0 - suggestions-list: 0.0.2 - xtend: 4.0.2 - - '@maplibre/maplibre-gl-style-spec@23.3.0': - dependencies: - '@mapbox/jsonlint-lines-primitives': 2.0.2 - '@mapbox/unitbezier': 0.0.1 - json-stringify-pretty-compact: 4.0.0 - minimist: 1.2.8 - quickselect: 3.0.0 - rw: 1.3.3 - tinyqueue: 3.0.0 - '@mdi/font@7.4.47': {} '@napi-rs/wasm-runtime@0.2.12': @@ -6964,7 +5936,7 @@ snapshots: '@nuxt/devtools-kit@3.0.1(magicast@0.5.1)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: - '@nuxt/kit': 4.2.0(magicast@0.5.1) + '@nuxt/kit': 4.2.1(magicast@0.5.1) execa: 8.0.1 vite: 7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: @@ -7045,7 +6017,7 @@ snapshots: dependencies: '@nuxt/devtools-kit': 3.0.1(magicast@0.5.1)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) '@nuxt/devtools-wizard': 3.0.1 - '@nuxt/kit': 4.2.0(magicast@0.5.1) + '@nuxt/kit': 4.2.1(magicast@0.5.1) '@vue/devtools-core': 7.7.7(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) '@vue/devtools-kit': 7.7.7 birpc: 2.8.0 @@ -7072,7 +6044,7 @@ snapshots: structured-clone-es: 1.0.0 tinyglobby: 0.2.15 vite: 7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vite-plugin-inspect: 11.3.3(@nuxt/kit@4.2.0(magicast@0.5.1))(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) + vite-plugin-inspect: 11.3.3(@nuxt/kit@4.2.1(magicast@0.5.1))(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) vite-plugin-vue-tracer: 1.1.3(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) which: 5.0.0 ws: 8.18.3 @@ -7128,7 +6100,7 @@ snapshots: '@nuxt/devtools-kit': 3.1.0(magicast@0.5.1)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) '@nuxt/eslint-config': 1.10.0(@typescript-eslint/utils@8.46.4(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.24)(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) '@nuxt/eslint-plugin': 1.10.0(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) - '@nuxt/kit': 4.2.0(magicast@0.5.1) + '@nuxt/kit': 4.2.1(magicast@0.5.1) chokidar: 4.0.3 eslint: 9.39.1(jiti@2.6.1) eslint-flat-config-utils: 2.1.4 @@ -7170,7 +6142,7 @@ snapshots: scule: 1.3.0 semver: 7.7.3 tinyglobby: 0.2.15 - ufo: 1.6.1 + ufo: 1.6.3 unctx: 2.4.1 untyped: 2.0.0 transitivePeerDependencies: @@ -7196,7 +6168,7 @@ snapshots: scule: 1.3.0 semver: 7.7.3 tinyglobby: 0.2.15 - ufo: 1.6.1 + ufo: 1.6.3 unctx: 2.4.1 untyped: 2.0.0 transitivePeerDependencies: @@ -7221,7 +6193,7 @@ snapshots: scule: 1.3.0 semver: 7.7.3 tinyglobby: 0.2.15 - ufo: 1.6.1 + ufo: 1.6.3 unctx: 2.4.1 untyped: 2.0.0 transitivePeerDependencies: @@ -7246,13 +6218,13 @@ snapshots: scule: 1.3.0 semver: 7.7.3 tinyglobby: 0.2.15 - ufo: 1.6.1 + ufo: 1.6.3 unctx: 2.4.1 untyped: 2.0.0 transitivePeerDependencies: - magicast - '@nuxt/module-builder@1.0.2(@nuxt/cli@3.30.0(magicast@0.5.1))(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(sass@1.86.0)(typescript@5.9.3)(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3))': + '@nuxt/module-builder@1.0.2(@nuxt/cli@3.30.0(magicast@0.5.1))(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(sass@1.86.0)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3))': dependencies: '@nuxt/cli': 3.30.0(magicast@0.5.1) citty: 0.1.6 @@ -7260,13 +6232,13 @@ snapshots: defu: 6.1.4 jiti: 2.6.1 magic-regexp: 0.10.0 - mkdist: 2.4.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) + mkdist: 2.4.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) mlly: 1.8.0 pathe: 2.0.3 pkg-types: 2.3.0 tsconfck: 3.1.6(typescript@5.9.3) typescript: 5.9.3 - unbuild: 3.6.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) + unbuild: 3.6.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) vue-sfc-transformer: 0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)) transitivePeerDependencies: - '@vue/compiler-core' @@ -7275,7 +6247,7 @@ snapshots: - vue - vue-tsc - '@nuxt/nitro-server@4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1))(typescript@5.9.3)': + '@nuxt/nitro-server@4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1))(typescript@5.9.3)': dependencies: '@nuxt/devalue': 2.0.2 '@nuxt/kit': 4.2.0(magicast@0.5.1) @@ -7288,17 +6260,17 @@ snapshots: errx: 0.1.0 escape-string-regexp: 5.0.0 exsolve: 1.0.8 - h3: 1.15.4 + h3: 1.15.10 impound: 1.0.0 klona: 2.0.6 mocked-exports: 0.1.1 nitropack: 2.12.9 - nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1) + nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1) pathe: 2.0.3 pkg-types: 2.3.0 radix3: 1.1.2 std-env: 3.10.0 - ufo: 1.6.1 + ufo: 1.6.3 unctx: 2.4.1 unstorage: 1.17.2(db0@0.3.4)(ioredis@5.8.2) vue: 3.5.22(typescript@5.9.3) @@ -7366,7 +6338,7 @@ snapshots: '@nuxt/test-utils@3.20.1(@vue/test-utils@2.4.6)(happy-dom@18.0.1)(jsdom@26.1.0)(magicast@0.5.1)(playwright-core@1.54.2)(typescript@5.9.3)(vitest@3.2.4(@types/node@24.10.0)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@26.1.0)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))': dependencies: - '@nuxt/kit': 4.2.0(magicast@0.5.1) + '@nuxt/kit': 4.2.1(magicast@0.5.1) c12: 3.3.2(magicast@0.5.1) consola: 3.4.2 defu: 6.1.4 @@ -7374,7 +6346,7 @@ snapshots: estree-walker: 3.0.3 fake-indexeddb: 6.2.5 get-port-please: 3.2.0 - h3: 1.15.4 + h3: 1.15.10 local-pkg: 1.1.2 magic-string: 0.30.21 node-fetch-native: 1.6.7 @@ -7418,7 +6390,7 @@ snapshots: '@types/webpack-bundle-analyzer': 3.9.5 '@types/webpack-hot-middleware': 2.25.5 - '@nuxt/vite-builder@4.2.0(@types/node@24.10.0)(eslint@9.39.1(jiti@2.6.1))(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1)': + '@nuxt/vite-builder@4.2.0(@types/node@24.10.0)(eslint@9.39.1(jiti@2.6.1))(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1)': dependencies: '@nuxt/kit': 4.2.0(magicast@0.5.1) '@rollup/plugin-replace': 6.0.3(rollup@4.53.2) @@ -7432,24 +6404,24 @@ snapshots: escape-string-regexp: 5.0.0 exsolve: 1.0.8 get-port-please: 3.2.0 - h3: 1.15.4 + h3: 1.15.10 jiti: 2.6.1 knitwork: 1.2.0 magic-string: 0.30.21 mlly: 1.8.0 mocked-exports: 0.1.1 - nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1) + nuxt: 4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1) pathe: 2.0.3 pkg-types: 2.3.0 postcss: 8.5.6 rollup-plugin-visualizer: 6.0.5(rollup@4.53.2) seroval: 1.3.2 std-env: 3.10.0 - ufo: 1.6.1 + ufo: 1.6.3 unenv: 2.0.0-rc.24 vite: 7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) vite-node: 3.2.4(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) - vite-plugin-checker: 0.11.0(eslint@9.39.1(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3)) + vite-plugin-checker: 0.11.0(eslint@9.39.1(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3)) vue: 3.5.22(typescript@5.9.3) vue-bundle-renderer: 2.2.0 transitivePeerDependencies: @@ -7477,12 +6449,6 @@ snapshots: - vue-tsc - yaml - '@observablehq/plot@0.6.17': - dependencies: - d3: 7.9.0 - interval-tree-1d: 1.0.4 - isoformat: 0.2.1 - '@one-ini/wasm@0.1.1': {} '@oxc-minify/binding-android-arm64@0.95.0': @@ -7922,23 +6888,6 @@ snapshots: estraverse: 5.3.0 picomatch: 4.0.3 - '@turf/centroid@7.3.0': - dependencies: - '@turf/helpers': 7.3.0 - '@turf/meta': 7.3.0 - '@types/geojson': 7946.0.16 - tslib: 2.8.1 - - '@turf/helpers@7.3.0': - dependencies: - '@types/geojson': 7946.0.16 - tslib: 2.8.1 - - '@turf/meta@7.3.0': - dependencies: - '@turf/helpers': 7.3.0 - '@types/geojson': 7946.0.16 - '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 @@ -7985,14 +6934,6 @@ snapshots: '@types/css-font-loading-module@0.0.7': {} - '@types/cytoscape-fcose@2.2.4': - dependencies: - '@types/cytoscape': 3.21.9 - - '@types/cytoscape@3.21.9': {} - - '@types/d3-scale-chromatic@3.1.0': {} - '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} @@ -8018,10 +6959,6 @@ snapshots: dependencies: '@types/webpack': 4.41.40 - '@types/geojson-vt@3.2.5': - dependencies: - '@types/geojson': 7946.0.16 - '@types/geojson@7946.0.16': {} '@types/html-minifier-terser@7.0.2': {} @@ -8038,22 +6975,9 @@ snapshots: '@types/less@3.0.6': {} - '@types/mapbox__mapbox-gl-draw@1.4.8': - dependencies: - '@types/geojson': 7946.0.16 - mapbox-gl: 3.16.0 - - '@types/mapbox__point-geometry@0.1.4': {} + '@types/node@16.18.126': {} - '@types/mapbox__vector-tile@1.3.4': - dependencies: - '@types/geojson': 7946.0.16 - '@types/mapbox__point-geometry': 0.1.4 - '@types/pbf': 3.0.5 - - '@types/node@16.18.126': {} - - '@types/node@20.19.24': + '@types/node@20.19.24': dependencies: undici-types: 6.21.0 @@ -8069,8 +6993,6 @@ snapshots: dependencies: parse-path: 7.1.0 - '@types/pbf@3.0.5': {} - '@types/pg@8.15.4': dependencies: '@types/node': 24.10.0 @@ -8101,10 +7023,6 @@ snapshots: '@types/source-list-map@0.1.6': {} - '@types/supercluster@7.1.3': - dependencies: - '@types/geojson': 7946.0.16 - '@types/tapable@1.0.12': {} '@types/terser-webpack-plugin@4.2.1': @@ -8476,15 +7394,15 @@ snapshots: loupe: 3.2.1 tinyrainbow: 2.0.0 - '@volar/language-core@2.4.23': + '@volar/language-core@2.4.28': dependencies: - '@volar/source-map': 2.4.23 + '@volar/source-map': 2.4.28 - '@volar/source-map@2.4.23': {} + '@volar/source-map@2.4.28': {} - '@volar/typescript@2.4.23': + '@volar/typescript@2.4.28': dependencies: - '@volar/language-core': 2.4.23 + '@volar/language-core': 2.4.28 path-browserify: 1.0.1 vscode-uri: 3.1.0 @@ -8632,17 +7550,15 @@ snapshots: dependencies: rfdc: 1.4.1 - '@vue/language-core@3.1.3(typescript@5.9.3)': + '@vue/language-core@3.2.6': dependencies: - '@volar/language-core': 2.4.23 + '@volar/language-core': 2.4.28 '@vue/compiler-dom': 3.5.24 '@vue/shared': 3.5.24 alien-signals: 3.1.0 muggle-string: 0.4.1 path-browserify: 1.0.1 picomatch: 4.0.3 - optionalDependencies: - typescript: 5.9.3 '@vue/reactivity@3.5.22': dependencies: @@ -8675,16 +7591,16 @@ snapshots: js-beautify: 1.15.4 vue-component-type-helpers: 2.2.12 - '@vueuse/core@14.0.0(vue@3.5.22(typescript@5.9.3))': + '@vueuse/core@14.2.1(vue@3.5.22(typescript@5.9.3))': dependencies: '@types/web-bluetooth': 0.0.21 - '@vueuse/metadata': 14.0.0 - '@vueuse/shared': 14.0.0(vue@3.5.22(typescript@5.9.3)) + '@vueuse/metadata': 14.2.1 + '@vueuse/shared': 14.2.1(vue@3.5.22(typescript@5.9.3)) vue: 3.5.22(typescript@5.9.3) - '@vueuse/metadata@14.0.0': {} + '@vueuse/metadata@14.2.1': {} - '@vueuse/shared@14.0.0(vue@3.5.22(typescript@5.9.3))': + '@vueuse/shared@14.2.1(vue@3.5.22(typescript@5.9.3))': dependencies: vue: 3.5.22(typescript@5.9.3) @@ -8790,23 +7706,8 @@ snapshots: argparse@2.0.1: {} - array-buffer-byte-length@1.0.2: - dependencies: - call-bound: 1.0.4 - is-array-buffer: 3.0.5 - array-flatten@1.1.1: {} - 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.0 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - is-array-buffer: 3.0.5 - assertion-error@2.0.1: {} ast-kit@2.2.0: @@ -8819,8 +7720,6 @@ snapshots: '@babel/parser': 7.28.5 ast-kit: 2.2.0 - async-function@1.0.0: {} - async-sema@3.1.1: {} async@3.2.6: {} @@ -8835,10 +7734,6 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 - available-typed-arrays@1.0.7: - dependencies: - possible-typed-array-names: 1.1.0 - b4a@1.7.3: {} balanced-match@1.0.2: {} @@ -8855,8 +7750,6 @@ snapshots: dependencies: safe-buffer: 5.1.2 - binary-search-bounds@2.0.5: {} - bindings@1.5.0: dependencies: file-uri-to-path: 1.0.0 @@ -8972,13 +7865,6 @@ snapshots: 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 @@ -9010,8 +7896,6 @@ snapshots: change-case@5.4.4: {} - cheap-ruler@4.0.0: {} - check-error@2.1.1: {} chokidar@4.0.3: @@ -9042,12 +7926,6 @@ snapshots: strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - cliui@9.0.1: - dependencies: - string-width: 7.2.0 - strip-ansi: 7.1.2 - wrap-ansi: 9.0.2 - cluster-key-slot@1.1.2: {} color-convert@2.0.1: @@ -9062,12 +7940,8 @@ snapshots: commander@11.1.0: {} - commander@14.0.0: {} - commander@2.20.3: {} - commander@7.2.0: {} - comment-parser@1.4.1: {} commondir@1.0.1: {} @@ -9130,10 +8004,6 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 - cose-base@2.2.0: - dependencies: - layout-base: 2.0.1 - crc-32@1.2.2: {} crc32-stream@6.0.0: @@ -9177,8 +8047,6 @@ snapshots: css-what@6.2.2: {} - csscolorparser@1.0.3: {} - cssesc@3.0.0: {} cssnano-preset-default@7.0.10(postcss@8.5.6): @@ -9238,198 +8106,13 @@ snapshots: csv-stringify@6.6.0: {} - cytoscape-fcose@2.2.0(cytoscape@3.31.1): - dependencies: - cose-base: 2.2.0 - cytoscape: 3.31.1 - - cytoscape@3.31.1: {} - - d3-array@3.2.4: - dependencies: - internmap: 2.0.3 - - d3-axis@3.0.0: {} - - d3-brush@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - - d3-chord@3.0.1: - dependencies: - d3-path: 3.1.0 - - d3-color@3.1.0: {} - - d3-contour@4.0.2: - dependencies: - d3-array: 3.2.4 - - d3-delaunay@6.0.4: - dependencies: - delaunator: 5.0.1 - - d3-dispatch@3.0.1: {} - - d3-drag@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-selection: 3.0.0 - - d3-dsv@3.0.1: - dependencies: - commander: 7.2.0 - iconv-lite: 0.6.3 - rw: 1.3.3 - - d3-ease@3.0.1: {} - - d3-fetch@3.0.1: - dependencies: - d3-dsv: 3.0.1 - - d3-force@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-quadtree: 3.0.1 - d3-timer: 3.0.1 - - d3-format@3.1.0: {} - - d3-geo-projection@4.0.0: - dependencies: - commander: 7.2.0 - d3-array: 3.2.4 - d3-geo: 3.1.1 - - d3-geo@3.1.1: - dependencies: - d3-array: 3.2.4 - - d3-hierarchy@3.1.2: {} - - d3-interpolate@3.0.1: - dependencies: - d3-color: 3.1.0 - - d3-path@3.1.0: {} - - d3-polygon@3.0.1: {} - - d3-quadtree@3.0.1: {} - - d3-random@3.0.1: {} - - d3-scale-chromatic@3.1.0: - dependencies: - d3-color: 3.1.0 - d3-interpolate: 3.0.1 - - d3-scale@4.0.2: - dependencies: - d3-array: 3.2.4 - d3-format: 3.1.0 - d3-interpolate: 3.0.1 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - - d3-selection@3.0.0: {} - - d3-shape@3.2.0: - dependencies: - d3-path: 3.1.0 - - d3-time-format@4.1.0: - dependencies: - d3-time: 3.1.0 - - d3-time@3.1.0: - dependencies: - d3-array: 3.2.4 - - d3-timer@3.0.1: {} - - d3-transition@3.0.1(d3-selection@3.0.0): - dependencies: - d3-color: 3.1.0 - d3-dispatch: 3.0.1 - d3-ease: 3.0.1 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-timer: 3.0.1 - - d3-zoom@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - - d3@7.9.0: - dependencies: - d3-array: 3.2.4 - d3-axis: 3.0.0 - d3-brush: 3.0.0 - d3-chord: 3.0.1 - d3-color: 3.1.0 - d3-contour: 4.0.2 - d3-delaunay: 6.0.4 - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-dsv: 3.0.1 - d3-ease: 3.0.1 - d3-fetch: 3.0.1 - d3-force: 3.0.0 - d3-format: 3.1.0 - d3-geo: 3.1.1 - d3-hierarchy: 3.1.2 - d3-interpolate: 3.0.1 - d3-path: 3.1.0 - d3-polygon: 3.0.1 - d3-quadtree: 3.0.1 - d3-random: 3.0.1 - d3-scale: 4.0.2 - d3-scale-chromatic: 3.1.0 - d3-selection: 3.0.0 - d3-shape: 3.2.0 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - d3-timer: 3.0.1 - d3-transition: 3.0.1(d3-selection@3.0.0) - d3-zoom: 3.0.0 - 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 - date-fns@4.1.0: {} - dayjs@1.11.19: {} - db0@0.3.4: {} debug@2.6.9: @@ -9455,28 +8138,12 @@ snapshots: bundle-name: 4.1.0 default-browser-id: 5.0.0 - define-data-property@1.1.4: - dependencies: - es-define-property: 1.0.1 - es-errors: 1.3.0 - gopd: 1.2.0 - define-lazy-prop@2.0.0: {} define-lazy-prop@3.0.0: {} - define-properties@1.2.1: - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - defu@6.1.4: {} - delaunator@5.0.1: - dependencies: - robust-predicates: 3.0.2 - denque@2.1.0: {} depd@2.0.0: {} @@ -9529,8 +8196,6 @@ snapshots: duplexer@0.1.2: {} - earcut@3.0.2: {} - eastasianwidth@0.2.0: {} editorconfig@1.0.4: @@ -9544,8 +8209,6 @@ snapshots: electron-to-chromium@1.5.250: {} - emoji-regex@10.6.0: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -9562,63 +8225,6 @@ snapshots: errx@0.1.0: {} - es-abstract@1.24.0: - 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.19 - es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -9629,19 +8235,6 @@ snapshots: 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-to-primitive@1.3.0: - dependencies: - is-callable: 1.2.7 - is-date-object: 1.1.0 - is-symbol: 1.1.1 - esbuild@0.25.12: optionalDependencies: '@esbuild/aix-ppc64': 0.25.12 @@ -9974,8 +8567,6 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 - fast-json-patch@3.1.1: {} - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} @@ -10045,10 +8636,6 @@ snapshots: flatted@3.3.3: {} - for-each@0.3.5: - dependencies: - is-callable: 1.2.7 - foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 @@ -10073,33 +8660,12 @@ snapshots: 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: {} - fuse.js@7.1.0: {} - fuzzy@0.1.3: {} - - generator-function@2.0.1: {} - gensync@1.0.0-beta.2: {} - geojson-flatten@1.1.1: {} - - geojson-vt@4.0.2: {} - get-caller-file@2.0.5: {} - get-east-asian-width@1.4.0: {} - get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -10120,16 +8686,8 @@ snapshots: dunder-proto: 1.0.1 es-object-atoms: 1.1.1 - get-stream@6.0.1: {} - get-stream@8.0.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 @@ -10152,8 +8710,6 @@ snapshots: dependencies: git-up: 8.1.1 - gl-matrix@3.4.4: {} - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -10175,21 +8731,10 @@ snapshots: dependencies: ini: 4.1.1 - global-prefix@4.0.0: - dependencies: - ini: 4.1.3 - kind-of: 6.0.3 - which: 4.0.0 - globals@14.0.0: {} globals@16.5.0: {} - globalthis@1.0.4: - dependencies: - define-properties: 1.2.1 - gopd: 1.2.0 - globby@15.0.0: dependencies: '@sindresorhus/merge-streams': 4.0.0 @@ -10212,34 +8757,20 @@ snapshots: graphql@16.10.0: {} - grid-index@1.1.0: {} - gzip-size@7.0.0: dependencies: duplexer: 0.1.2 - h3@1.15.1: - dependencies: - cookie-es: 1.2.2 - crossws: 0.3.5 - defu: 6.1.4 - destr: 2.0.3 - iron-webcrypto: 1.2.1 - node-mock-http: 1.0.3 - radix3: 1.1.2 - ufo: 1.6.1 - uncrypto: 0.1.3 - - h3@1.15.4: + h3@1.15.10: dependencies: cookie-es: 1.2.2 crossws: 0.3.5 defu: 6.1.4 destr: 2.0.5 iron-webcrypto: 1.2.1 - node-mock-http: 1.0.3 + node-mock-http: 1.0.4 radix3: 1.1.2 - ufo: 1.6.1 + ufo: 1.6.3 uncrypto: 0.1.3 happy-dom@18.0.1: @@ -10248,30 +8779,14 @@ snapshots: '@types/whatwg-mimetype': 3.0.2 whatwg-mimetype: 3.0.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 - hat@0.0.3: {} - hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -10359,20 +8874,6 @@ snapshots: ini@4.1.1: {} - ini@4.1.3: {} - - internal-slot@1.1.0: - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.1.0 - - internmap@2.0.3: {} - - interval-tree-1d@1.0.4: - dependencies: - binary-search-bounds: 2.0.5 - ioredis@5.8.2: dependencies: '@ioredis/commands': 1.4.0 @@ -10393,70 +8894,22 @@ snapshots: is-absolute-url@3.0.3: {} - 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-boolean-object@1.2.2: - dependencies: - call-bound: 1.0.4 - has-tostringtag: 1.0.2 - is-builtin-module@5.0.0: dependencies: builtin-modules: 5.0.0 - 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-docker@2.2.1: {} is-docker@3.0.0: {} is-extglob@2.1.1: {} - is-finalizationregistry@1.1.1: - dependencies: - call-bound: 1.0.4 - is-fullwidth-code-point@3.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 @@ -10470,17 +8923,8 @@ snapshots: global-directory: 4.0.1 is-path-inside: 4.0.0 - is-map@2.0.3: {} - is-module@1.0.0: {} - 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-path-inside@4.0.0: {} @@ -10493,19 +8937,6 @@ snapshots: dependencies: '@types/estree': 1.0.8 - 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-ssh@1.4.1: dependencies: protocols: 2.0.2 @@ -10514,32 +8945,6 @@ snapshots: is-stream@3.0.0: {} - 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.19 - - 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 - is-what@5.5.0: {} is-wsl@2.2.0: @@ -10556,14 +8961,10 @@ snapshots: isarray@1.0.0: {} - isarray@2.0.5: {} - isexe@2.0.0: {} isexe@3.1.1: {} - isoformat@0.2.1: {} - jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -10574,6 +8975,8 @@ snapshots: jiti@2.6.1: {} + jose@6.2.2: {} + js-beautify@1.15.4: dependencies: config-chain: 1.1.13 @@ -10636,8 +9039,6 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - json-stringify-pretty-compact@4.0.0: {} - json5@2.2.3: {} jsonfile@6.2.0: @@ -10646,14 +9047,10 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - kdbush@4.0.2: {} - keyv@4.5.4: dependencies: json-buffer: 3.0.1 - kind-of@6.0.3: {} - kleur@3.0.3: {} kleur@4.1.5: {} @@ -10667,8 +9064,6 @@ snapshots: picocolors: 1.1.1 shell-quote: 1.8.3 - layout-base@2.0.1: {} - lazystream@1.0.1: dependencies: readable-stream: 2.3.8 @@ -10690,7 +9085,7 @@ snapshots: crossws: 0.3.5 defu: 6.1.4 get-port-please: 3.2.0 - h3: 1.15.1 + h3: 1.15.10 http-shutdown: 1.2.2 jiti: 2.6.1 mlly: 1.8.0 @@ -10723,14 +9118,10 @@ snapshots: lodash-es@4.17.21: {} - lodash.debounce@4.0.8: {} - lodash.defaults@4.2.0: {} lodash.isarguments@3.1.0: {} - lodash.isequal@4.5.0: {} - lodash.memoize@4.1.2: {} lodash.merge@4.6.2: {} @@ -10783,71 +9174,6 @@ snapshots: '@babel/types': 7.28.5 source-map-js: 1.2.1 - mapbox-gl@3.16.0: - dependencies: - '@mapbox/jsonlint-lines-primitives': 2.0.2 - '@mapbox/mapbox-gl-supported': 3.0.0 - '@mapbox/point-geometry': 1.1.0 - '@mapbox/tiny-sdf': 2.0.7 - '@mapbox/unitbezier': 0.0.1 - '@mapbox/vector-tile': 2.0.4 - '@mapbox/whoots-js': 3.1.0 - '@types/geojson': 7946.0.16 - '@types/geojson-vt': 3.2.5 - '@types/mapbox__point-geometry': 0.1.4 - '@types/pbf': 3.0.5 - '@types/supercluster': 7.1.3 - cheap-ruler: 4.0.0 - csscolorparser: 1.0.3 - earcut: 3.0.2 - geojson-vt: 4.0.2 - gl-matrix: 3.4.4 - grid-index: 1.1.0 - kdbush: 4.0.2 - martinez-polygon-clipping: 0.7.4 - murmurhash-js: 1.0.0 - pbf: 4.0.1 - potpack: 2.1.0 - quickselect: 3.0.0 - serialize-to-js: 3.1.2 - supercluster: 8.0.1 - tinyqueue: 3.0.0 - - maplibre-gl@5.2.0: - dependencies: - '@mapbox/geojson-rewind': 0.5.2 - '@mapbox/jsonlint-lines-primitives': 2.0.2 - '@mapbox/point-geometry': 0.1.0 - '@mapbox/tiny-sdf': 2.0.7 - '@mapbox/unitbezier': 0.0.1 - '@mapbox/vector-tile': 1.3.1 - '@mapbox/whoots-js': 3.1.0 - '@maplibre/maplibre-gl-style-spec': 23.3.0 - '@types/geojson': 7946.0.16 - '@types/geojson-vt': 3.2.5 - '@types/mapbox__point-geometry': 0.1.4 - '@types/mapbox__vector-tile': 1.3.4 - '@types/pbf': 3.0.5 - '@types/supercluster': 7.1.3 - earcut: 3.0.2 - geojson-vt: 4.0.2 - gl-matrix: 3.4.4 - global-prefix: 4.0.0 - kdbush: 4.0.2 - murmurhash-js: 1.0.0 - pbf: 3.3.0 - potpack: 2.1.0 - quickselect: 3.0.0 - supercluster: 8.0.1 - tinyqueue: 3.0.0 - vt-pbf: 3.1.3 - - martinez-polygon-clipping@0.7.4: - dependencies: - robust-predicates: 2.0.4 - splaytree: 0.1.4 - tinyqueue: 1.2.3 - math-intrinsics@1.1.0: {} mdn-data@2.0.28: {} @@ -10909,8 +9235,6 @@ snapshots: dependencies: brace-expansion: 2.0.2 - minimist@1.2.8: {} - minipass@7.1.2: {} minizlib@3.1.0: @@ -10923,7 +9247,7 @@ snapshots: dependencies: rrweb: 2.0.0-alpha.13 - mkdist@2.4.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)): + mkdist@2.4.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)): dependencies: autoprefixer: 10.4.22(postcss@8.5.6) citty: 0.1.6 @@ -10943,7 +9267,7 @@ snapshots: typescript: 5.9.3 vue: 3.5.22(typescript@5.9.3) vue-sfc-transformer: 0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)) - vue-tsc: 3.1.3(typescript@5.9.3) + vue-tsc: 3.2.6(typescript@5.9.3) mlly@1.8.0: dependencies: @@ -10972,8 +9296,6 @@ snapshots: muggle-string@0.4.1: {} - murmurhash-js@1.0.0: {} - nanoid@3.3.11: {} nanoid@5.1.6: {} @@ -11017,7 +9339,7 @@ snapshots: exsolve: 1.0.8 globby: 15.0.0 gzip-size: 7.0.0 - h3: 1.15.4 + h3: 1.15.10 hookable: 5.5.3 httpxy: 0.1.7 ioredis: 5.8.2 @@ -11030,7 +9352,7 @@ snapshots: mime: 4.1.0 mlly: 1.8.0 node-fetch-native: 1.6.7 - node-mock-http: 1.0.3 + node-mock-http: 1.0.4 ofetch: 1.5.1 ohash: 2.0.11 pathe: 2.0.3 @@ -11046,7 +9368,7 @@ snapshots: serve-static: 2.2.0 source-map: 0.7.6 std-env: 3.10.0 - ufo: 1.6.1 + ufo: 1.6.3 ultrahtml: 1.6.0 uncrypto: 0.1.3 unctx: 2.4.1 @@ -11104,6 +9426,8 @@ snapshots: node-mock-http@1.0.3: {} + node-mock-http@1.0.4: {} + node-releases@2.0.27: {} nopt@7.2.1: @@ -11141,16 +9465,16 @@ snapshots: transitivePeerDependencies: - magicast - nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1): + nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1): dependencies: '@dxup/nuxt': 0.2.1(magicast@0.5.1) '@nuxt/cli': 3.30.0(magicast@0.5.1) '@nuxt/devtools': 2.7.0(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue@3.5.22(typescript@5.9.3)) '@nuxt/kit': 4.2.0(magicast@0.5.1) - '@nuxt/nitro-server': 4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1))(typescript@5.9.3) + '@nuxt/nitro-server': 4.2.0(db0@0.3.4)(ioredis@5.8.2)(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1))(typescript@5.9.3) '@nuxt/schema': 4.2.0 '@nuxt/telemetry': 2.6.6(magicast@0.5.1) - '@nuxt/vite-builder': 4.2.0(@types/node@24.10.0)(eslint@9.39.1(jiti@2.6.1))(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1) + '@nuxt/vite-builder': 4.2.0(@types/node@24.10.0)(eslint@9.39.1(jiti@2.6.1))(magicast@0.5.1)(nuxt@4.2.0(@parcel/watcher@2.5.1)(@types/node@24.10.0)(@vue/compiler-sfc@3.5.24)(db0@0.3.4)(eslint@9.39.1(jiti@2.6.1))(ioredis@5.8.2)(magicast@0.5.1)(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3))(yaml@2.8.1))(optionator@0.9.4)(rollup@4.53.2)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(typescript@5.9.3)(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3))(yaml@2.8.1) '@unhead/vue': 2.0.19(vue@3.5.22(typescript@5.9.3)) '@vue/shared': 3.5.24 c12: 3.3.2(magicast@0.5.1) @@ -11164,7 +9488,7 @@ snapshots: errx: 0.1.0 escape-string-regexp: 5.0.0 exsolve: 1.0.8 - h3: 1.15.4 + h3: 1.15.10 hookable: 5.5.3 ignore: 7.0.5 impound: 1.0.0 @@ -11190,13 +9514,13 @@ snapshots: semver: 7.7.3 std-env: 3.10.0 tinyglobby: 0.2.15 - ufo: 1.6.1 + ufo: 1.6.3 ultrahtml: 1.6.0 uncrypto: 0.1.3 unctx: 2.4.1 unimport: 5.5.0 unplugin: 2.3.10 - unplugin-vue-router: 0.16.1(@vue/compiler-sfc@3.5.24)(typescript@5.9.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)) + unplugin-vue-router: 0.16.1(@vue/compiler-sfc@3.5.24)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)) untyped: 2.0.0 vue: 3.5.22(typescript@5.9.3) vue-router: 4.6.3(vue@3.5.22(typescript@5.9.3)) @@ -11271,23 +9595,14 @@ snapshots: pkg-types: 2.3.0 tinyexec: 1.0.2 + oauth4webapi@3.8.5: {} + object-assign@4.1.1: {} object-deep-merge@2.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 - ofetch@1.5.1: dependencies: destr: 2.0.5 @@ -11325,6 +9640,11 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 + openid-client@6.8.2: + dependencies: + jose: 6.2.2 + oauth4webapi: 3.8.5 + optimism@0.18.1: dependencies: '@wry/caches': 1.0.1 @@ -11341,12 +9661,6 @@ snapshots: 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 - oxc-minify@0.95.0: optionalDependencies: '@oxc-minify/binding-android-arm64': 0.95.0 @@ -11480,15 +9794,6 @@ snapshots: pathval@2.0.1: {} - pbf@3.3.0: - dependencies: - ieee754: 1.2.1 - resolve-protobuf-schema: 2.1.0 - - pbf@4.0.1: - dependencies: - resolve-protobuf-schema: 2.1.0 - perfect-debounce@1.0.0: {} perfect-debounce@2.0.0: {} @@ -11527,8 +9832,6 @@ snapshots: pluralize@8.0.0: {} - possible-typed-array-names@1.1.0: {} - postcss-calc@10.1.1(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -11711,8 +10014,6 @@ snapshots: dependencies: xtend: 4.0.2 - potpack@2.1.0: {} - prelude-ls@1.2.1: {} pretty-bytes@7.1.0: {} @@ -11734,8 +10035,6 @@ snapshots: proto-list@1.2.4: {} - protocol-buffers-schema@3.6.0: {} - protocols@2.0.2: {} protomaps-themes-base@1.3.1: {} @@ -11761,8 +10060,6 @@ snapshots: queue-microtask@1.2.3: {} - quickselect@3.0.0: {} - radix3@1.1.2: {} randombytes@2.1.0: @@ -11819,17 +10116,6 @@ snapshots: dependencies: '@eslint-community/regexpp': 4.12.2 - reflect.getprototypeof@1.0.10: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.0 - 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-ast-analysis@0.7.1: dependencies: '@eslint-community/regexpp': 4.12.2 @@ -11837,15 +10123,6 @@ snapshots: regexp-tree@0.1.27: {} - 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 - regjsparser@0.13.0: dependencies: jsesc: 3.1.0 @@ -11864,10 +10141,6 @@ snapshots: resolve-pkg-maps@1.0.0: {} - resolve-protobuf-schema@2.1.0: - dependencies: - protocol-buffers-schema: 3.6.0 - resolve@1.22.11: dependencies: is-core-module: 2.16.1 @@ -11878,10 +10151,6 @@ snapshots: rfdc@1.4.1: {} - robust-predicates@2.0.4: {} - - robust-predicates@3.0.2: {} - rollup-plugin-dts@6.2.3(rollup@4.53.2)(typescript@5.9.3): dependencies: magic-string: 0.30.21 @@ -11956,33 +10225,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 - rw@0.1.4: {} - - rw@1.3.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-buffer@5.1.2: {} safe-buffer@5.2.1: {} - 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: {} sass@1.86.0: @@ -12049,8 +10295,6 @@ snapshots: dependencies: randombytes: 2.1.0 - serialize-to-js@3.1.2: {} - seroval@1.3.2: {} serve-placeholder@2.0.2: @@ -12077,28 +10321,6 @@ snapshots: set-cookie-parser@2.7.2: {} - 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 - setprototypeof@1.2.0: {} shebang-command@2.0.0: @@ -12185,8 +10407,6 @@ snapshots: speakingurl@14.0.1: {} - splaytree@0.1.4: {} - srvx@0.9.5: {} stable-hash-x@0.2.0: {} @@ -12201,11 +10421,6 @@ snapshots: std-env@3.10.0: {} - stop-iteration-iterator@1.1.0: - dependencies: - es-errors: 1.3.0 - internal-slot: 1.1.0 - streamx@2.23.0: dependencies: events-universal: 1.0.1 @@ -12227,35 +10442,6 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.2 - string-width@7.2.0: - dependencies: - emoji-regex: 10.6.0 - get-east-asian-width: 1.4.0 - strip-ansi: 7.1.2 - - 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.0 - 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 - string_decoder@1.1.1: dependencies: safe-buffer: 5.1.2 @@ -12290,17 +10476,6 @@ snapshots: postcss: 8.5.6 postcss-selector-parser: 7.1.0 - subtag@0.5.0: {} - - suggestions-list@0.0.2: - dependencies: - fuzzy: 0.1.3 - xtend: 4.0.2 - - supercluster@8.0.1: - dependencies: - kdbush: 4.0.2 - superjson@2.2.5: dependencies: copy-anything: 4.0.5 @@ -12370,8 +10545,6 @@ snapshots: throttle-debounce@5.0.2: {} - tiny-emitter@2.1.0: {} - tiny-invariant@1.3.3: {} tinybench@2.9.0: {} @@ -12387,10 +10560,6 @@ snapshots: tinypool@1.1.1: {} - tinyqueue@1.2.3: {} - - tinyqueue@3.0.0: {} - tinyrainbow@2.0.0: {} tinyspy@4.0.4: {} @@ -12414,10 +10583,6 @@ snapshots: toidentifier@1.0.1: {} - topojson-client@3.1.0: - dependencies: - commander: 2.20.3 - totalist@3.0.1: {} tough-cookie@5.1.2: @@ -12430,12 +10595,6 @@ snapshots: dependencies: punycode: 2.3.1 - traverse@0.6.11: - dependencies: - gopd: 1.2.0 - typedarray.prototype.slice: 1.0.5 - which-typed-array: 1.1.19 - ts-api-utils@2.1.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -12476,50 +10635,6 @@ snapshots: type-level-regexp@0.1.17: {} - 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 - - typedarray.prototype.slice@1.0.5: - dependencies: - call-bind: 1.0.8 - define-properties: 1.2.1 - es-abstract: 1.24.0 - es-errors: 1.3.0 - get-proto: 1.0.1 - math-intrinsics: 1.1.0 - typed-array-buffer: 1.0.3 - typed-array-byte-offset: 1.0.4 - typescript-eslint@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3): dependencies: '@typescript-eslint/eslint-plugin': 8.46.3(@typescript-eslint/parser@8.46.3(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.1(jiti@2.6.1))(typescript@5.9.3) @@ -12535,16 +10650,11 @@ snapshots: ufo@1.6.1: {} - ultrahtml@1.6.0: {} + ufo@1.6.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 + ultrahtml@1.6.0: {} - unbuild@3.6.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)): + unbuild@3.6.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)): dependencies: '@rollup/plugin-alias': 5.1.1(rollup@4.53.2) '@rollup/plugin-commonjs': 28.0.9(rollup@4.53.2) @@ -12560,7 +10670,7 @@ snapshots: hookable: 5.5.3 jiti: 2.6.1 magic-string: 0.30.21 - mkdist: 2.4.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.1.3(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) + mkdist: 2.4.1(sass@1.86.0)(typescript@5.9.3)(vue-sfc-transformer@0.1.17(@vue/compiler-core@3.5.24)(esbuild@0.25.12)(vue@3.5.22(typescript@5.9.3)))(vue-tsc@3.2.6(typescript@5.9.3))(vue@3.5.22(typescript@5.9.3)) mlly: 1.8.0 pathe: 2.0.3 pkg-types: 2.3.0 @@ -12636,12 +10746,12 @@ snapshots: pathe: 2.0.3 picomatch: 4.0.3 - unplugin-vue-router@0.16.1(@vue/compiler-sfc@3.5.24)(typescript@5.9.3)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)): + unplugin-vue-router@0.16.1(@vue/compiler-sfc@3.5.24)(vue-router@4.6.3(vue@3.5.22(typescript@5.9.3)))(vue@3.5.22(typescript@5.9.3)): dependencies: '@babel/generator': 7.28.5 '@vue-macros/common': 3.1.1(vue@3.5.22(typescript@5.9.3)) '@vue/compiler-sfc': 3.5.24 - '@vue/language-core': 3.1.3(typescript@5.9.3) + '@vue/language-core': 3.2.6 ast-walker-scope: 0.8.3 chokidar: 4.0.3 json5: 2.2.3 @@ -12659,7 +10769,6 @@ snapshots: optionalDependencies: vue-router: 4.6.3(vue@3.5.22(typescript@5.9.3)) transitivePeerDependencies: - - typescript - vue unplugin@2.3.10: @@ -12693,30 +10802,16 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.11.1 '@unrs/resolver-binding-win32-x64-msvc': 1.11.1 - unstorage@1.15.0(db0@0.3.4)(ioredis@5.8.2): - dependencies: - anymatch: 3.1.3 - chokidar: 4.0.3 - destr: 2.0.3 - h3: 1.15.1 - lru-cache: 10.4.3 - node-fetch-native: 1.6.7 - ofetch: 1.5.1 - ufo: 1.6.1 - optionalDependencies: - db0: 0.3.4 - ioredis: 5.8.2 - unstorage@1.17.2(db0@0.3.4)(ioredis@5.8.2): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 destr: 2.0.5 - h3: 1.15.4 + h3: 1.15.10 lru-cache: 10.4.3 node-fetch-native: 1.6.7 ofetch: 1.5.1 - ufo: 1.6.1 + ufo: 1.6.3 optionalDependencies: db0: 0.3.4 ioredis: 5.8.2 @@ -12769,270 +10864,6 @@ snapshots: vary@1.1.2: {} - vega-canvas@2.0.0: {} - - vega-crossfilter@5.1.0: - dependencies: - d3-array: 3.2.4 - vega-dataflow: 6.1.0 - vega-util: 2.1.0 - - vega-dataflow@6.1.0: - dependencies: - vega-format: 2.1.0 - vega-loader: 5.1.0 - vega-util: 2.1.0 - - vega-embed@7.1.0(vega-lite@6.4.1(vega@6.2.0))(vega@6.2.0): - dependencies: - fast-json-patch: 3.1.1 - json-stringify-pretty-compact: 4.0.0 - semver: 7.7.3 - tslib: 2.8.1 - vega: 6.2.0 - vega-interpreter: 2.2.1 - vega-lite: 6.4.1(vega@6.2.0) - vega-schema-url-parser: 3.0.2 - vega-themes: 3.0.0(vega-lite@6.4.1(vega@6.2.0))(vega@6.2.0) - vega-tooltip: 1.0.0 - - vega-encode@5.1.0: - dependencies: - d3-array: 3.2.4 - d3-interpolate: 3.0.1 - vega-dataflow: 6.1.0 - vega-scale: 8.1.0 - vega-util: 2.1.0 - - vega-event-selector@4.0.0: {} - - vega-expression@6.1.0: - dependencies: - '@types/estree': 1.0.8 - vega-util: 2.1.0 - - vega-force@5.1.0: - dependencies: - d3-force: 3.0.0 - vega-dataflow: 6.1.0 - vega-util: 2.1.0 - - vega-format@2.1.0: - dependencies: - d3-array: 3.2.4 - d3-format: 3.1.0 - d3-time-format: 4.1.0 - vega-time: 3.1.0 - vega-util: 2.1.0 - - vega-functions@6.1.1: - dependencies: - d3-array: 3.2.4 - d3-color: 3.1.0 - d3-geo: 3.1.1 - vega-dataflow: 6.1.0 - vega-expression: 6.1.0 - vega-scale: 8.1.0 - vega-scenegraph: 5.1.0 - vega-selections: 6.1.2 - vega-statistics: 2.0.0 - vega-time: 3.1.0 - vega-util: 2.1.0 - - vega-geo@5.1.0: - dependencies: - d3-array: 3.2.4 - d3-color: 3.1.0 - d3-geo: 3.1.1 - vega-canvas: 2.0.0 - vega-dataflow: 6.1.0 - vega-projection: 2.1.0 - vega-statistics: 2.0.0 - vega-util: 2.1.0 - - vega-hierarchy@5.1.0: - dependencies: - d3-hierarchy: 3.1.2 - vega-dataflow: 6.1.0 - vega-util: 2.1.0 - - vega-interpreter@2.2.1: - dependencies: - vega-util: 2.1.0 - - vega-label@2.1.0: - dependencies: - vega-canvas: 2.0.0 - vega-dataflow: 6.1.0 - vega-scenegraph: 5.1.0 - vega-util: 2.1.0 - - vega-lite@6.4.1(vega@6.2.0): - dependencies: - json-stringify-pretty-compact: 4.0.0 - tslib: 2.8.1 - vega: 6.2.0 - vega-event-selector: 4.0.0 - vega-expression: 6.1.0 - vega-util: 2.1.0 - yargs: 18.0.0 - - vega-loader@5.1.0: - dependencies: - d3-dsv: 3.0.1 - topojson-client: 3.1.0 - vega-format: 2.1.0 - vega-util: 2.1.0 - - vega-parser@7.1.0: - dependencies: - vega-dataflow: 6.1.0 - vega-event-selector: 4.0.0 - vega-functions: 6.1.1 - vega-scale: 8.1.0 - vega-util: 2.1.0 - - vega-projection@2.1.0: - dependencies: - d3-geo: 3.1.1 - d3-geo-projection: 4.0.0 - vega-scale: 8.1.0 - - vega-regression@2.1.0: - dependencies: - d3-array: 3.2.4 - vega-dataflow: 6.1.0 - vega-statistics: 2.0.0 - vega-util: 2.1.0 - - vega-runtime@7.1.0: - dependencies: - vega-dataflow: 6.1.0 - vega-util: 2.1.0 - - vega-scale@8.1.0: - dependencies: - d3-array: 3.2.4 - d3-interpolate: 3.0.1 - d3-scale: 4.0.2 - d3-scale-chromatic: 3.1.0 - vega-time: 3.1.0 - vega-util: 2.1.0 - - vega-scenegraph@5.1.0: - dependencies: - d3-path: 3.1.0 - d3-shape: 3.2.0 - vega-canvas: 2.0.0 - vega-loader: 5.1.0 - vega-scale: 8.1.0 - vega-util: 2.1.0 - - vega-schema-url-parser@3.0.2: {} - - vega-selections@6.1.2: - dependencies: - d3-array: 3.2.4 - vega-expression: 6.1.0 - vega-util: 2.1.0 - - vega-statistics@2.0.0: - dependencies: - d3-array: 3.2.4 - - vega-themes@3.0.0(vega-lite@6.4.1(vega@6.2.0))(vega@6.2.0): - dependencies: - vega: 6.2.0 - vega-lite: 6.4.1(vega@6.2.0) - - vega-time@3.1.0: - dependencies: - d3-array: 3.2.4 - d3-time: 3.1.0 - vega-util: 2.1.0 - - vega-tooltip@1.0.0: - dependencies: - vega-util: 2.1.0 - - vega-transforms@5.1.0: - dependencies: - d3-array: 3.2.4 - vega-dataflow: 6.1.0 - vega-statistics: 2.0.0 - vega-time: 3.1.0 - vega-util: 2.1.0 - - vega-typings@2.1.0: - dependencies: - '@types/geojson': 7946.0.16 - vega-event-selector: 4.0.0 - vega-expression: 6.1.0 - vega-util: 2.1.0 - - vega-util@2.1.0: {} - - vega-view-transforms@5.1.0: - dependencies: - vega-dataflow: 6.1.0 - vega-scenegraph: 5.1.0 - vega-util: 2.1.0 - - vega-view@6.1.0: - dependencies: - d3-array: 3.2.4 - d3-timer: 3.0.1 - vega-dataflow: 6.1.0 - vega-format: 2.1.0 - vega-functions: 6.1.1 - vega-runtime: 7.1.0 - vega-scenegraph: 5.1.0 - vega-util: 2.1.0 - - vega-voronoi@5.1.0: - dependencies: - d3-delaunay: 6.0.4 - vega-dataflow: 6.1.0 - vega-util: 2.1.0 - - vega-wordcloud@5.1.0: - dependencies: - vega-canvas: 2.0.0 - vega-dataflow: 6.1.0 - vega-scale: 8.1.0 - vega-statistics: 2.0.0 - vega-util: 2.1.0 - - vega@6.2.0: - dependencies: - vega-crossfilter: 5.1.0 - vega-dataflow: 6.1.0 - vega-encode: 5.1.0 - vega-event-selector: 4.0.0 - vega-expression: 6.1.0 - vega-force: 5.1.0 - vega-format: 2.1.0 - vega-functions: 6.1.1 - vega-geo: 5.1.0 - vega-hierarchy: 5.1.0 - vega-label: 2.1.0 - vega-loader: 5.1.0 - vega-parser: 7.1.0 - vega-projection: 2.1.0 - vega-regression: 2.1.0 - vega-runtime: 7.1.0 - vega-scale: 8.1.0 - vega-scenegraph: 5.1.0 - vega-statistics: 2.0.0 - vega-time: 3.1.0 - vega-transforms: 5.1.0 - vega-typings: 2.1.0 - vega-util: 2.1.0 - vega-view: 6.1.0 - vega-view-transforms: 5.1.0 - vega-voronoi: 5.1.0 - vega-wordcloud: 5.1.0 - vite-dev-rpc@1.1.0(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): dependencies: birpc: 2.8.0 @@ -13064,7 +10895,7 @@ snapshots: - tsx - yaml - vite-plugin-checker@0.11.0(eslint@9.39.1(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.1.3(typescript@5.9.3)): + vite-plugin-checker@0.11.0(eslint@9.39.1(jiti@2.6.1))(optionator@0.9.4)(typescript@5.9.3)(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1))(vue-tsc@3.2.6(typescript@5.9.3)): dependencies: '@babel/code-frame': 7.27.1 chokidar: 4.0.3 @@ -13079,7 +10910,7 @@ snapshots: eslint: 9.39.1(jiti@2.6.1) optionator: 0.9.4 typescript: 5.9.3 - vue-tsc: 3.1.3(typescript@5.9.3) + vue-tsc: 3.2.6(typescript@5.9.3) vite-plugin-inspect@11.3.3(@nuxt/kit@3.20.1(magicast@0.3.5))(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): dependencies: @@ -13098,7 +10929,7 @@ snapshots: transitivePeerDependencies: - supports-color - vite-plugin-inspect@11.3.3(@nuxt/kit@4.2.0(magicast@0.5.1))(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): + vite-plugin-inspect@11.3.3(@nuxt/kit@4.2.1(magicast@0.5.1))(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)): dependencies: ansis: 4.2.0 debug: 4.4.3 @@ -13111,7 +10942,7 @@ snapshots: vite: 7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1) vite-dev-rpc: 1.1.0(vite@7.2.2(@types/node@24.10.0)(jiti@2.6.1)(sass@1.86.0)(terser@5.44.1)(tsx@4.20.6)(yaml@2.8.1)) optionalDependencies: - '@nuxt/kit': 4.2.0(magicast@0.5.1) + '@nuxt/kit': 4.2.1(magicast@0.5.1) transitivePeerDependencies: - supports-color @@ -13204,15 +11035,9 @@ snapshots: vscode-uri@3.1.0: {} - vt-pbf@3.1.3: - dependencies: - '@mapbox/point-geometry': 0.1.0 - '@mapbox/vector-tile': 1.3.1 - pbf: 3.3.0 - vue-bundle-renderer@2.2.0: dependencies: - ufo: 1.6.1 + ufo: 1.6.3 vue-component-type-helpers@2.2.12: {} @@ -13250,10 +11075,10 @@ snapshots: esbuild: 0.25.12 vue: 3.5.22(typescript@5.9.3) - vue-tsc@3.1.3(typescript@5.9.3): + vue-tsc@3.2.6(typescript@5.9.3): dependencies: - '@volar/typescript': 2.4.23 - '@vue/language-core': 3.1.3(typescript@5.9.3) + '@volar/typescript': 2.4.28 + '@vue/language-core': 3.2.6 typescript: 5.9.3 vue@3.5.22(typescript@5.9.3): @@ -13276,8 +11101,6 @@ snapshots: webpack-virtual-modules@0.6.2: {} - wgs84@0.0.0: {} - whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 @@ -13296,55 +11119,10 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 - 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.19 - - 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-typed-array@1.1.19: - 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 - which@4.0.0: - dependencies: - isexe: 3.1.1 - which@5.0.0: dependencies: isexe: 3.1.1 @@ -13368,12 +11146,6 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.2 - wrap-ansi@9.0.2: - dependencies: - ansi-styles: 6.2.3 - string-width: 7.2.0 - strip-ansi: 7.1.2 - ws@8.18.3: {} wsl-utils@0.1.0: @@ -13398,8 +11170,6 @@ snapshots: yargs-parser@21.1.1: {} - yargs-parser@22.0.0: {} - yargs@17.7.2: dependencies: cliui: 8.0.1 @@ -13410,15 +11180,6 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 - yargs@18.0.0: - dependencies: - cliui: 9.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - string-width: 7.2.0 - y18n: 5.0.8 - yargs-parser: 22.0.0 - yocto-queue@0.1.0: {} yocto-queue@1.2.1: {} diff --git a/src/module.ts b/src/module.ts index c84a92ee..f1458e9f 100644 --- a/src/module.ts +++ b/src/module.ts @@ -1,4 +1,4 @@ -import { defineNuxtModule, addPlugin, createResolver, addImportsDir, addServerHandler, addVitePlugin, addComponentsDir } from '@nuxt/kit' +import { defineNuxtModule, addPlugin, createResolver, addImportsDir, addServerHandler, addVitePlugin, addComponentsDir, installModule } from '@nuxt/kit' import { defu } from 'defu' import type { Tlv2RouteKey } from './runtime/route-keys' @@ -11,9 +11,7 @@ export interface ModuleOptions { // Route resolver routes?: Partial> // Proxy options - useProxy: boolean proxyBase?: string - apiBase?: string // Login gate loginGate?: boolean requireLogin?: boolean @@ -21,16 +19,6 @@ export interface ModuleOptions { protomapsApikey?: string nearmapsApikey?: string mixpanelApikey?: string - // Auth0 - auth0ClientId?: string - auth0Domain?: string - auth0Audience?: string - auth0Scope?: string - auth0RedirectUri?: string - auth0LogoutUri?: string - // Transfer Analyst options - transferAnalystReadOnlyFeedSelector?: boolean - transferAnalystGtfsRealtimeStopObservations?: boolean } export default defineNuxtModule({ @@ -42,38 +30,35 @@ export default defineNuxtModule({ nuxt: '^4.0.0' } }, - moduleDependencies: { - 'nuxt-csurf': { - defaults: { - addCsrfTokenToEventCtx: true - } - } - }, defaults: { bulma: '', - useProxy: false, loginGate: false, requireLogin: false, safelinkUtmSource: undefined, proxyBase: undefined, - apiBase: undefined, protomapsApikey: undefined, nearmapsApikey: undefined, - auth0ClientId: undefined, - auth0Domain: undefined, - auth0Audience: undefined, - auth0Scope: undefined, - auth0RedirectUri: undefined, - auth0LogoutUri: undefined, - transferAnalystReadOnlyFeedSelector: false, - transferAnalystGtfsRealtimeStopObservations: true }, async setup (options, nuxt) { // Create resolver to resolve relative paths const resolver = createResolver(import.meta.url) const resolveRuntimeModule = (path: string) => resolver.resolve('./runtime', path) - const useProxy = !!options.useProxy + // CSRF protection (required for all requests, including unauthenticated) + await installModule('nuxt-csurf', { addCsrfTokenToEventCtx: true }) + + // Auth via auth0-nuxt (server-side sessions with HTTP-only cookies). + // Only installed when clientId is configured — auth0-nuxt hard fails without it. + // When installed, a server middleware populates event.context.auth0Session + // so that useAuth0Session() can read it without importing auth0 directly. + const auth0ClientId = process.env.NUXT_AUTH0_CLIENT_ID || nuxt.options.runtimeConfig.auth0?.clientId + if (auth0ClientId) { + await installModule('@auth0/auth0-nuxt', {}) + addServerHandler({ + middleware: true, + handler: resolveRuntimeModule('server/middleware/auth0') + }) + } // Private runtime options (server-side only) // Nuxt 4 recommended pattern: merge at the nested key level @@ -90,50 +75,47 @@ export default defineNuxtModule({ // Public runtime options (available on both server and client) // Nuxt 4 recommended pattern: merge at the nested key level + const publicConfig: Record = { + safelinkUtmSource: options.safelinkUtmSource, + protomapsApikey: options.protomapsApikey, + nearmapsApikey: options.nearmapsApikey, + mixpanelApikey: options.mixpanelApikey, + loginGate: options.loginGate, + requireLogin: options.requireLogin, + routes: options.routes, + } + Object.assign(nuxt.options.runtimeConfig.public, defu(nuxt.options.runtimeConfig.public, { - tlv2: { - useProxy: useProxy, - safelinkUtmSource: options.safelinkUtmSource, - apiBase: { - default: options.apiBase, - stationEditor: '', - feedManagement: '', - }, - protomapsApikey: options.protomapsApikey, - nearmapsApikey: options.nearmapsApikey, - mixpanelApikey: options.mixpanelApikey, - loginGate: options.loginGate, - requireLogin: options.requireLogin, - routes: options.routes, - auth0Domain: options.auth0Domain, - auth0ClientId: options.auth0ClientId, - auth0RedirectUri: options.auth0RedirectUri, - auth0LogoutUri: options.auth0LogoutUri, - auth0Audience: options.auth0Audience, - auth0Scope: options.auth0Scope, - transferAnalystReadOnlyFeedSelector: options.transferAnalystReadOnlyFeedSelector, - transferAnalystGtfsRealtimeStopObservations: options.transferAnalystGtfsRealtimeStopObservations, - } + tlv2: publicConfig })) // Setup CSS nuxt.options.css.push(resolveRuntimeModule('assets/main.css')) nuxt.options.css.push('@mdi/font/css/materialdesignicons.css') - nuxt.options.css.push('maplibre-gl/dist/maplibre-gl.css') - // Setup plugins (run in order added) + // Setup plugins (run in order added — auth/CSRF must be before Apollo) + addPlugin(resolveRuntimeModule('plugins/auth.server')) + addPlugin(resolveRuntimeModule('plugins/csrf.client')) addPlugin(resolveRuntimeModule('plugins/apollo')) addPlugin(resolveRuntimeModule('plugins/mixpanel.client')) - addPlugin(resolveRuntimeModule('plugins/auth.client')) + + // Auth plugin (enriches user with roles from GraphQL) + addPlugin(resolveRuntimeModule('auth/plugin.client')) + addImportsDir(resolveRuntimeModule('composables')) - // Proxy options - if (useProxy) { - addServerHandler({ - route: '/api/v2/**', - handler: resolveRuntimeModule('plugins/proxy') - }) - } + // Session endpoint for ssr:false apps to fetch user claims client-side + addServerHandler({ + route: '/api/auth/session', + method: 'get', + handler: resolveRuntimeModule('server/api/auth/session.get') + }) + + // Proxy — routes /api/proxy/{backend}/... to the configured proxyBase for that backend + addServerHandler({ + route: '/api/proxy/**', + handler: resolveRuntimeModule('plugins/proxy') + }) // Add assets nuxt.hook('nitro:config', (nitroConfig) => { @@ -157,13 +139,6 @@ export default defineNuxtModule({ prefix: 't' }) - // Add apps (TlApps* components) - addComponentsDir({ - path: resolveRuntimeModule('apps'), - pathPrefix: true, - prefix: 'TlApps' - }) - // Nuxt 4: Transpile packages for SSR compatibility // These packages need transpilation because they: // - Ship as ESM but need to work in SSR/Node context diff --git a/src/runtime/apps/admin/entity-list.vue b/src/runtime/apps/admin/entity-list.vue deleted file mode 100644 index b59c8d84..00000000 --- a/src/runtime/apps/admin/entity-list.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - - - diff --git a/src/runtime/apps/admin/entrel-list.vue b/src/runtime/apps/admin/entrel-list.vue deleted file mode 100644 index ebc74c36..00000000 --- a/src/runtime/apps/admin/entrel-list.vue +++ /dev/null @@ -1,125 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/entrel-search.vue b/src/runtime/apps/admin/entrel-search.vue deleted file mode 100644 index 24bb3e63..00000000 --- a/src/runtime/apps/admin/entrel-search.vue +++ /dev/null @@ -1,163 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/feed-item.vue b/src/runtime/apps/admin/feed-item.vue deleted file mode 100644 index b514c917..00000000 --- a/src/runtime/apps/admin/feed-item.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/feed-version.vue b/src/runtime/apps/admin/feed-version.vue deleted file mode 100644 index 11aad0cb..00000000 --- a/src/runtime/apps/admin/feed-version.vue +++ /dev/null @@ -1,183 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/feed.vue b/src/runtime/apps/admin/feed.vue deleted file mode 100644 index f4d98890..00000000 --- a/src/runtime/apps/admin/feed.vue +++ /dev/null @@ -1,116 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/group-item.vue b/src/runtime/apps/admin/group-item.vue deleted file mode 100644 index b11fd009..00000000 --- a/src/runtime/apps/admin/group-item.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/group.vue b/src/runtime/apps/admin/group.vue deleted file mode 100644 index a157d094..00000000 --- a/src/runtime/apps/admin/group.vue +++ /dev/null @@ -1,277 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/index.ts b/src/runtime/apps/admin/index.ts deleted file mode 100644 index af227417..00000000 --- a/src/runtime/apps/admin/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -// Composables -export * from './useAdminApi' -export * from './useAuthz' diff --git a/src/runtime/apps/admin/input.vue b/src/runtime/apps/admin/input.vue deleted file mode 100644 index 6e353ab1..00000000 --- a/src/runtime/apps/admin/input.vue +++ /dev/null @@ -1,76 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/list-groups-inner.vue b/src/runtime/apps/admin/list-groups-inner.vue deleted file mode 100644 index 72691e31..00000000 --- a/src/runtime/apps/admin/list-groups-inner.vue +++ /dev/null @@ -1,52 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/list-groups-outer.vue b/src/runtime/apps/admin/list-groups-outer.vue deleted file mode 100644 index fe23f200..00000000 --- a/src/runtime/apps/admin/list-groups-outer.vue +++ /dev/null @@ -1,25 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/pages/admin-index.vue b/src/runtime/apps/admin/pages/admin-index.vue deleted file mode 100644 index c7477546..00000000 --- a/src/runtime/apps/admin/pages/admin-index.vue +++ /dev/null @@ -1,26 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/pages/group-index.vue b/src/runtime/apps/admin/pages/group-index.vue deleted file mode 100644 index 1e74e886..00000000 --- a/src/runtime/apps/admin/pages/group-index.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/pages/groups-index.vue b/src/runtime/apps/admin/pages/groups-index.vue deleted file mode 100644 index 0541cedc..00000000 --- a/src/runtime/apps/admin/pages/groups-index.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/pages/tenant-index.vue b/src/runtime/apps/admin/pages/tenant-index.vue deleted file mode 100644 index a64114f2..00000000 --- a/src/runtime/apps/admin/pages/tenant-index.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/pages/tenants-index.vue b/src/runtime/apps/admin/pages/tenants-index.vue deleted file mode 100644 index 352667df..00000000 --- a/src/runtime/apps/admin/pages/tenants-index.vue +++ /dev/null @@ -1,50 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/perm-list.vue b/src/runtime/apps/admin/perm-list.vue deleted file mode 100644 index 33aa835e..00000000 --- a/src/runtime/apps/admin/perm-list.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/tenant-item.vue b/src/runtime/apps/admin/tenant-item.vue deleted file mode 100644 index f8385aad..00000000 --- a/src/runtime/apps/admin/tenant-item.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - - - diff --git a/src/runtime/apps/admin/tenant.vue b/src/runtime/apps/admin/tenant.vue deleted file mode 100644 index 6eba83d2..00000000 --- a/src/runtime/apps/admin/tenant.vue +++ /dev/null @@ -1,218 +0,0 @@ - - - diff --git a/src/runtime/apps/admin/useAdminApi.ts b/src/runtime/apps/admin/useAdminApi.ts deleted file mode 100644 index 831f35ab..00000000 --- a/src/runtime/apps/admin/useAdminApi.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { useFetch } from '#imports' -import type { UseFetchOptions, AsyncData } from 'nuxt/app' -import type { FetchError } from 'ofetch' -import { useApiEndpoint } from '../../composables/useApiEndpoint' -import { useAuthHeaders } from '../../composables/useAuthHeaders' - -export function useAdminFetch (path: string | (() => string), options: UseFetchOptions = {}): AsyncData { - const apiEndpoint = useApiEndpoint('', 'feedManagement') - - return useFetch(path, { - baseURL: apiEndpoint + '/admin', - onRequest: async ({ options }) => { - const authHeaders = await useAuthHeaders() - options.headers = { - ...options.headers, - ...authHeaders - } - }, - ...options - }) as AsyncData -} - -export async function fetchAdmin (path: string, options: any = {}) { - const apiEndpoint = useApiEndpoint('', 'feedManagement') - const authHeaders = await useAuthHeaders() - - return $fetch(path, { - baseURL: apiEndpoint + '/admin', - credentials: 'same-origin', - headers: { - ...options.headers, - ...authHeaders - }, - ...options - }) -} diff --git a/src/runtime/apps/admin/useAuthz.ts b/src/runtime/apps/admin/useAuthz.ts deleted file mode 100644 index f1be8cd8..00000000 --- a/src/runtime/apps/admin/useAuthz.ts +++ /dev/null @@ -1,30 +0,0 @@ -export const OBJECTTYPES: Record = { - empty_object: 0, - tenant: 1, - org: 2, - feed: 3, - feed_version: 4, - user: 5 -} - -export const RELATIONS: Record = { - empty_relation: 0, - admin: 1, - member: 2, - manager: 3, - viewer: 4, - editor: 5, - parent: 6 -} - -export function useAuthz () { - const getObjectType = (v: string) => OBJECTTYPES[v] - const getRelation = (v: string) => RELATIONS[v] - - return { - OBJECTTYPES, - RELATIONS, - getObjectType, - getRelation - } -} diff --git a/src/runtime/apps/admin/user-item.vue b/src/runtime/apps/admin/user-item.vue deleted file mode 100644 index bc7768a7..00000000 --- a/src/runtime/apps/admin/user-item.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/basemap-control.vue b/src/runtime/apps/stations/basemap-control.vue deleted file mode 100644 index 206cb065..00000000 --- a/src/runtime/apps/stations/basemap-control.vue +++ /dev/null @@ -1,36 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/basemaps.ts b/src/runtime/apps/stations/basemaps.ts deleted file mode 100644 index 3a7e184e..00000000 --- a/src/runtime/apps/stations/basemaps.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { PathwayModeIcon } from '../../lib/pathways/pathway-icons' - -export const PeliasIcons: Record = { - marker: { - icon: 'marker', - label: 'marker' - } -} - -export const LocationTypes = new Map([ - [0, 'Platform'], - [1, 'Station'], - [2, 'Entrance/Exit'], - [3, 'Node'], - [4, 'Boarding area'] -]) diff --git a/src/runtime/apps/stations/composables/useFeed.ts b/src/runtime/apps/stations/composables/useFeed.ts deleted file mode 100644 index c0a61819..00000000 --- a/src/runtime/apps/stations/composables/useFeed.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { computed, type Ref, type ComputedRef } from 'vue' -import { gql } from 'graphql-tag' -import type { DocumentNode } from 'graphql' -import { useQuery } from '@vue/apollo-composable' -import { useToastNotification } from '../../../composables/useToastNotification' -import type { FeedQueryResponse } from '../types' - -const currentFeedsQuery: DocumentNode = gql` -query currentFeeds ($feed_onestop_id: String, $feed_version_ids: [Int!]) { - feeds(limit:1000, where: {onestop_id: $feed_onestop_id, spec: GTFS}) { - id - name - onestop_id - feed_versions(limit: 10, where: {ids: $feed_version_ids}) { - file - sha1 - name - description - id - stations: stops(limit:1000, where:{location_type:1}) { - feed_version { - id - } - station_id: stop_id - stationName: stop_name - geometry - } - } - } -} -` - -export interface UseFeedOptions { - feedKey?: Ref - feedVersionKey?: Ref - clientId?: string -} - -interface UseFeedReturn { - feeds: ComputedRef - loading: Ref - error: Ref - feed: ComputedRef - feedVersion: ComputedRef - feedName: ComputedRef - feedVersionName: ComputedRef - stations: ComputedRef -} - -export function useFeed (options: UseFeedOptions): UseFeedReturn { - const { feedKey, feedVersionKey, clientId } = options - const { showToast } = useToastNotification() - - // Apollo query using useQuery from @vue/apollo-composable - const { result, loading, error, onError } = useQuery( - currentFeedsQuery, - () => ({ - feed_onestop_id: feedKey?.value || undefined, - feed_version_ids: feedVersionKey?.value ? [feedVersionKey.value] : null - }), - () => ({ - ...(clientId && { clientId }), - fetchPolicy: 'cache-and-network' - }) - ) - - // Handle errors - onError((err) => { - const msg = err.message || JSON.stringify(err) - showToast(`Error: ${msg}`, 'danger') - }) - - // Reactive state - const feeds = computed(() => result.value?.feeds || []) - - // Computed properties - const feed = computed(() => { - return (feeds.value && feeds.value.length === 1) ? feeds.value[0] : null - }) - - const feedVersion = computed(() => { - if (feed.value?.feed_versions && feed.value.feed_versions.length > 0) { - return feed.value.feed_versions[0] ?? feedVersionKey?.value - } - return feedVersionKey?.value - }) - - const feedName = computed(() => { - return feed.value ? (feed.value.name || feed.value.onestop_id) : feedKey?.value - }) - - const feedVersionName = computed(() => { - return String((typeof feedVersion.value === 'string' ? null : feedVersion.value?.id) || feedVersionKey?.value || '').substr(0, 8) - }) - - const stations = computed(() => { - return (typeof feedVersion.value !== 'string' && feedVersion.value) ? feedVersion.value.stations : null - }) - - return { - // Reactive state - feeds, - loading, - error, - - // Computed properties - feed, - feedVersion, - feedName, - feedVersionName, - stations - } -} diff --git a/src/runtime/apps/stations/composables/usePathwayEditorKeyboard.ts b/src/runtime/apps/stations/composables/usePathwayEditorKeyboard.ts deleted file mode 100644 index 83d3978e..00000000 --- a/src/runtime/apps/stations/composables/usePathwayEditorKeyboard.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { onMounted, onUnmounted } from 'vue' - -interface KeyboardActions { - onEscape: () => void - onV: () => void - onE: () => void - onN: () => void - onF: () => void - onS: () => void - onP: () => void - onC: () => void -} - -export function usePathwayEditorKeyboard (actions: KeyboardActions) { - function handleKeyDown (event: KeyboardEvent) { - const tag = ((event.target as HTMLElement)?.tagName || '').toLowerCase() - if (['input', 'textarea', 'select'].includes(tag) || (event.target as HTMLElement)?.isContentEditable) { - return - } - if (event.metaKey || event.ctrlKey || event.altKey) { - return - } - switch (event.key) { - case 'Escape': - actions.onEscape() - break - case 'v': - case 'V': - actions.onV() - break - case 'e': - case 'E': - actions.onE() - break - case 'n': - case 'N': - actions.onN() - break - case 'f': - case 'F': - actions.onF() - break - case 's': - case 'S': - actions.onS() - break - case 'p': - case 'P': - actions.onP() - break - case 'c': - case 'C': - actions.onC() - break - } - } - - onMounted(() => { - window.addEventListener('keydown', handleKeyDown) - }) - - onUnmounted(() => { - window.removeEventListener('keydown', handleKeyDown) - }) -} diff --git a/src/runtime/apps/stations/composables/usePathwaySelection.spec.ts b/src/runtime/apps/stations/composables/usePathwaySelection.spec.ts deleted file mode 100644 index fb2bb7ec..00000000 --- a/src/runtime/apps/stations/composables/usePathwaySelection.spec.ts +++ /dev/null @@ -1,462 +0,0 @@ -import { describe, test, expect, beforeEach } from 'vitest' -import { ref, nextTick } from 'vue' -import { Stop, Pathway, Station } from '../station' -import { usePathwaySelection } from './usePathwaySelection' -import type { StopData, PathwayData } from '../types' - -// ─── Factories ──────────────────────────────────────────────────────────────── - -function makeStop (id: number, overrides: Partial = {}): Stop { - return new Stop({ - id, - stop_id: `stop-${id}`, - stop_name: `Stop ${id}`, - location_type: 3, - geometry: { type: 'Point', coordinates: [0, 0] }, - pathways_from_stop: [], - pathways_to_stop: [], - ...overrides - }) -} - -let nextPwId = 0 - -function connectStops (fromStop: Stop, toStop: Stop, overrides: Partial = {}): Pathway { - const id = ++nextPwId - const pw = new Pathway({ - id, - pathway_id: `pw-${id}`, - pathway_mode: 1, - is_bidirectional: 1, - from_stop: { id: fromStop.id }, - to_stop: { id: toStop.id }, - ...overrides - }) - fromStop.pathways_from_stop.push(pw) - toStop.pathways_to_stop.push(pw) - return pw -} - -function makeFilledStation (stops: Stop[]): Station { - const st = new Station({ - id: 100, - stop_id: 'station', - stop_name: 'Station', - location_type: 1, - geometry: { type: 'Point', coordinates: [0, 0] } - }) - st.addStops(stops) - return st -} - -// ─── Setup helper ───────────────────────────────────────────────────────────── - -function setup (stops: Stop[] = []) { - const stationRef = ref(makeFilledStation(stops)) - const selectedProfile = ref('Pathways: Default') - const toasts: string[] = [] - const sel = usePathwaySelection(stationRef, selectedProfile, msg => toasts.push(msg)) - return { ...sel, stationRef, toasts } -} - -// ─── Tests ──────────────────────────────────────────────────────────────────── - -describe('usePathwaySelection', () => { - beforeEach(() => { nextPwId = 0 }) - - // ── Initial state ────────────────────────────────────────────────────────── - - describe('initial state', () => { - test('selectMode is "select"', () => { - const { selectMode } = setup() - expect(selectMode.value).toBe('select') - }) - - test('selectedStops and selectedPathways are empty', () => { - const { selectedStops, selectedPathways } = setup() - expect(selectedStops.value).toHaveLength(0) - expect(selectedPathways.value).toHaveLength(0) - }) - - test('selectedStop and selectedSource are null', () => { - const { selectedStop, selectedSource } = setup() - expect(selectedStop.value).toBeNull() - expect(selectedSource.value).toBeNull() - }) - }) - - // ── selectStop ───────────────────────────────────────────────────────────── - - describe('selectStop', () => { - test('null clears selection and resets mode to select', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1)]) - selectStop(1) - selectStop(null) - expect(selectMode.value).toBe('select') - expect(selectedStops.value).toHaveLength(0) - }) - - test('unknown ID is a no-op', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1)]) - selectStop(999) - expect(selectMode.value).toBe('select') - expect(selectedStops.value).toHaveLength(0) - }) - - test('first click enters edit-node mode with one stop', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1)]) - selectStop(1) - expect(selectMode.value).toBe('edit-node') - expect(selectedStops.value).toHaveLength(1) - expect(selectedStops.value[0]!.id).toBe(1) - }) - - test('second click on a different stop enters add-pathway mode with two stops', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1), makeStop(2)]) - selectStop(1) - selectStop(2) - expect(selectMode.value).toBe('add-pathway') - expect(selectedStops.value).toHaveLength(2) - expect(selectedStops.value[0]!.id).toBe(1) - expect(selectedStops.value[1]!.id).toBe(2) - }) - - test('second click on the same stop deselects and resets to select mode', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1)]) - selectStop(1) - selectStop(1) - expect(selectMode.value).toBe('select') - expect(selectedStops.value).toHaveLength(0) - }) - - test('selecting a stop clears any selected pathways', () => { - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - const { selectStop, selectPathway, selectedPathways } = setup([a, b]) - selectPathway(a.pathways_from_stop[0]!.id!) - expect(selectedPathways.value).toHaveLength(1) - selectStop(1) - expect(selectedPathways.value).toHaveLength(0) - }) - - describe('find-route mode', () => { - test('second click replaces slot 2 while preserving slot 1', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1), makeStop(2), makeStop(3)]) - selectStop(1) - selectStop(2) - selectMode.value = 'find-route' - selectStop(3) - expect(selectedStops.value[0]!.id).toBe(1) - expect(selectedStops.value[1]!.id).toBe(3) - }) - - test('clicking the current last stop clears the selection', () => { - const { selectStop, selectMode, selectedStops } = setup([makeStop(1), makeStop(2)]) - selectStop(1) - selectStop(2) - selectMode.value = 'find-route' - selectStop(2) - expect(selectedStops.value).toHaveLength(0) - }) - }) - }) - - // ── selectPathway ────────────────────────────────────────────────────────── - - describe('selectPathway', () => { - test('null clears selection and resets mode to select', () => { - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - const { selectPathway, selectMode, selectedPathways } = setup([a, b]) - selectPathway(a.pathways_from_stop[0]!.id!) - selectPathway(null) - expect(selectMode.value).toBe('select') - expect(selectedPathways.value).toHaveLength(0) - }) - - test('valid pathway enters edit-pathway mode', () => { - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b) - const { selectPathway, selectMode, selectedPathways } = setup([a, b]) - selectPathway(pw.id!) - expect(selectMode.value).toBe('edit-pathway') - expect(selectedPathways.value).toHaveLength(1) - expect(selectedPathways.value[0]!.id).toBe(pw.id) - }) - - test('clicking the same pathway a second time deselects it', () => { - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b) - const { selectPathway, selectMode, selectedPathways } = setup([a, b]) - selectPathway(pw.id!) - selectPathway(pw.id!) - expect(selectMode.value).toBe('select') - expect(selectedPathways.value).toHaveLength(0) - }) - - test('selecting a pathway clears any selected stops', () => { - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b) - const { selectStop, selectPathway, selectedStops } = setup([a, b]) - selectStop(1) - expect(selectedStops.value).toHaveLength(1) - selectPathway(pw.id!) - expect(selectedStops.value).toHaveLength(0) - }) - - test('unknown ID clears selection and resets mode to select', () => { - const { selectPathway, selectMode } = setup([makeStop(1)]) - selectPathway(999) - expect(selectMode.value).toBe('select') - }) - }) - - // ── selectPath ───────────────────────────────────────────────────────────── - - describe('selectPath', () => { - test('enters find-route mode with the two given stops', () => { - const { selectPath, selectMode, selectedStops } = setup([makeStop(1), makeStop(2)]) - selectPath(1, 2) - expect(selectMode.value).toBe('find-route') - expect(selectedStops.value[0]!.id).toBe(1) - expect(selectedStops.value[1]!.id).toBe(2) - }) - - test('is a no-op when station is null', () => { - const stationRef = ref(null) - const sel = usePathwaySelection(stationRef, ref('Pathways: Default'), () => {}) - sel.selectPath(1, 2) - expect(sel.selectMode.value).toBe('select') - expect(sel.selectedStops.value).toHaveLength(0) - }) - }) - - // ── unselectAll ──────────────────────────────────────────────────────────── - - describe('unselectAll', () => { - test('resets all state to initial defaults', () => { - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - const { selectStop, selectPoint, unselectAll, - selectMode, selectedStops, selectedPathways, - selectedPoint, hoverStopId, hoverPathwayId, lastFilterApplied } = setup([a, b]) - - selectStop(1) - selectPoint({ lng: 1, lat: 2 }) - hoverStopId.value = 5 - hoverPathwayId.value = 7 - lastFilterApplied.value = 'some filter' - - unselectAll() - - expect(selectMode.value).toBe('select') - expect(selectedStops.value).toHaveLength(0) - expect(selectedPathways.value).toHaveLength(0) - expect(selectedPoint.value).toBeNull() - expect(hoverStopId.value).toBeNull() - expect(hoverPathwayId.value).toBeNull() - expect(lastFilterApplied.value).toBe('') - }) - }) - - // ── add-node mode watch ──────────────────────────────────────────────────── - - describe('add-node mode watch', () => { - test('entering add-node mode clears selected stops and pathways', async () => { - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - const { selectStop, selectMode, selectedStops, selectedPathways } = setup([a, b]) - - selectStop(1) - expect(selectedStops.value).toHaveLength(1) - - selectMode.value = 'add-node' - await nextTick() - - expect(selectedStops.value).toHaveLength(0) - expect(selectedPathways.value).toHaveLength(0) - }) - }) - - // ── selectedStop computed ────────────────────────────────────────────────── - - describe('selectedStop computed', () => { - test('is null when nothing is selected', () => { - const { selectedStop } = setup([makeStop(1)]) - expect(selectedStop.value).toBeNull() - }) - - test('is the selected stop when one is selected', () => { - const { selectStop, selectedStop } = setup([makeStop(1)]) - selectStop(1) - expect(selectedStop.value?.id).toBe(1) - }) - - test('is the second stop (destination) when two are selected', () => { - const { selectStop, selectedStop } = setup([makeStop(1), makeStop(2)]) - selectStop(1) - selectStop(2) - expect(selectedStop.value?.id).toBe(2) - }) - }) - - // ── selectedSource computed ──────────────────────────────────────────────── - - describe('selectedSource computed', () => { - test('is null when fewer than 2 stops are selected', () => { - const { selectStop, selectedSource } = setup([makeStop(1)]) - selectStop(1) - expect(selectedSource.value).toBeNull() - }) - - test('is the first stop (source) when two stops are selected', () => { - const { selectStop, selectedSource } = setup([makeStop(1), makeStop(2)]) - selectStop(1) - selectStop(2) - expect(selectedSource.value?.id).toBe(1) - }) - }) - - // ── selectedPath computed ────────────────────────────────────────────────── - - describe('selectedPath computed', () => { - test('is null when not in find-route mode', () => { - const { selectedPath } = setup([makeStop(1), makeStop(2)]) - expect(selectedPath.value).toBeNull() - }) - - test('is null when fewer than 2 stops are selected', () => { - const { selectStop, selectMode, selectedPath } = setup([makeStop(1)]) - selectStop(1) - selectMode.value = 'find-route' - expect(selectedPath.value).toBeNull() - }) - - test('returns route edges for a connected station', () => { - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b, { traversal_time: 30 }) - const { selectPath, selectedPath } = setup([a, b]) - selectPath(1, 2) - expect(selectedPath.value).toHaveLength(1) - expect(selectedPath.value![0]!.pathway.id).toBe(pw.id) - expect(selectedPath.value![0]!.cost).toBe(30) - }) - - test('returns an empty array when stops are not connected', () => { - const { selectPath, selectedPath } = setup([makeStop(1), makeStop(2)]) - selectPath(1, 2) - expect(selectedPath.value).toHaveLength(0) - }) - }) - - // ── pathwayIndex computed ────────────────────────────────────────────────── - - describe('pathwayIndex computed', () => { - test('maps pathway IDs to their Pathway objects', () => { - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b) - const { pathwayIndex } = setup([a, b]) - expect(pathwayIndex.value[pw.id!]).toBeDefined() - expect(pathwayIndex.value[pw.id!]!.id).toBe(pw.id) - }) - - test('is empty when the station has no pathways', () => { - const { pathwayIndex } = setup([makeStop(1)]) - expect(Object.keys(pathwayIndex.value)).toHaveLength(0) - }) - }) - - // ── filter methods ───────────────────────────────────────────────────────── - - describe('filter methods', () => { - test('selectLocationTypes selects stops matching that type', () => { - const stops = [ - makeStop(1, { location_type: 0 }), - makeStop(2, { location_type: 0 }), - makeStop(3, { location_type: 2 }) - ] - const { selectLocationTypes, selectedStops } = setup(stops) - selectLocationTypes(0) - expect(selectedStops.value).toHaveLength(2) - expect(selectedStops.value.every(s => s.location_type === 0)).toBe(true) - }) - - test('selectLocationTypes sets lastFilterApplied', () => { - const { selectLocationTypes, lastFilterApplied } = setup([makeStop(1, { location_type: 0 })]) - selectLocationTypes(0) - expect(lastFilterApplied.value).toBe('Stops: Platform') - }) - - test('selectPathwayModes selects pathways of that mode', () => { - const a = makeStop(1) - const b = makeStop(2) - const c = makeStop(3) - connectStops(a, b, { pathway_mode: 1 }) - connectStops(b, c, { pathway_mode: 2 }) - const { selectPathwayModes, selectedPathways } = setup([a, b, c]) - selectPathwayModes(2) - expect(selectedPathways.value).toHaveLength(1) - expect(selectedPathways.value[0]!.pathway_mode).toBe(2) - }) - - test('selectStopsWithAssociations selects stops that have an external reference', () => { - const stops = [ - makeStop(1, { external_reference: { target_feed_onestop_id: 'f', target_stop_id: 'ext-1' } }), - makeStop(2), - makeStop(3, { external_reference: { target_feed_onestop_id: 'f', target_stop_id: 'ext-3' } }) - ] - const { selectStopsWithAssociations, selectedStops } = setup(stops) - selectStopsWithAssociations() - expect(selectedStops.value.map(s => s.id)).toEqual(expect.arrayContaining([1, 3])) - expect(selectedStops.value).toHaveLength(2) - }) - - test('selectPathwaysOneway selects non-bidirectional pathways', () => { - const a = makeStop(1) - const b = makeStop(2) - const c = makeStop(3) - connectStops(a, b, { is_bidirectional: 0 }) - connectStops(b, c, { is_bidirectional: 1 }) - const { selectPathwaysOneway, selectedPathways } = setup([a, b, c]) - selectPathwaysOneway() - expect(selectedPathways.value).toHaveLength(1) - expect(selectedPathways.value[0]!.is_bidirectional).toBe(0) - }) - - test('selectPathwaysBidirectional selects bidirectional pathways', () => { - const a = makeStop(1) - const b = makeStop(2) - const c = makeStop(3) - connectStops(a, b, { is_bidirectional: 1 }) - connectStops(b, c, { is_bidirectional: 0 }) - const { selectPathwaysBidirectional, selectedPathways } = setup([a, b, c]) - selectPathwaysBidirectional() - expect(selectedPathways.value).toHaveLength(1) - expect(selectedPathways.value[0]!.is_bidirectional).toBe(1) - }) - - test('filter resets selectMode to "select"', () => { - const { selectStop, selectLocationTypes, selectMode } = setup([makeStop(1, { location_type: 0 })]) - selectStop(1) - expect(selectMode.value).toBe('edit-node') - selectLocationTypes(0) - expect(selectMode.value).toBe('select') - }) - - test('filter calls showToast when no results are found', () => { - const { selectLocationTypes, toasts } = setup([makeStop(1, { location_type: 3 })]) - selectLocationTypes(0) // no platforms exist - expect(toasts).toHaveLength(1) - expect(toasts[0]).toMatch(/no.*platform/i) - }) - }) -}) diff --git a/src/runtime/apps/stations/composables/usePathwaySelection.ts b/src/runtime/apps/stations/composables/usePathwaySelection.ts deleted file mode 100644 index f724f7fa..00000000 --- a/src/runtime/apps/stations/composables/usePathwaySelection.ts +++ /dev/null @@ -1,315 +0,0 @@ -import { ref, computed, watch, type Ref } from 'vue' -import { Pathway } from '../station' -import type { Station, Stop } from '../station' -import { Profiles } from '../../../lib/pathways/graph' -import { computeFilterCounts } from '../station-pathways-filter-counts' -import { LocationTypes } from '../basemaps' -import { PathwayModes } from '../../../lib/pathways/pathway-icons' - -type SelectMode = 'select' | 'add-node' | 'add-pathway' | 'find-route' | 'edit-node' | 'edit-pathway' | 'export' -type LngLat = { lng: number, lat: number } - -export function usePathwaySelection ( - station: Ref, - selectedProfile: Ref, - showToast: (msg: string) => void -) { - const selectMode = ref('select') - const selectedStops = ref([]) - const selectedPathways = ref([]) - const selectedPoint = ref(null) - const hoverStopId = ref(null) - const hoverPathwayId = ref(null) - const lastFilterApplied = ref('') - - // Clear selection when entering add-node mode - watch(selectMode, (mode) => { - if (mode === 'add-node') { - selectedStops.value = [] - selectedPathways.value = [] - } - }) - - const pathwayIndex = computed>(() => { - const pwi: Record = {} - for (const pw of (station.value?.pathways || [])) { - if (pw.id != null) { - pwi[pw.id] = pw - } - } - return pwi - }) - - const filterCounts = computed(() => { - return computeFilterCounts(station.value?.stops || [], station.value?.pathways || []) - }) - - const selectedStop = computed(() => { - const stops = selectedStops.value - return stops.length > 0 ? (stops[stops.length - 1] ?? null) : null - }) - - const selectedSource = computed(() => { - const stops = selectedStops.value - return stops.length === 2 ? (stops[0] ?? null) : null - }) - - const selectedPath = computed(() => { - if (selectMode.value !== 'find-route' || selectedStops.value.length < 2 || !station.value) { - return null - } - const from = selectedStops.value[0] - const to = selectedStops.value[1] - if (!from?.id || !to?.id) { return null } - const p = station.value.findRoute( - from.id, - to.id, - Profiles[selectedProfile.value] - ) - if (!p) { - return null - } - const edges: { cost: number, pathway: Pathway }[] = [] - for (const edge of (p.edges || [])) { - if (edge.pathway_id) { - const pathway = pathwayIndex.value[edge.pathway_id] - if (pathway) { - edges.push({ cost: edge.cost, pathway }) - } - } else if (edge.from_stop_id && edge.to_stop_id) { - const fromStop = station.value.getStop(edge.from_stop_id) - const toStop = station.value.getStop(edge.to_stop_id) - if (fromStop && toStop) { - edges.push({ - cost: edge.cost, - pathway: new Pathway({ pathway_mode: 1, is_bidirectional: 1, from_stop: fromStop, to_stop: toStop }) - }) - } - } - } - return edges - }) - - function selectStop (stopId: number | null) { - if (stopId === null) { - selectedStops.value = [] - selectMode.value = 'select' - return - } - const cur = station.value?.getStop(stopId) - const prev = selectedStops.value.length > 0 ? selectedStops.value[selectedStops.value.length - 1] : null - if (!cur) { - return - } - // find-route is sticky on first selected stop - if (prev && selectMode.value === 'find-route') { - if (prev === cur) { - selectedStops.value = [] - return - } - selectedStops.value = [selectedStops.value[0]!, cur] - return - } - selectedPathways.value = [] - if (prev) { - if (prev === cur) { - selectedStops.value = [] - selectMode.value = 'select' - } else { - selectedStops.value = [prev, cur] - selectMode.value = 'add-pathway' - } - } else { - selectedStops.value = [cur] - selectMode.value = 'edit-node' - } - } - - function selectPathway (pwid: number | null) { - if (pwid === null) { - selectedPathways.value = [] - selectMode.value = 'select' - return - } - const cur = pathwayIndex.value[pwid] ?? null - const prev = selectedPathways.value.length > 0 ? (selectedPathways.value[selectedPathways.value.length - 1] ?? null) : null - selectedStops.value = [] - if (!cur || prev === cur) { - selectedPathways.value = [] - selectMode.value = 'select' - } else { - selectedPathways.value = [cur] - selectMode.value = 'edit-pathway' - } - } - - function selectPath (fromId: number, toId: number) { - if (!station.value) { return } - const from = station.value.getStop(fromId) - const to = station.value.getStop(toId) - if (from && to) { - selectMode.value = 'find-route' - selectedStops.value = [from, to] - } - } - - function selectPoint (ll: LngLat) { - selectedPoint.value = ll - } - - function unselectAll () { - selectedStops.value = [] - selectedPathways.value = [] - selectedPoint.value = null - lastFilterApplied.value = '' - selectMode.value = 'select' - hoverStopId.value = null - hoverPathwayId.value = null - } - - function applyFilter ( - filterFn: (item: Stop | Pathway) => boolean, - filterLabel: string, - notFoundMessage: string, - target: 'stops' | 'pathways' = 'stops' - ) { - const source = target === 'stops' ? (station.value?.stops || []) : (station.value?.pathways || []) - const results = source.filter(filterFn as (item: Stop | Pathway) => boolean) - if (target === 'stops') { - selectedStops.value = results as Stop[] - } else { - selectedPathways.value = results as Pathway[] - } - lastFilterApplied.value = filterLabel - selectMode.value = 'select' - if (results.length === 0) { - showToast(notFoundMessage) - } - } - - function selectLocationTypes (stype: number) { - const label = LocationTypes.get(stype) || String(stype) - applyFilter( - s => (s as Stop).location_type === stype, - `Stops: ${label}`, - `No ${label} stops found` - ) - } - - function selectPathwayModes (stype: number) { - const label = PathwayModes.get(stype) || String(stype) - applyFilter( - s => (s as Pathway).pathway_mode === stype, - `Pathways: ${label}`, - `No ${label} pathways found`, - 'pathways' - ) - } - - function selectStopsWithAssociations () { - applyFilter( - s => !!(s as Stop).external_reference?.target_stop_id, - 'Stops with associations', - 'No stops with associations found' - ) - } - - function selectStopsPlatformsWithoutAssociations () { - applyFilter( - s => (s as Stop).location_type === 0 && !(s as Stop).external_reference, - 'Platforms without associations', - 'No platforms without associations found' - ) - } - - function selectStopsEntrancesWithoutAssociations () { - applyFilter( - s => (s as Stop).location_type === 2 && !(s as Stop).external_reference, - 'Entrances without associations', - 'No entrances without associations found' - ) - } - - function selectStopsWithPairedPathways () { - const pairedPathways = new Map() - applyFilter( - (s) => { - const stop = s as Stop - const pwKeys: string[] = [] - for (const pw of (stop.pathways_from_stop || [])) { - pwKeys.push(`${pw.from_stop.id}-${pw.to_stop.id}`) - } - for (const pw of (stop.pathways_to_stop || [])) { - pwKeys.push(`${pw.to_stop.id}-${pw.from_stop.id}`) - } - let matched = false - for (const pwkey of pwKeys) { - if (pairedPathways.has(pwkey)) { - matched = true - } - pairedPathways.set(pwkey, true) - } - return matched - }, - 'Stops with paired pathways', - 'No stops with paired pathways found' - ) - } - - function selectPathwaysWithPairs () { - const allKeys = new Set((station.value?.pathways || []).map(p => `${p.from_stop.id}-${p.to_stop.id}`)) - applyFilter( - s => allKeys.has(`${(s as Pathway).to_stop.id}-${(s as Pathway).from_stop.id}`), - 'Pathways with pairs', - 'No pathways with pairs found', - 'pathways' - ) - } - - function selectPathwaysOneway () { - applyFilter( - s => (s as Pathway).is_bidirectional === 0, - 'One-directional pathways', - 'No one-directional pathways found', - 'pathways' - ) - } - - function selectPathwaysBidirectional () { - applyFilter( - s => (s as Pathway).is_bidirectional === 1, - 'Bi-directional pathways', - 'No bi-directional pathways found', - 'pathways' - ) - } - - return { - selectMode, - selectedStops, - selectedPathways, - selectedPoint, - hoverStopId, - hoverPathwayId, - lastFilterApplied, - pathwayIndex, - filterCounts, - selectedStop, - selectedSource, - selectedPath, - selectStop, - selectPathway, - selectPath, - selectPoint, - unselectAll, - selectLocationTypes, - selectPathwayModes, - selectStopsWithAssociations, - selectStopsPlatformsWithoutAssociations, - selectStopsEntrancesWithoutAssociations, - selectStopsWithPairedPathways, - selectPathwaysWithPairs, - selectPathwaysOneway, - selectPathwaysBidirectional - } -} diff --git a/src/runtime/apps/stations/composables/useStation.ts b/src/runtime/apps/stations/composables/useStation.ts deleted file mode 100644 index 265f4e9b..00000000 --- a/src/runtime/apps/stations/composables/useStation.ts +++ /dev/null @@ -1,556 +0,0 @@ -import { ref, computed, watch, type Ref } from 'vue' -import { gql } from 'graphql-tag' -import { useQuery, useApolloClient } from '@vue/apollo-composable' -import { useToastNotification } from '../../../composables/useToastNotification' -import { symmetricDifference } from '../../../lib/util/sets' -import type { Level, Pathway } from '../station' -import { Stop, Station, stationQuery, stationStopQuery, mapLevelKeyFn } from '../station' -import type { FeedQueryResponse, StationQueryResponse, StopsQueryResponse } from '../types' - -const currentFeedsQuery = gql` -query currentFeeds ($feed_onestop_id: String, $feed_version_ids: [Int!]) { - feeds(limit:1000, where: {onestop_id: $feed_onestop_id, spec: GTFS}) { - id - name - onestop_id - feed_versions(limit: 10, where: {ids: $feed_version_ids}) { - file - sha1 - id - agencies { - id - agency_id - agency_name - } - stations: stops(limit:1000, where:{location_type:1}) { - feed_version { - id - } - station_id: stop_id - stationName: stop_name - geometry - } - } - } -} -` - -export interface UseStationOptions { - feedKey: Ref - feedVersionKey: Ref - stationKey: Ref - clientId?: string -} - -export function useStation (options: UseStationOptions) { - const { feedKey, feedVersionKey, stationKey, clientId } = options - const { showToast } = useToastNotification() - - // Reactive state - const ready = ref(false) - const refetching = ref(false) - const station = ref(null) - const stopList = ref([]) - const selectedAgenciesShadow = ref(null) - const selectedLevelShadow = ref(null) - const selectedLevelsShadow = ref(null) - - // Error handler - const handleError = (err: Error | string) => { - const msg = typeof err === 'string' ? err : (err.message || JSON.stringify(err)) - showToast(`Error: ${msg}`, 'danger') - } - - // Query feeds - const { result: feedsResult, loading: feedsLoading, onError: onFeedsError } = useQuery( - currentFeedsQuery, - () => ({ - feed_onestop_id: feedKey.value, - feed_version_ids: feedVersionKey.value ? [feedVersionKey.value] : null - }), - () => ({ - ...(clientId && { clientId }), - fetchPolicy: 'network-only' - }) - ) - - onFeedsError(handleError) - - const feeds = computed(() => feedsResult.value?.feeds || []) - const feed = computed(() => { - return feeds.value.length > 0 ? feeds.value[0] : null - }) - - const feedVersion = computed(() => { - if (!feed.value?.feed_versions || feed.value.feed_versions.length === 0) { - return null - } - return feed.value.feed_versions[0] - }) - - const feedName = computed(() => { - return feed.value?.name || feed.value?.onestop_id || feedKey.value - }) - - const feedVersionName = computed(() => { - return String(feedVersion.value?.id || feedVersionKey.value || '').substr(0, 8) - }) - - const stationName = computed(() => { - return station.value?.stop?.stop_name - }) - - const stopAssociationsEnabled = computed(() => { - return (feedVersion.value?.agencies || []).length === 0 - }) - - // Query station - const { result: stationResult, loading: stationLoading, onError: onStationError, refetch: refetchStation } = useQuery( - stationQuery, - () => ({ - feed_version_ids: feedVersionKey.value ? [feedVersionKey.value] : null, - feed_onestop_id: feedKey.value, - stop_id: stationKey.value - }), - () => ({ - ...(clientId && { clientId }), - fetchPolicy: 'network-only', - notifyOnNetworkStatusChange: true - }) - ) - - onStationError(handleError) - - // Watch station query result - watch(stationResult, (data: StationQueryResponse | undefined) => { - if (!data || data.feed_versions.length === 0) { - return - } - const fv = data.feed_versions[0] - if (!fv || fv.stops.length === 0) { - return - } - station.value = new Station(fv.stops[0]) - const initialStop = new Stop(fv.stops[0]) - if (!initialStop.id) { - return - } - const childIds = (initialStop.children || []).map(s => s.id).filter((id): id is number => id !== undefined) - stopList.value = [initialStop.id, ...childIds] - }) - - // Query station stops (cascading query) - const { result: stopsResult, loading: stopsLoading, onError: onStopsError, refetch: refetchStops } = useQuery( - stationStopQuery, - () => ({ - stop_ids: stopList.value - }), - () => ({ - ...(clientId && { clientId }), - fetchPolicy: 'network-only', - enabled: stopList.value.length > 0, - notifyOnNetworkStatusChange: true - }) - ) - - onStopsError(handleError) - - // Watch stops query result and cascade if needed - watch(stopsResult, (data: StopsQueryResponse | undefined) => { - if (!data || !station.value) { - return - } - const a = new Set(stopList.value) - const newStops = station.value.addStops(data.stops.map(s => new Stop(s))) - const b = new Set(newStops) - const stationStopId = station.value.stop?.id - if (stationStopId !== undefined) { - a.add(stationStopId) - b.add(stationStopId) - } - if (symmetricDifference(a, b).size === 0) { - ready.value = true - } else { - stopList.value = newStops - refetchStops({ stop_ids: newStops }) - } - }) - - // Computed properties for selected agencies - const selectedAgencies = computed({ - get (): string[] { - if (selectedAgenciesShadow.value != null) { - return selectedAgenciesShadow.value - } - const allAgencies = new Map() - for (const stop of station.value?.stops || []) { - for (const rs of stop.route_stops || []) { - if (rs.agency) { - allAgencies.set(rs.agency.agency_id!, true) - } - } - } - return Array.from(allAgencies.keys()) - }, - set (v: string[]) { - selectedAgenciesShadow.value = v - } - }) - - // Computed properties for selected level - const selectedLevel = computed({ - get (): number | null { - if (selectedLevelShadow.value != null) { - return selectedLevelShadow.value - } - return station.value?.levels[0]?.id || null - }, - set (v: number | null) { - selectedLevelShadow.value = v - } - }) - - // Computed properties for selected levels - const selectedLevels = computed({ - get (): string[] { - if (selectedLevelsShadow.value != null) { - return selectedLevelsShadow.value - } - return station.value?.levels?.map(mapLevelKeyFn) || [] - }, - set (v: string[]) { - selectedLevelsShadow.value = v - } - }) - - const loading = computed(() => { - return feedsLoading.value || stationLoading.value || stopsLoading.value - }) - - const refetch = async () => { - refetching.value = true - try { - await refetchStation() - // Refetch stops if we have a station with stops to reload - if (station.value && stopList.value.length > 0) { - await refetchStops({ stop_ids: stopList.value }) - } - } finally { - refetching.value = false - } - } - - // GraphQL Mutations - const levelCreateMutation = gql` - mutation($set: LevelSetInput!) { - level_create(set: $set) { id } - } - ` - - const levelUpdateMutation = gql` - mutation($set: LevelSetInput!) { - level_update(set: $set) { id } - } - ` - - const levelDeleteMutation = gql` - mutation($id: Int!) { - level_delete(id: $id) { id } - } - ` - - const pathwayCreateMutation = gql` - mutation($set: PathwaySetInput!) { - pathway_create(set: $set) { id } - } - ` - - const pathwayUpdateMutation = gql` - mutation($set: PathwaySetInput!) { - pathway_update(set: $set) { id } - } - ` - - const pathwayDeleteMutation = gql` - mutation($id: Int!) { - pathway_delete(id: $id) { id } - } - ` - - const stopCreateMutation = gql` - mutation($set: StopSetInput!) { - stop_create(set: $set) { id } - } - ` - - const stopUpdateMutation = gql` - mutation($set: StopSetInput!) { - stop_update(set: $set) { id } - } - ` - - const stopDeleteMutation = gql` - mutation($id: Int!) { - stop_delete(id: $id) { id } - } - ` - - const stationCreateMutation = gql` - mutation($set: StopSetInput!) { - stop_create(set: $set) { id } - } - ` - - const stationUpdateMutation = gql` - mutation($set: StopSetInput!) { - stop_update(set: $set) { id } - } - ` - - const stationDeleteMutation = gql` - mutation($id: Int!) { - stop_delete(id: $id) { id } - } - ` - - // Apollo Client for mutations - const { resolveClient } = useApolloClient() - const executeMutation = async (mutation: any, variables: Record): Promise => { - const apollo = resolveClient(clientId) - const result = await apollo.mutate({ - mutation, - variables, - context: { clientName: options.clientId } - }) - await refetch() - return result - } - - // Level mutations - const createLevel = async (ent: Level): Promise => { - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - if (!station.value) { - throw new Error('Station not available') - } - ent.feed_version = { id: feedVersion.value.id } - ent.parent = { id: station.value.id } - const v = ent.value() - const vars = { set: v } - return executeMutation(levelCreateMutation, vars) - } - - const updateLevel = async (ent: Level): Promise => { - if (!ent.id) { - throw new Error('Level ID required for update') - } - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - if (!station.value) { - throw new Error('Station not available') - } - const v = ent.value() - v.parent = { id: station.value.id } - const vars = { set: v } - return executeMutation(levelUpdateMutation, vars) - } - - const deleteLevel = async (ent: Level): Promise => { - if (!ent.id) { - throw new Error('Level ID required for delete') - } - return executeMutation(levelDeleteMutation, { id: ent.id }) - } - - // Pathway mutations - const createPathway = async (ent: Pathway): Promise => { - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - ent.feed_version = { id: feedVersion.value.id } - const v = ent.value() - const vars = { set: v } - return executeMutation(pathwayCreateMutation, vars) - } - - const updatePathway = async (ent: Pathway): Promise => { - if (!ent.id) { - throw new Error('Pathway ID required for update') - } - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - const v = ent.value() - const vars = { set: v } - return executeMutation(pathwayUpdateMutation, vars) - } - - const deletePathway = async (ent: Pathway): Promise => { - if (!ent.id) { - throw new Error('Pathway ID required for delete') - } - return executeMutation(pathwayDeleteMutation, { id: ent.id }) - } - - // Stop mutations - const createStop = async (ent: Stop): Promise => { - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - if (!station.value) { - throw new Error('Station not available') - } - ent.feed_version.id = feedVersion.value.id - // Boarding areas (location_type=4) must have a Platform (location_type=0) as parent_station - // For all other stop types, parent should be the Station (location_type=1) - if (ent.location_type !== 4) { - ent.parent = { id: station.value.id } - } - // If location_type is 4, preserve the parent that was set in the entity (should be a platform) - const v = ent.value() - const vars = { set: v } - return executeMutation(stopCreateMutation, vars) - } - - const updateStop = async (ent: Stop): Promise => { - if (!ent.id) { - throw new Error('Stop ID required for update') - } - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - if (!station.value) { - throw new Error('Station not available') - } - const v = ent.value() - // Boarding areas (location_type=4) must have a Platform (location_type=0) as parent_station - // For all other stop types, parent should be the Station (location_type=1) - if (ent.location_type !== 4) { - v.parent = { id: station.value.id } - } - // If location_type is 4, preserve the parent that was set in the entity (should be a platform) - const vars = { set: v } - return executeMutation(stopUpdateMutation, vars) - } - - const deleteStop = async (ent: Stop): Promise => { - if (!ent.id) { - throw new Error('Stop ID required for delete') - } - return executeMutation(stopDeleteMutation, { id: ent.id }) - } - - const importStop = async (ent: Stop): Promise => { - if (!station.value) { - throw new Error('Station not available') - } - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - const sourceFeed = ent.feed_version?.feed?.onestop_id - // For boarding areas (location_type=4), don't set parent to station - // The parent platform relationship from the source feed may not exist in the target station - // User will need to manually set the correct platform parent after import - // For all other stop types, set parent to station - const stopData: any = { - feed_version: { id: feedVersion.value.id }, - stop_id: `import-${sourceFeed}-${ent.stop_id}`, - level: { id: ent.level.id }, - stop_name: ent.stop_name, - stop_code: ent.stop_code, - platform_code: ent.platform_code, - location_type: ent.location_type, - geometry: ent.geometry, - external_reference: { - target_feed_onestop_id: sourceFeed, - target_stop_id: ent.stop_id - } - } - // Only set parent for non-boarding areas - if (ent.location_type !== 4) { - stopData.parent = { id: station.value.id } - } - const stop = new Stop(stopData) - return createStop(stop) - } - - // Station mutations - const createStation = async (ent: Stop): Promise => { - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - ent.feed_version.id = feedVersion.value.id - ent.parent = { id: undefined } - const v = ent.value() - const vars = { set: v } - return executeMutation(stationCreateMutation, vars) - } - - const updateStation = async (ent: Stop): Promise => { - if (!ent.id) { - throw new Error('Station ID required for update') - } - if (!feedVersion.value) { - throw new Error('Feed version not available') - } - const v = ent.value() - // Station has no parent (it IS the parent) - v.parent = { id: null } - const vars = { set: v } - return executeMutation(stationUpdateMutation, vars) - } - - const deleteStation = async (ent: Stop): Promise => { - if (!ent.id) { - throw new Error('Station ID required for delete') - } - return executeMutation(stationDeleteMutation, { id: ent.id }) - } - - return { - // State - ready, - refetching, - station, - feeds, - feed, - feedVersion, - feedName, - feedVersionName, - stationName, - stopAssociationsEnabled, - loading, - - // Selection state - selectedAgencies, - selectedLevel, - selectedLevels, - - // Methods - handleError, - refetch, - - // Level mutations - createLevel, - updateLevel, - deleteLevel, - - // Pathway mutations - createPathway, - updatePathway, - deletePathway, - - // Stop mutations - createStop, - updateStop, - deleteStop, - importStop, - - // Station mutations - createStation, - updateStation, - deleteStation - } -} diff --git a/src/runtime/apps/stations/gtfs-export-download.vue b/src/runtime/apps/stations/gtfs-export-download.vue deleted file mode 100644 index b9e77401..00000000 --- a/src/runtime/apps/stations/gtfs-export-download.vue +++ /dev/null @@ -1,301 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/index.ts b/src/runtime/apps/stations/index.ts deleted file mode 100644 index 7b81f4d1..00000000 --- a/src/runtime/apps/stations/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Lib -export * from './basemaps' -export * from './station' -export * from './types' -export * from './station-validation' - -// Composables -export * from './composables/useFeed' -export * from './composables/useStation' diff --git a/src/runtime/apps/stations/level-editor.vue b/src/runtime/apps/stations/level-editor.vue deleted file mode 100644 index d71c3939..00000000 --- a/src/runtime/apps/stations/level-editor.vue +++ /dev/null @@ -1,324 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/level-map.vue b/src/runtime/apps/stations/level-map.vue deleted file mode 100644 index a1cf2dea..00000000 --- a/src/runtime/apps/stations/level-map.vue +++ /dev/null @@ -1,272 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/mode-switch.vue b/src/runtime/apps/stations/mode-switch.vue deleted file mode 100644 index 3658c538..00000000 --- a/src/runtime/apps/stations/mode-switch.vue +++ /dev/null @@ -1,61 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/editor-index.vue b/src/runtime/apps/stations/pages/editor-index.vue deleted file mode 100644 index 1fd14e77..00000000 --- a/src/runtime/apps/stations/pages/editor-index.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/export.vue b/src/runtime/apps/stations/pages/export.vue deleted file mode 100644 index 8493cee9..00000000 --- a/src/runtime/apps/stations/pages/export.vue +++ /dev/null @@ -1,57 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/level-edit.vue b/src/runtime/apps/stations/pages/level-edit.vue deleted file mode 100644 index c4c277eb..00000000 --- a/src/runtime/apps/stations/pages/level-edit.vue +++ /dev/null @@ -1,109 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/levels-new.vue b/src/runtime/apps/stations/pages/levels-new.vue deleted file mode 100644 index de4db603..00000000 --- a/src/runtime/apps/stations/pages/levels-new.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/station-diagram.vue b/src/runtime/apps/stations/pages/station-diagram.vue deleted file mode 100644 index 6e8cf75c..00000000 --- a/src/runtime/apps/stations/pages/station-diagram.vue +++ /dev/null @@ -1,161 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pages/station-edit.vue b/src/runtime/apps/stations/pages/station-edit.vue deleted file mode 100644 index db8fbb7c..00000000 --- a/src/runtime/apps/stations/pages/station-edit.vue +++ /dev/null @@ -1,101 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/station-index.vue b/src/runtime/apps/stations/pages/station-index.vue deleted file mode 100644 index e8976db0..00000000 --- a/src/runtime/apps/stations/pages/station-index.vue +++ /dev/null @@ -1,97 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pages/station-pathways-v2.vue b/src/runtime/apps/stations/pages/station-pathways-v2.vue deleted file mode 100644 index b6965ea5..00000000 --- a/src/runtime/apps/stations/pages/station-pathways-v2.vue +++ /dev/null @@ -1,709 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pages/station-pathways.vue b/src/runtime/apps/stations/pages/station-pathways.vue deleted file mode 100644 index 237d50c3..00000000 --- a/src/runtime/apps/stations/pages/station-pathways.vue +++ /dev/null @@ -1,822 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pages/station-simulator.vue b/src/runtime/apps/stations/pages/station-simulator.vue deleted file mode 100644 index 77235a39..00000000 --- a/src/runtime/apps/stations/pages/station-simulator.vue +++ /dev/null @@ -1,1225 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pages/station-stops.vue b/src/runtime/apps/stations/pages/station-stops.vue deleted file mode 100644 index 955e5d24..00000000 --- a/src/runtime/apps/stations/pages/station-stops.vue +++ /dev/null @@ -1,499 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pages/stations-index.vue b/src/runtime/apps/stations/pages/stations-index.vue deleted file mode 100644 index 78d44243..00000000 --- a/src/runtime/apps/stations/pages/stations-index.vue +++ /dev/null @@ -1,68 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/stations-new.vue b/src/runtime/apps/stations/pages/stations-new.vue deleted file mode 100644 index fd7c01ea..00000000 --- a/src/runtime/apps/stations/pages/stations-new.vue +++ /dev/null @@ -1,77 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/pages/stations-stop-associations.vue b/src/runtime/apps/stations/pages/stations-stop-associations.vue deleted file mode 100644 index 426ac675..00000000 --- a/src/runtime/apps/stations/pages/stations-stop-associations.vue +++ /dev/null @@ -1,185 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/path-viewer.vue b/src/runtime/apps/stations/path-viewer.vue deleted file mode 100644 index 3fc1c3b8..00000000 --- a/src/runtime/apps/stations/path-viewer.vue +++ /dev/null @@ -1,100 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pathway-editor.vue b/src/runtime/apps/stations/pathway-editor.vue deleted file mode 100644 index 24424340..00000000 --- a/src/runtime/apps/stations/pathway-editor.vue +++ /dev/null @@ -1,197 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/pathway-map.vue b/src/runtime/apps/stations/pathway-map.vue deleted file mode 100644 index 4c38f736..00000000 --- a/src/runtime/apps/stations/pathway-map.vue +++ /dev/null @@ -1,904 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-diagram-viewer.vue b/src/runtime/apps/stations/station-diagram-viewer.vue deleted file mode 100644 index 16133f25..00000000 --- a/src/runtime/apps/stations/station-diagram-viewer.vue +++ /dev/null @@ -1,217 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-editor.vue b/src/runtime/apps/stations/station-editor.vue deleted file mode 100644 index f0aa60b3..00000000 --- a/src/runtime/apps/stations/station-editor.vue +++ /dev/null @@ -1,196 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/station-levels-viewer-sorter.vue b/src/runtime/apps/stations/station-levels-viewer-sorter.vue deleted file mode 100644 index bea154e6..00000000 --- a/src/runtime/apps/stations/station-levels-viewer-sorter.vue +++ /dev/null @@ -1,90 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/station-mode-tabs.vue b/src/runtime/apps/stations/station-mode-tabs.vue deleted file mode 100644 index 79f9f889..00000000 --- a/src/runtime/apps/stations/station-mode-tabs.vue +++ /dev/null @@ -1,150 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-pathways-add-node-panel.vue b/src/runtime/apps/stations/station-pathways-add-node-panel.vue deleted file mode 100644 index beea1d97..00000000 --- a/src/runtime/apps/stations/station-pathways-add-node-panel.vue +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/station-pathways-add-pathway-panel.vue b/src/runtime/apps/stations/station-pathways-add-pathway-panel.vue deleted file mode 100644 index 3938aac8..00000000 --- a/src/runtime/apps/stations/station-pathways-add-pathway-panel.vue +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/station-pathways-editor-panel.vue b/src/runtime/apps/stations/station-pathways-editor-panel.vue deleted file mode 100644 index 69a6b849..00000000 --- a/src/runtime/apps/stations/station-pathways-editor-panel.vue +++ /dev/null @@ -1,53 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/station-pathways-filter-counts.spec.ts b/src/runtime/apps/stations/station-pathways-filter-counts.spec.ts deleted file mode 100644 index 87155348..00000000 --- a/src/runtime/apps/stations/station-pathways-filter-counts.spec.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { describe, test, expect } from 'vitest' -import { Stop, Pathway } from './station' -import { computeFilterCounts } from './station-pathways-filter-counts' -import type { StopData, PathwayData } from './types' - -function makeStop (overrides: Partial = {}): Stop { - return new Stop({ - id: 1, - stop_id: 'stop-1', - stop_name: 'Test Stop', - location_type: 3, - geometry: { type: 'Point', coordinates: [-122.0, 37.0] }, - level: { id: 10, level_name: 'Ground' }, - pathways_from_stop: [], - pathways_to_stop: [], - ...overrides - }) -} - -function makePathway (overrides: Partial = {}): Pathway { - return new Pathway({ - id: 1, - pathway_id: 'pw-1', - pathway_mode: 1, - is_bidirectional: 1, - from_stop: { id: 1, stop_id: 'from', level: { id: 10, level_name: 'Ground' } }, - to_stop: { id: 2, stop_id: 'to', level: { id: 10, level_name: 'Ground' } }, - ...overrides - }) -} - -describe('computeFilterCounts', () => { - describe('empty station', () => { - test('returns zeros for all counts', () => { - const counts = computeFilterCounts([], []) - expect(counts.stopsByLocationType).toEqual({}) - expect(counts.stopsWithAssociations).toBe(0) - expect(counts.platformsWithoutAssociations).toBe(0) - expect(counts.entrancesWithoutAssociations).toBe(0) - expect(counts.stopsWithPairedPathways).toBe(0) - expect(counts.pathwaysByMode).toEqual({}) - expect(counts.pathwaysWithPairs).toBe(0) - expect(counts.pathwaysOneway).toBe(0) - expect(counts.pathwaysBidirectional).toBe(0) - }) - }) - - describe('stopsByLocationType', () => { - test('counts stops by location_type', () => { - const stops = [ - makeStop({ id: 1, location_type: 0 }), - makeStop({ id: 2, location_type: 0 }), - makeStop({ id: 3, location_type: 2 }), - makeStop({ id: 4, location_type: 3 }) - ] - const { stopsByLocationType } = computeFilterCounts(stops, []) - expect(stopsByLocationType[0]).toBe(2) - expect(stopsByLocationType[2]).toBe(1) - expect(stopsByLocationType[3]).toBe(1) - expect(stopsByLocationType[1]).toBeUndefined() - }) - }) - - describe('stopsWithAssociations', () => { - test('counts stops with external_reference.target_stop_id', () => { - const stops = [ - makeStop({ id: 1, external_reference: { target_feed_onestop_id: 'f', target_stop_id: 'ext-1' } }), - makeStop({ id: 2, external_reference: { target_feed_onestop_id: 'f', target_stop_id: 'ext-2' } }), - makeStop({ id: 3 }) - ] - expect(computeFilterCounts(stops, []).stopsWithAssociations).toBe(2) - }) - - test('does not count stops without external_reference', () => { - const stops = [makeStop({ id: 1 }), makeStop({ id: 2 })] - expect(computeFilterCounts(stops, []).stopsWithAssociations).toBe(0) - }) - }) - - describe('platformsWithoutAssociations', () => { - test('counts platforms (location_type=0) with no external_reference', () => { - const stops = [ - makeStop({ id: 1, location_type: 0 }), - makeStop({ id: 2, location_type: 0 }), - makeStop({ id: 3, location_type: 0, external_reference: { target_feed_onestop_id: 'f', target_stop_id: 'x' } }), - makeStop({ id: 4, location_type: 2 }) // entrance, not counted - ] - expect(computeFilterCounts(stops, []).platformsWithoutAssociations).toBe(2) - }) - }) - - describe('entrancesWithoutAssociations', () => { - test('counts entrances (location_type=2) with no external_reference', () => { - const stops = [ - makeStop({ id: 1, location_type: 2 }), - makeStop({ id: 2, location_type: 2, external_reference: { target_feed_onestop_id: 'f', target_stop_id: 'x' } }), - makeStop({ id: 3, location_type: 0 }) // platform, not counted - ] - expect(computeFilterCounts(stops, []).entrancesWithoutAssociations).toBe(1) - }) - }) - - describe('stopsWithPairedPathways', () => { - test('returns 0 when no pathways exist', () => { - const stops = [makeStop({ id: 1 }), makeStop({ id: 2 })] - expect(computeFilterCounts(stops, []).stopsWithPairedPathways).toBe(0) - }) - - test('returns 0 when pathways are one-directional with no reverse', () => { - // Stop A has A→B outgoing only; stop B has A→B incoming only - const stopA = makeStop({ - id: 1, - pathways_from_stop: [{ id: 10, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [] - }) - const stopB = makeStop({ - id: 2, - pathways_from_stop: [], - pathways_to_stop: [{ id: 10, from_stop: { id: 1 }, to_stop: { id: 2 } }] - }) - expect(computeFilterCounts([stopA, stopB], []).stopsWithPairedPathways).toBe(0) - }) - - test('counts stops that participate in a paired (A→B + B→A) set', () => { - // Both stops have the pathway in each direction listed in their from/to lists - const stopA = makeStop({ - id: 1, - pathways_from_stop: [{ id: 10, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [{ id: 11, from_stop: { id: 2 }, to_stop: { id: 1 } }] - }) - const stopB = makeStop({ - id: 2, - pathways_from_stop: [{ id: 11, from_stop: { id: 2 }, to_stop: { id: 1 } }], - pathways_to_stop: [{ id: 10, from_stop: { id: 1 }, to_stop: { id: 2 } }] - }) - expect(computeFilterCounts([stopA, stopB], []).stopsWithPairedPathways).toBe(2) - }) - }) - - describe('pathwaysByMode', () => { - test('counts pathways by pathway_mode', () => { - const pathways = [ - makePathway({ id: 1, pathway_mode: 1 }), - makePathway({ id: 2, pathway_mode: 1 }), - makePathway({ id: 3, pathway_mode: 2 }), - makePathway({ id: 4, pathway_mode: 5 }) - ] - const { pathwaysByMode } = computeFilterCounts([], pathways) - expect(pathwaysByMode[1]).toBe(2) - expect(pathwaysByMode[2]).toBe(1) - expect(pathwaysByMode[5]).toBe(1) - expect(pathwaysByMode[3]).toBeUndefined() - }) - }) - - describe('pathwaysWithPairs', () => { - test('returns 0 when all pathways are one-directional with no reverse', () => { - const pathways = [ - makePathway({ id: 1, from_stop: { id: 1, stop_id: 'a' }, to_stop: { id: 2, stop_id: 'b' } }) - ] - expect(computeFilterCounts([], pathways).pathwaysWithPairs).toBe(0) - }) - - test('counts both pathways when A→B and B→A both exist', () => { - const pathways = [ - makePathway({ id: 1, from_stop: { id: 1, stop_id: 'a' }, to_stop: { id: 2, stop_id: 'b' } }), - makePathway({ id: 2, from_stop: { id: 2, stop_id: 'b' }, to_stop: { id: 1, stop_id: 'a' } }) - ] - expect(computeFilterCounts([], pathways).pathwaysWithPairs).toBe(2) - }) - - test('only counts pathways that have a reverse, not unpaired ones', () => { - const pathways = [ - makePathway({ id: 1, from_stop: { id: 1, stop_id: 'a' }, to_stop: { id: 2, stop_id: 'b' } }), - makePathway({ id: 2, from_stop: { id: 2, stop_id: 'b' }, to_stop: { id: 1, stop_id: 'a' } }), - makePathway({ id: 3, from_stop: { id: 3, stop_id: 'c' }, to_stop: { id: 4, stop_id: 'd' } }) // no reverse - ] - expect(computeFilterCounts([], pathways).pathwaysWithPairs).toBe(2) - }) - }) - - describe('pathwaysOneway / pathwaysBidirectional', () => { - test('counts one-directional pathways (is_bidirectional=0)', () => { - const pathways = [ - makePathway({ id: 1, is_bidirectional: 0 }), - makePathway({ id: 2, is_bidirectional: 0 }), - makePathway({ id: 3, is_bidirectional: 1 }) - ] - const counts = computeFilterCounts([], pathways) - expect(counts.pathwaysOneway).toBe(2) - expect(counts.pathwaysBidirectional).toBe(1) - }) - - test('counts bi-directional pathways (is_bidirectional=1)', () => { - const pathways = [ - makePathway({ id: 1, is_bidirectional: 1 }), - makePathway({ id: 2, is_bidirectional: 1 }) - ] - const counts = computeFilterCounts([], pathways) - expect(counts.pathwaysOneway).toBe(0) - expect(counts.pathwaysBidirectional).toBe(2) - }) - }) -}) diff --git a/src/runtime/apps/stations/station-pathways-filter-counts.ts b/src/runtime/apps/stations/station-pathways-filter-counts.ts deleted file mode 100644 index 5d4d4ba7..00000000 --- a/src/runtime/apps/stations/station-pathways-filter-counts.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { Stop, Pathway } from './station' - -export interface FilterCounts { - stopsByLocationType: Record - stopsWithAssociations: number - platformsWithoutAssociations: number - entrancesWithoutAssociations: number - stopsWithPairedPathways: number - pathwaysByMode: Record - pathwaysWithPairs: number - pathwaysOneway: number - pathwaysBidirectional: number -} - -export function computeFilterCounts (stops: Stop[], pathways: Pathway[]): FilterCounts { - const stopsByLocationType: Record = {} - for (const s of stops) { - if (s.location_type != null) { - stopsByLocationType[s.location_type] = (stopsByLocationType[s.location_type] || 0) + 1 - } - } - - const pathwaysByMode: Record = {} - for (const p of pathways) { - if (p.pathway_mode != null) { - pathwaysByMode[p.pathway_mode] = (pathwaysByMode[p.pathway_mode] || 0) + 1 - } - } - - // A stop "has paired pathways" when it participates in both directions of a - // pair (A→B and B→A). Each stop contributes canonical keys for its outgoing - // pathways (from_stop perspective) and incoming pathways (to_stop reversed), - // and a match occurs when another stop has already contributed the same key. - const pairedStopMap = new Map() - const stopsWithPairedPathways = stops.filter((s) => { - const keys: string[] = [] - for (const pw of (s.pathways_from_stop || [])) { - keys.push(`${pw.from_stop.id}-${pw.to_stop.id}`) - } - for (const pw of (s.pathways_to_stop || [])) { - keys.push(`${pw.to_stop.id}-${pw.from_stop.id}`) - } - let matched = false - for (const k of keys) { - if (pairedStopMap.has(k)) { - matched = true - } - pairedStopMap.set(k, true) - } - return matched - }).length - - const allPathwayKeys = new Set(pathways.map(p => `${p.from_stop.id}-${p.to_stop.id}`)) - const pathwaysWithPairs = pathways.filter(p => - allPathwayKeys.has(`${p.to_stop.id}-${p.from_stop.id}`) - ).length - - return { - stopsByLocationType, - stopsWithAssociations: stops.filter(s => s.external_reference?.target_stop_id).length, - platformsWithoutAssociations: stops.filter(s => s.location_type === 0 && !s.external_reference).length, - entrancesWithoutAssociations: stops.filter(s => s.location_type === 2 && !s.external_reference).length, - stopsWithPairedPathways, - pathwaysByMode, - pathwaysWithPairs, - pathwaysOneway: pathways.filter(p => p.is_bidirectional === 0).length, - pathwaysBidirectional: pathways.filter(p => p.is_bidirectional === 1).length - } -} diff --git a/src/runtime/apps/stations/station-pathways-find-route-panel.vue b/src/runtime/apps/stations/station-pathways-find-route-panel.vue deleted file mode 100644 index b46fde68..00000000 --- a/src/runtime/apps/stations/station-pathways-find-route-panel.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/station-pathways-node-panel.vue b/src/runtime/apps/stations/station-pathways-node-panel.vue deleted file mode 100644 index 6fb429e4..00000000 --- a/src/runtime/apps/stations/station-pathways-node-panel.vue +++ /dev/null @@ -1,237 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-pathways-pathway-panel.vue b/src/runtime/apps/stations/station-pathways-pathway-panel.vue deleted file mode 100644 index aebb92db..00000000 --- a/src/runtime/apps/stations/station-pathways-pathway-panel.vue +++ /dev/null @@ -1,221 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-pathways-select-panel.vue b/src/runtime/apps/stations/station-pathways-select-panel.vue deleted file mode 100644 index 5f49cdcb..00000000 --- a/src/runtime/apps/stations/station-pathways-select-panel.vue +++ /dev/null @@ -1,243 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-simulator-helpers.ts b/src/runtime/apps/stations/station-simulator-helpers.ts deleted file mode 100644 index f57c6205..00000000 --- a/src/runtime/apps/stations/station-simulator-helpers.ts +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Pure helper functions for the station simulator. - * Extracted here to be independently testable without Vue/MapLibre setup. - */ - -/** - * Compute a quadratic bezier arc between two [lon, lat] points. - * The control point is offset perpendicular to the straight-line segment - * so the arc curves away from the direct path. - * - * Returns `steps + 1` evenly-spaced points along the curve, - * with the first equal to p0 and the last equal to p2. - * Degenerate case (p0 === p2): returns [p0, p2] directly. - */ -export function computeArc (p0: [number, number], p2: [number, number], steps = 32): [number, number][] { - const dLon = p2[0] - p0[0] - const dLat = p2[1] - p0[1] - const len = Math.sqrt(dLon * dLon + dLat * dLat) - if (len === 0) { return [p0, p2] } - // Control point: midpoint shifted perpendicular to the segment - const offset = len * 0.35 - const p1: [number, number] = [ - (p0[0] + p2[0]) / 2 - (dLat / len) * offset, - (p0[1] + p2[1]) / 2 + (dLon / len) * offset - ] - const pts: [number, number][] = [] - for (let i = 0; i <= steps; i++) { - const t = i / steps - pts.push([ - (1 - t) * (1 - t) * p0[0] + 2 * (1 - t) * t * p1[0] + t * t * p2[0], - (1 - t) * (1 - t) * p0[1] + 2 * (1 - t) * t * p1[1] + t * t * p2[1] - ]) - } - return pts -} - -/** - * Bearing in degrees clockwise from north, derived from the last two points - * of an arc (i.e. the terminal direction of travel). - * Returns 0 for arrays with fewer than two points. - */ -export function terminalBearing (pts: [number, number][]): number { - if (pts.length < 2) { return 0 } - const a = pts[pts.length - 2]! - const b = pts[pts.length - 1]! - return Math.atan2(b[0] - a[0], b[1] - a[1]) * 180 / Math.PI -} diff --git a/src/runtime/apps/stations/station-simulator-map.vue b/src/runtime/apps/stations/station-simulator-map.vue deleted file mode 100644 index 1bfc36ff..00000000 --- a/src/runtime/apps/stations/station-simulator-map.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station-simulator.spec.ts b/src/runtime/apps/stations/station-simulator.spec.ts deleted file mode 100644 index 58897b2c..00000000 --- a/src/runtime/apps/stations/station-simulator.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { describe, test, expect } from 'vitest' -import { computeArc, terminalBearing } from './station-simulator-helpers' - -describe('computeArc', () => { - test('first point equals p0 and last point equals p2', () => { - const p0: [number, number] = [-122.4, 37.8] - const p2: [number, number] = [-122.41, 37.81] - const pts = computeArc(p0, p2) - expect(pts[0]).toEqual(p0) - expect(pts[pts.length - 1]).toEqual(p2) - }) - - test('returns steps + 1 points', () => { - expect(computeArc([0, 0], [1, 1], 16)).toHaveLength(17) - expect(computeArc([0, 0], [1, 1], 32)).toHaveLength(33) - }) - - test('degenerate case: same start and end returns two-element array', () => { - const p: [number, number] = [-122.4, 37.8] - const pts = computeArc(p, p) - expect(pts).toHaveLength(2) - expect(pts[0]).toEqual(p) - expect(pts[1]).toEqual(p) - }) - - test('arc curves away from the straight line (control point offset)', () => { - // Horizontal segment due east: midpoint of arc should be north of the midline - const p0: [number, number] = [0, 0] - const p2: [number, number] = [1, 0] - const pts = computeArc(p0, p2, 32) - const mid = pts[16]! - // The perpendicular offset pushes control point north (+lat), - // so the arc midpoint should have positive latitude - expect(mid[1]).toBeGreaterThan(0) - // Longitude at midpoint is close to 0.5 - expect(mid[0]).toBeCloseTo(0.5, 1) - }) -}) - -describe('terminalBearing', () => { - test('returns 0 for empty or single-point arrays', () => { - expect(terminalBearing([])).toBe(0) - expect(terminalBearing([[0, 0]])).toBe(0) - }) - - test('due north (increasing lat) → 0°', () => { - const bearing = terminalBearing([[0, 0], [0, 1]]) - expect(bearing).toBeCloseTo(0, 5) - }) - - test('due east (increasing lon) → 90°', () => { - const bearing = terminalBearing([[0, 0], [1, 0]]) - expect(bearing).toBeCloseTo(90, 5) - }) - - test('due south (decreasing lat) → 180°', () => { - const bearing = terminalBearing([[0, 1], [0, 0]]) - expect(bearing).toBeCloseTo(180, 5) - }) - - test('due west (decreasing lon) → -90°', () => { - const bearing = terminalBearing([[1, 0], [0, 0]]) - expect(bearing).toBeCloseTo(-90, 5) - }) -}) diff --git a/src/runtime/apps/stations/station-validation.spec.ts b/src/runtime/apps/stations/station-validation.spec.ts deleted file mode 100644 index 609622ee..00000000 --- a/src/runtime/apps/stations/station-validation.spec.ts +++ /dev/null @@ -1,761 +0,0 @@ -import { describe, test, expect } from 'vitest' -import { Stop, Pathway, Station } from './station' -import { validateStop, validatePathway, validateConnectivity } from './station-validation' -import type { StopData, PathwayData } from './types' - -// Helper to create a minimal valid stop with sensible defaults -function makeStop (overrides: Partial = {}): Stop { - return new Stop({ - id: 1, - stop_id: 'stop-1', - stop_name: 'Test Stop', - location_type: 3, - geometry: { type: 'Point', coordinates: [-122.0, 37.0] }, - level: { id: 10, level_name: 'Ground' }, - pathways_from_stop: [{ id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [{ id: 101, from_stop: { id: 3 }, to_stop: { id: 1 } }], - ...overrides - }) -} - -// Helper to create a minimal valid pathway -function makePathway (overrides: Partial = {}): Pathway { - return new Pathway({ - id: 1, - pathway_id: 'pw-1', - pathway_mode: 1, - is_bidirectional: 1, - from_stop: { - id: 1, - stop_id: 'from', - level: { id: 10, level_name: 'Ground' }, - geometry: { type: 'Point', coordinates: [-122.0, 37.0] } - }, - to_stop: { - id: 2, - stop_id: 'to', - level: { id: 11, level_name: 'Upper' }, - geometry: { type: 'Point', coordinates: [-122.001, 37.0] } - }, - ...overrides - }) -} - -function hasMessage (errs: { message: string }[], substring: string): boolean { - return errs.some(e => e.message.includes(substring)) -} - -describe('validateStop', () => { - describe('stop_name required', () => { - test('error when non-generic node has no stop_name', () => { - const stop = makeStop({ location_type: 0, stop_name: '' }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Stop name is required')).toBe(true) - }) - - test('error when stop_name is whitespace only', () => { - const stop = makeStop({ location_type: 2, stop_name: ' ' }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Stop name is required')).toBe(true) - }) - - test('no error when generic node (location_type=3) has no stop_name', () => { - const stop = makeStop({ location_type: 3, stop_name: '' }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Stop name is required')).toBe(false) - }) - - test('no error when non-generic node has a stop_name', () => { - const stop = makeStop({ location_type: 0, stop_name: 'Platform A' }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Stop name is required')).toBe(false) - }) - }) - - describe('coordinates required', () => { - test('error when non-generic node has no geometry', () => { - const stop = makeStop({ location_type: 2, geometry: undefined }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Coordinates are required')).toBe(true) - }) - - test('no error when generic node has no geometry', () => { - const stop = makeStop({ location_type: 3, geometry: undefined }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Coordinates are required')).toBe(false) - }) - - test('interline recommendation when generic node has no geometry', () => { - const stop = makeStop({ location_type: 3, geometry: undefined }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'generic nodes should have coordinates')).toBe(true) - expect(errs.find(e => e.message.includes('generic nodes should have coordinates'))?.severity).toBe('interline') - }) - - test('no interline recommendation when generic node has geometry', () => { - const stop = makeStop({ location_type: 3, geometry: { type: 'Point', coordinates: [-122.0, 37.0] } }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'generic nodes should have coordinates')).toBe(false) - }) - - test('no interline recommendation for non-generic node without geometry (covered by critical error)', () => { - const stop = makeStop({ location_type: 2, geometry: undefined }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'generic nodes should have coordinates')).toBe(false) - }) - }) - - describe('level assignment', () => { - test('error when stop has no level assignment', () => { - const stop = makeStop({ level: undefined }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'stop should have a level assignment')).toBe(true) - }) - - test('no error when stop has a level', () => { - const stop = makeStop({ level: { id: 10, level_name: 'Ground' } }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'stop should have a level assignment')).toBe(false) - }) - }) - - describe('target stop location_type mismatch', () => { - test('error when external reference target has different location_type', () => { - const stop = makeStop({ - location_type: 0, - stop_name: 'Platform', - external_reference: { - target_feed_onestop_id: 'feed-1', - target_stop_id: 'ext-1', - target_active_stop: { id: 99, location_type: 2 } - } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'same location_type as the target stop')).toBe(true) - }) - - test('no error when external reference target has same location_type', () => { - const stop = makeStop({ - location_type: 0, - stop_name: 'Platform', - external_reference: { - target_feed_onestop_id: 'feed-1', - target_stop_id: 'ext-1', - target_active_stop: { id: 99, location_type: 0 } - } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'same location_type as the target stop')).toBe(false) - }) - }) - - describe('pathways on station', () => { - test('error when station (location_type=1) has pathways_from_stop', () => { - const stop = makeStop({ - location_type: 1, - stop_name: 'Station', - pathways_from_stop: [{ id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Pathways cannot use Station')).toBe(true) - }) - - test('error when station (location_type=1) has pathways_to_stop', () => { - const stop = makeStop({ - location_type: 1, - stop_name: 'Station', - pathways_from_stop: [], - pathways_to_stop: [{ id: 100, from_stop: { id: 2 }, to_stop: { id: 1 } }] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Pathways cannot use Station')).toBe(true) - }) - - test('no error when station has no pathways', () => { - const stop = makeStop({ - location_type: 1, - stop_name: 'Station', - pathways_from_stop: [], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Pathways cannot use Station')).toBe(false) - }) - }) - - describe('self as parent_station', () => { - test('error when stop is its own parent', () => { - const stop = makeStop({ - id: 5, - parent: { id: 5, location_type: 1 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Cannot have self as parent_station')).toBe(true) - }) - - test('no error when parent is different stop', () => { - const stop = makeStop({ - id: 5, - parent: { id: 6, location_type: 1 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Cannot have self as parent_station')).toBe(false) - }) - }) - - describe('parent must be station', () => { - test('error when non-boarding-area has non-station parent', () => { - const stop = makeStop({ - location_type: 3, - parent: { id: 6, location_type: 0 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'parent_station must be a Station')).toBe(true) - }) - - test('no error when non-boarding-area has station parent', () => { - const stop = makeStop({ - location_type: 3, - parent: { id: 6, location_type: 1 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'parent_station must be a Station')).toBe(false) - }) - - test('no error for boarding area with platform parent (checked separately)', () => { - const stop = makeStop({ - location_type: 4, - stop_name: 'Boarding Area', - parent: { id: 6, location_type: 0 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'parent_station must be a Station')).toBe(false) - }) - }) - - describe('boarding area parent', () => { - test('error when boarding area has no parent', () => { - const stop = makeStop({ - location_type: 4, - stop_name: 'Boarding Area', - parent: undefined - }) - // Stop constructor sets parent to { id: undefined } when no parent data - stop.parent = null as any - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Boarding areas require a Platform')).toBe(true) - }) - - test('error when boarding area has non-platform parent', () => { - const stop = makeStop({ - location_type: 4, - stop_name: 'Boarding Area', - parent: { id: 6, location_type: 1 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Boarding areas require a Platform')).toBe(true) - }) - - test('no error when boarding area has platform parent', () => { - const stop = makeStop({ - location_type: 4, - stop_name: 'Boarding Area', - parent: { id: 6, location_type: 0 } - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Boarding areas require a Platform')).toBe(false) - }) - }) - - describe('unresolvable external reference', () => { - test('error when external reference target_active_stop is null', () => { - const stop = makeStop({ - external_reference: { - target_feed_onestop_id: 'feed-1', - target_stop_id: 'stop-x', - target_active_stop: undefined - } - }) - // Set target_active_stop to null explicitly (the validation checks for null) - stop.external_reference!.target_active_stop = null as any - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'cannot resolve reference')).toBe(true) - }) - - test('no error when no external reference', () => { - const stop = makeStop({ external_reference: undefined }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'cannot resolve reference')).toBe(false) - }) - }) - - describe('missing connecting pathway', () => { - test('error when non-station stop has no pathways and no boarding areas', () => { - const stop = makeStop({ - location_type: 2, - stop_name: 'Entrance', - pathways_from_stop: [], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'require at least one connecting pathway')).toBe(true) - }) - - test('no error for station (location_type=1) without pathways', () => { - const stop = makeStop({ - location_type: 1, - stop_name: 'Station', - pathways_from_stop: [], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'require at least one connecting pathway')).toBe(false) - }) - - test('no error for platform with boarding areas and no pathways', () => { - const platform = makeStop({ - id: 10, - location_type: 0, - stop_name: 'Platform', - pathways_from_stop: [], - pathways_to_stop: [] - }) - const boardingArea = makeStop({ - id: 11, - location_type: 4, - stop_name: 'Boarding', - parent: { id: 10, location_type: 0 } - }) - const errs = validateStop(platform, [platform, boardingArea]) - expect(hasMessage(errs, 'require at least one connecting pathway')).toBe(false) - }) - }) - - describe('generic node pathway count', () => { - test('error when generic node has fewer than 2 pathways', () => { - const stop = makeStop({ - location_type: 3, - pathways_from_stop: [{ id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'generic nodes should connect to at least two pathways')).toBe(true) - }) - - test('no error when generic node has 2+ pathways', () => { - const stop = makeStop({ - location_type: 3, - pathways_from_stop: [{ id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [{ id: 101, from_stop: { id: 3 }, to_stop: { id: 1 } }] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'generic nodes should connect to at least two pathways')).toBe(false) - }) - }) - - describe('platform with boarding areas has pathways', () => { - test('error when platform with boarding areas also has pathways', () => { - const platform = makeStop({ - id: 10, - location_type: 0, - stop_name: 'Platform', - pathways_from_stop: [{ id: 100, from_stop: { id: 10 }, to_stop: { id: 20 } }], - pathways_to_stop: [] - }) - const boardingArea = makeStop({ - id: 11, - location_type: 4, - stop_name: 'Boarding', - parent: { id: 10, location_type: 0 } - }) - const errs = validateStop(platform, [platform, boardingArea]) - expect(hasMessage(errs, 'Platforms with boarding areas must not have pathways')).toBe(true) - }) - }) - - describe('do not transit through platforms', () => { - test('warning when platform without boarding areas has more than 1 pathway', () => { - const stop = makeStop({ - location_type: 0, - stop_name: 'Platform', - pathways_from_stop: [ - { id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }, - { id: 101, from_stop: { id: 1 }, to_stop: { id: 3 } } - ], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'do not transit through platforms')).toBe(true) - }) - - test('no warning when platform has exactly 1 pathway', () => { - const stop = makeStop({ - location_type: 0, - stop_name: 'Platform', - pathways_from_stop: [{ id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'do not transit through platforms')).toBe(false) - }) - }) - - describe('boarding area pathway to parent', () => { - test('info when boarding area has a pathway connecting to its parent', () => { - const stop = makeStop({ - id: 11, - location_type: 4, - stop_name: 'Boarding Area', - parent: { id: 10, location_type: 0 }, - pathways_from_stop: [{ id: 100, from_stop: { id: 11 }, to_stop: { id: 10 } }], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Boarding areas connect to their parent platform via the parent_station setting')).toBe(true) - }) - - test('no info when boarding area pathways do not connect to parent', () => { - const stop = makeStop({ - id: 11, - location_type: 4, - stop_name: 'Boarding Area', - parent: { id: 10, location_type: 0 }, - pathways_from_stop: [{ id: 100, from_stop: { id: 11 }, to_stop: { id: 20 } }], - pathways_to_stop: [] - }) - const errs = validateStop(stop, []) - expect(hasMessage(errs, 'Boarding areas connect to their parent platform via the parent_station setting')).toBe(false) - }) - }) - - describe('valid stop produces no unexpected errors', () => { - test('well-formed generic node with level and 2 pathways has no errors', () => { - const stop = makeStop({ - location_type: 3, - stop_name: 'Node', - geometry: { type: 'Point', coordinates: [-122.0, 37.0] }, - level: { id: 10, level_name: 'Ground' }, - pathways_from_stop: [{ id: 100, from_stop: { id: 1 }, to_stop: { id: 2 } }], - pathways_to_stop: [{ id: 101, from_stop: { id: 3 }, to_stop: { id: 1 } }], - parent: { id: 5, location_type: 1 } - }) - const errs = validateStop(stop, []) - expect(errs).toEqual([]) - }) - }) -}) - -describe('validatePathway', () => { - describe('pathway endpoint is station', () => { - test('error when from_stop is a station (location_type=1)', () => { - const pw = makePathway({ - from_stop: { id: 1, stop_id: 'station', location_type: 1, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 2, stop_id: 'node', location_type: 3, level: { id: 10, level_name: 'G' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Pathway endpoints must not be stations')).toBe(true) - expect(errs.find(e => e.message.includes('must not be stations'))?.severity).toBe('critical') - }) - - test('error when to_stop is a station (location_type=1)', () => { - const pw = makePathway({ - from_stop: { id: 1, stop_id: 'node', location_type: 3, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 2, stop_id: 'station', location_type: 1, level: { id: 10, level_name: 'G' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Pathway endpoints must not be stations')).toBe(true) - }) - - test('no error when endpoints are valid location types', () => { - const pw = makePathway({ - from_stop: { id: 1, stop_id: 'entrance', location_type: 2, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 2, stop_id: 'node', location_type: 3, level: { id: 11, level_name: 'U' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'must not be stations')).toBe(false) - }) - }) - - describe('pathway to platform with boarding areas', () => { - test('error when from_stop is a platform with boarding areas', () => { - const pw = makePathway({ - from_stop: { id: 10, stop_id: 'platform', stop_name: 'Platform A', location_type: 0, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 20, stop_id: 'node', location_type: 3, level: { id: 10, level_name: 'G' } } - }) - const boardingArea = makeStop({ id: 11, location_type: 4, stop_name: 'BA', parent: { id: 10, location_type: 0 } }) - const errs = validatePathway(pw, [makeStop({ id: 10, location_type: 0 }), boardingArea]) - expect(hasMessage(errs, 'which has boarding areas')).toBe(true) - expect(errs.find(e => e.message.includes('boarding areas'))?.severity).toBe('critical') - }) - - test('error when to_stop is a platform with boarding areas', () => { - const pw = makePathway({ - from_stop: { id: 20, stop_id: 'node', location_type: 3, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 10, stop_id: 'platform', stop_name: 'Platform A', location_type: 0, level: { id: 10, level_name: 'G' } } - }) - const boardingArea = makeStop({ id: 11, location_type: 4, stop_name: 'BA', parent: { id: 10, location_type: 0 } }) - const errs = validatePathway(pw, [makeStop({ id: 10, location_type: 0 }), boardingArea]) - expect(hasMessage(errs, 'which has boarding areas')).toBe(true) - }) - - test('no error when platform has no boarding areas', () => { - const pw = makePathway({ - from_stop: { id: 10, stop_id: 'platform', location_type: 0, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 20, stop_id: 'node', location_type: 3, level: { id: 11, level_name: 'U' } } - }) - const errs = validatePathway(pw, [makeStop({ id: 10, location_type: 0 })]) - expect(hasMessage(errs, 'boarding areas')).toBe(false) - }) - - test('no error when stationStops not provided', () => { - const pw = makePathway({ - from_stop: { id: 10, stop_id: 'platform', location_type: 0, level: { id: 10, level_name: 'G' } }, - to_stop: { id: 20, stop_id: 'node', location_type: 3, level: { id: 11, level_name: 'U' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'boarding areas')).toBe(false) - }) - }) - - describe('pathway loop', () => { - test('error when from_stop and to_stop are the same', () => { - const pw = makePathway({ - from_stop: { id: 1, stop_id: 'a', level: { id: 10, level_name: 'G' } }, - to_stop: { id: 1, stop_id: 'a', level: { id: 10, level_name: 'G' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'pathway is a loop')).toBe(true) - }) - - test('no error when from_stop and to_stop differ', () => { - const pw = makePathway() - const errs = validatePathway(pw) - expect(hasMessage(errs, 'pathway is a loop')).toBe(false) - }) - }) - - describe('endpoint level assignments', () => { - test('critical error when elevator from_stop has no level', () => { - const pw = makePathway({ - pathway_mode: 5, - from_stop: { id: 1, stop_id: 'from' }, - to_stop: { id: 2, stop_id: 'to', level: { id: 11, level_name: 'Upper' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Elevator pathway endpoint stops must have level assignments')).toBe(true) - expect(errs.find(e => e.message.includes('Elevator'))?.severity).toBe('critical') - }) - - test('critical error when elevator to_stop has no level', () => { - const pw = makePathway({ - pathway_mode: 5, - from_stop: { id: 1, stop_id: 'from', level: { id: 10, level_name: 'Ground' } }, - to_stop: { id: 2, stop_id: 'to' } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Elevator pathway endpoint stops must have level assignments')).toBe(true) - expect(errs.find(e => e.message.includes('Elevator'))?.severity).toBe('critical') - }) - - test('interline error when non-elevator from_stop has no level', () => { - const pw = makePathway({ - pathway_mode: 1, - from_stop: { id: 1, stop_id: 'from' }, - to_stop: { id: 2, stop_id: 'to', level: { id: 11, level_name: 'Upper' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Interline recommendation: pathway endpoint stops should have level assignments')).toBe(true) - expect(errs.find(e => e.message.includes('endpoint stops'))?.severity).toBe('interline') - }) - - test('no error when both stops have levels', () => { - const pw = makePathway() - const errs = validatePathway(pw) - expect(hasMessage(errs, 'level assignments')).toBe(false) - }) - }) - - describe('exit-gate bidirectional', () => { - test('error when exit-gate (mode=7) is bidirectional', () => { - const pw = makePathway({ pathway_mode: 7, is_bidirectional: 1 }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Exit-gate pathways must be one-way')).toBe(true) - }) - - test('no error when exit-gate is one-way', () => { - const pw = makePathway({ pathway_mode: 7, is_bidirectional: 0 }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Exit-gate pathways must be one-way')).toBe(false) - }) - - test('no error when non-exit-gate is bidirectional', () => { - const pw = makePathway({ pathway_mode: 1, is_bidirectional: 1 }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'Exit-gate pathways must be one-way')).toBe(false) - }) - }) - - describe('stairs stair_count', () => { - test('error when stairs on same level have no stair_count', () => { - const pw = makePathway({ - pathway_mode: 2, - stair_count: undefined, - from_stop: { id: 1, stop_id: 'from', level: { id: 10, level_name: 'Ground' } }, - to_stop: { id: 2, stop_id: 'to', level: { id: 10, level_name: 'Ground' } } - }) - // stair_count defaults to undefined from constructor; set to null to match the check - pw.stair_count = null as any - const errs = validatePathway(pw) - expect(hasMessage(errs, 'stairs pathways should have a stair_count')).toBe(true) - }) - - test('no error when stairs connect different levels without stair_count', () => { - const pw = makePathway({ - pathway_mode: 2, - stair_count: undefined, - from_stop: { id: 1, stop_id: 'from', level: { id: 10, level_name: 'Ground' } }, - to_stop: { id: 2, stop_id: 'to', level: { id: 11, level_name: 'Upper' } } - }) - pw.stair_count = null as any - const errs = validatePathway(pw) - expect(hasMessage(errs, 'stairs pathways should have a stair_count')).toBe(false) - }) - - test('no error when stairs have a stair_count', () => { - const pw = makePathway({ - pathway_mode: 2, - stair_count: 12, - from_stop: { id: 1, stop_id: 'from', level: { id: 10, level_name: 'Ground' } }, - to_stop: { id: 2, stop_id: 'to', level: { id: 10, level_name: 'Ground' } } - }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'stairs pathways should have a stair_count')).toBe(false) - }) - }) - - describe('length and traversal_time', () => { - test('info when length is missing (default options)', () => { - const pw = makePathway({ length: undefined }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'missing a length value')).toBe(true) - expect(errs.find(e => e.message.includes('length'))?.severity).toBe('info') - }) - - test('info when traversal_time is missing (default options)', () => { - const pw = makePathway({ traversal_time: undefined }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'missing a traversal_time value')).toBe(true) - expect(errs.find(e => e.message.includes('traversal_time'))?.severity).toBe('info') - }) - - test('no error when length and traversal_time are present', () => { - const pw = makePathway({ length: 50, traversal_time: 30 }) - const errs = validatePathway(pw) - expect(hasMessage(errs, 'missing a length')).toBe(false) - expect(hasMessage(errs, 'missing a traversal_time')).toBe(false) - }) - - test('no error when requireLengthAndTraversalTime is false', () => { - const pw = makePathway({ length: undefined, traversal_time: undefined }) - const errs = validatePathway(pw, [], { requireLengthAndTraversalTime: false }) - expect(hasMessage(errs, 'missing a length')).toBe(false) - expect(hasMessage(errs, 'missing a traversal_time')).toBe(false) - }) - }) - - describe('valid pathway produces no errors', () => { - test('well-formed walkway has no errors', () => { - const pw = makePathway({ - pathway_mode: 1, - is_bidirectional: 1, - length: 50, - traversal_time: 30 - }) - const errs = validatePathway(pw) - expect(errs).toEqual([]) - }) - - test('well-formed walkway has no errors with editor options', () => { - const pw = makePathway({ - pathway_mode: 1, - is_bidirectional: 1 - }) - const errs = validatePathway(pw, [], { requireLengthAndTraversalTime: false }) - expect(errs).toEqual([]) - }) - }) -}) - -describe('validateConnectivity', () => { - test('returns empty when no entrances exist', () => { - const station = new Station() - // Add only generic nodes, no entrances - station.addStops([ - makeStop({ id: 1, location_type: 3 }), - makeStop({ id: 2, location_type: 3 }) - ]) - const results = validateConnectivity(station) - expect(results).toEqual([]) - }) - - test('returns results when entrance cannot reach other stops', () => { - const entrance = makeStop({ - id: 1, - location_type: 2, - stop_name: 'Entrance', - pathways_from_stop: [], - pathways_to_stop: [] - }) - const platform = makeStop({ - id: 2, - location_type: 0, - stop_name: 'Platform', - pathways_from_stop: [], - pathways_to_stop: [] - }) - const station = new Station() - station.addStops([entrance, platform]) - const results = validateConnectivity(station) - expect(results.length).toBeGreaterThan(0) - expect(results[0]?.stop.id).toBe(1) - }) - - test('returns empty when all stops are reachable from entrance', () => { - const entrance = makeStop({ - id: 1, - location_type: 2, - stop_name: 'Entrance', - geometry: { type: 'Point', coordinates: [-122.0, 37.0] }, - pathways_from_stop: [{ - id: 100, - pathway_id: 'pw-1', - pathway_mode: 1, - is_bidirectional: 1, - from_stop: { id: 1 }, - to_stop: { id: 2 } - }], - pathways_to_stop: [] - }) - const platform = makeStop({ - id: 2, - location_type: 0, - stop_name: 'Platform', - geometry: { type: 'Point', coordinates: [-122.001, 37.0] }, - pathways_from_stop: [], - pathways_to_stop: [{ - id: 100, - pathway_id: 'pw-1', - pathway_mode: 1, - is_bidirectional: 1, - from_stop: { id: 1 }, - to_stop: { id: 2 } - }] - }) - const station = new Station() - station.addStops([entrance, platform]) - const results = validateConnectivity(station) - // All paths should have info (OK) messages, so no error paths → empty result - expect(results.every(r => r.paths.every(p => p.info))).toBe(true) - }) -}) diff --git a/src/runtime/apps/stations/station-validation.ts b/src/runtime/apps/stations/station-validation.ts deleted file mode 100644 index 2deccc48..00000000 --- a/src/runtime/apps/stations/station-validation.ts +++ /dev/null @@ -1,220 +0,0 @@ -import type { Stop, Pathway, Station } from './station' -import type { ValidationPath } from './types' - -export type ValidationSeverity = 'critical' | 'info' | 'interline' - -export interface ValidationError { - message: string - severity: ValidationSeverity -} - -export interface ValidationOptions { - requireLengthAndTraversalTime?: boolean -} - -export function validateStop (stop: Stop, stationStops: Stop[], _options: ValidationOptions = {}): ValidationError[] { - const fromPathways = stop.pathways_from_stop || [] - const toPathways = stop.pathways_to_stop || [] - const targetStop = stop.external_reference?.target_active_stop || null - const errs: ValidationError[] = [] - if (stop.location_type !== 3 && (!stop.stop_name || stop.stop_name.trim() === '')) { - errs.push({ - severity: 'critical', - message: 'Stop name is required for all location types except generic nodes (location_type = 3)' - }) - } - if (stop.location_type !== 3 && (!stop.geometry || !stop.geometry.coordinates)) { - errs.push({ - severity: 'critical', - message: 'Coordinates are required for all location types except generic nodes (location_type = 3)' - }) - } - if (stop.location_type === 3 && (!stop.geometry || !stop.geometry.coordinates)) { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: generic nodes should have coordinates to enable visualization and pathway maintenance' - }) - } - if (!stop.level?.id) { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: stop should have a level assignment' - }) - } - if (stop.location_type === 0 && !targetStop) { - // errs.push({ - // message: 'Platform (location_type = 0) must have a stop association' - // }) - } - if (targetStop && targetStop.location_type !== stop.location_type) { - errs.push({ - severity: 'interline', - message: `Interline recommendation: stop must have the same location_type as the target stop (location_type = ${targetStop.location_type})` - }) - } - // if (stop.location_type === 2 && !stop.external_reference?.target_active_stop) { - // errs.push({ - // message: 'Entrance (location_type = 2) must have a stop association' - // }) - // } - if (stop.location_type === 1 && (fromPathways.length > 0 || toPathways.length > 0)) { - errs.push({ - severity: 'critical', - message: 'Pathways cannot use Station (location_type = 1)' - }) - } - if (stop.parent?.id && stop.parent.id === stop.id) { - errs.push({ - severity: 'critical', - message: 'Cannot have self as parent_station' - }) - } - if (stop.location_type !== 4 && stop.parent?.id && stop.parent.location_type !== 1) { - errs.push({ - severity: 'critical', - message: 'The parent_station must be a Station (location_type = 1)' - }) - } - if ( - (stop.location_type === 4 && stop.parent === null) || (stop.location_type === 4 && stop.parent && stop.parent.location_type !== 0) - ) { - errs.push({ - severity: 'critical', - message: 'Boarding areas require a Platform (location_type = 0) as a parent_station' - }) - } - if (stop.external_reference && stop.external_reference.target_active_stop === null) { - errs.push({ - severity: 'interline', - message: `Interline recommendation: cannot resolve reference to stop ${stop.external_reference.target_feed_onestop_id}:${stop.external_reference.target_stop_id}` - }) - } - const hasBoardingAreas = stop.location_type === 0 && stationStops.some(s => s.location_type === 4 && s.parent?.id === stop.id) - if (stop.location_type !== 1 && !hasBoardingAreas && fromPathways.length === 0 && toPathways.length === 0) { - errs.push({ - severity: 'critical', - message: 'All locations within a station require at least one connecting pathway, except platforms with boarding areas' - }) - } - if (stop.location_type === 3 && (fromPathways.length + toPathways.length < 2)) { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: generic nodes should connect to at least two pathways so a rider can transit through the node to another node' - }) - } - if (stop.location_type === 0) { - if (hasBoardingAreas && (fromPathways.length + toPathways.length > 0)) { - errs.push({ - severity: 'critical', - message: 'Platforms with boarding areas must not have pathways; assign pathways to the boarding areas instead' - }) - } else if (!hasBoardingAreas && (fromPathways.length + toPathways.length > 1)) { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: do not transit through platforms' - }) - } - } - if (stop.location_type === 4 && stop.parent?.id) { - const allPathways = [...fromPathways, ...toPathways] - const hasParentPathway = allPathways.some(pw => pw.from_stop.id === stop.parent!.id || pw.to_stop.id === stop.parent!.id) - if (hasParentPathway) { - errs.push({ - severity: 'info', - message: 'Boarding areas connect to their parent platform via the parent_station setting, not via drawn pathways' - }) - } - } - return errs -} - -export function validatePathway (pathway: Pathway, stationStops: Stop[] = [], options: ValidationOptions = {}): ValidationError[] { - const { requireLengthAndTraversalTime = true } = options - const errs: ValidationError[] = [] - if (pathway.from_stop.location_type === 1 || pathway.to_stop.location_type === 1) { - errs.push({ - severity: 'critical', - message: 'Pathway endpoints must not be stations (location_type = 1)' - }) - } - for (const endpoint of [pathway.from_stop, pathway.to_stop]) { - if (endpoint.location_type === 0) { - const hasBoardingAreas = stationStops.some(s => s.location_type === 4 && s.parent?.id === endpoint.id) - if (hasBoardingAreas) { - errs.push({ - severity: 'critical', - message: `Pathway must not target platform "${endpoint.stop_name || endpoint.stop_id}" which has boarding areas; assign pathways to the boarding areas instead` - }) - } - } - } - if (pathway.from_stop.id === pathway.to_stop.id) { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: pathway is a loop — from_stop_id should not equal to_stop_id' - }) - } - if (!pathway.from_stop.level?.id || !pathway.to_stop.level?.id) { - if (pathway.pathway_mode === 5) { - errs.push({ - severity: 'critical', - message: 'Elevator pathway endpoint stops must have level assignments (GTFS spec: levels.txt is required for pathway_mode=5)' - }) - } else { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: pathway endpoint stops should have level assignments' - }) - } - } - if (requireLengthAndTraversalTime) { - if (!pathway.length || pathway.length === 0) { - errs.push({ - severity: 'info', - message: 'Pathway is missing a length value' - }) - } - if (!pathway.traversal_time || pathway.traversal_time === 0) { - errs.push({ - severity: 'info', - message: 'Pathway is missing a traversal_time value' - }) - } - } - if (pathway.pathway_mode === 7 && pathway.is_bidirectional === 1) { - errs.push({ - severity: 'critical', - message: 'Exit-gate pathways must be one-way' - }) - } - if (pathway.pathway_mode === 2 && pathway.stair_count === null) { - if (pathway.from_stop.level?.id !== pathway.to_stop.level?.id) { - // ok - } else { - errs.push({ - severity: 'interline', - message: 'Interline recommendation: stairs pathways should have a stair_count or connect stops with different levels' - }) - } - } - return errs -} - -export interface ConnectivityResult { - stop: Stop - paths: ValidationPath[] -} - -export function validateConnectivity (station: Station): ConnectivityResult[] { - const ret: ConnectivityResult[] = [] - const entrances = station.stops.filter(s => s.location_type === 2) - const mustReach = station.stops.filter(s => s.location_type !== 1) - for (const stop of entrances) { - const paths = station.validatePathsToStops(stop, mustReach) - .filter(path => path.target.id !== stop.id) - if (paths.length > 0) { - ret.push({ stop, paths }) - } - } - return ret -} diff --git a/src/runtime/apps/stations/station-validator.vue b/src/runtime/apps/stations/station-validator.vue deleted file mode 100644 index 12d6f036..00000000 --- a/src/runtime/apps/stations/station-validator.vue +++ /dev/null @@ -1,272 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/station.spec.ts b/src/runtime/apps/stations/station.spec.ts deleted file mode 100644 index bf084ff5..00000000 --- a/src/runtime/apps/stations/station.spec.ts +++ /dev/null @@ -1,369 +0,0 @@ -import { describe, test, expect, beforeEach } from 'vitest' -import { Stop, Pathway, Station } from './station' -import { WheelchairProfile } from '../../lib/pathways/graph' -import type { StopData, PathwayData } from './types' - -// ─── Factories ──────────────────────────────────────────────────────────────── - -function makeStop (id: number, overrides: Partial = {}): Stop { - return new Stop({ - id, - stop_id: `stop-${id}`, - stop_name: `Stop ${id}`, - location_type: 3, - geometry: { type: 'Point', coordinates: [-122.0 + id * 0.001, 37.0] }, - pathways_from_stop: [], - pathways_to_stop: [], - ...overrides - }) -} - -// Stops co-located at origin — heuristic is 0 for all pairs, so A* behaves -// like Dijkstra and only traversal_time determines path cost. -function makeColocatedStop (id: number, overrides: Partial = {}): Stop { - return makeStop(id, { geometry: { type: 'Point', coordinates: [0, 0] }, ...overrides }) -} - -let nextPwId = 0 - -// Creates a Pathway and links it into the from/to stop lists. -function connectStops (fromStop: Stop, toStop: Stop, overrides: Partial = {}): Pathway { - const id = ++nextPwId - const pw = new Pathway({ - id, - pathway_id: `pw-${id}`, - pathway_mode: 1, - is_bidirectional: 1, - from_stop: { id: fromStop.id }, - to_stop: { id: toStop.id }, - ...overrides - }) - fromStop.pathways_from_stop.push(pw) - toStop.pathways_to_stop.push(pw) - return pw -} - -function makeStation (id = 100): Station { - return new Station({ - id, - stop_id: 'station', - stop_name: 'Station', - location_type: 1, - geometry: { type: 'Point', coordinates: [-122.0, 37.0] } - }) -} - -// ─── Station.findRoute ──────────────────────────────────────────────────────── - -describe('Station.findRoute', () => { - beforeEach(() => { nextPwId = 0 }) - - test('returns undefined when no stops are loaded', () => { - const station = makeStation() - expect(station.findRoute(1, 2)).toBeUndefined() - }) - - test('finds a direct route between two connected stops', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - station.addStops([a, b]) - - const result = station.findRoute(1, 2) - expect(result).toBeDefined() - expect(result!.path).toEqual([1, 2]) - expect(result!.distance).toBeGreaterThan(0) - }) - - test('finds a multi-hop route through intermediate stops', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - const c = makeStop(3) - connectStops(a, b) - connectStops(b, c) - station.addStops([a, b, c]) - - const result = station.findRoute(1, 3) - expect(result).toBeDefined() - expect(result!.path).toEqual([1, 2, 3]) - }) - - test('returns empty path when no route exists between disconnected stops', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - station.addStops([a, b]) // no pathway - - const result = station.findRoute(1, 2) - expect(result!.path).toHaveLength(0) - expect(result!.distance).toBeNull() - }) - - test('one-directional pathway: can travel forward but not in reverse', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b, { is_bidirectional: 0 }) - station.addStops([a, b]) - - expect(station.findRoute(1, 2)!.path).toEqual([1, 2]) - expect(station.findRoute(2, 1)!.path).toHaveLength(0) - }) - - test('bidirectional pathway allows travel in both directions', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b, { is_bidirectional: 1 }) - station.addStops([a, b]) - - expect(station.findRoute(1, 2)!.path).toEqual([1, 2]) - expect(station.findRoute(2, 1)!.path).toEqual([2, 1]) - }) - - test('returns error result for unknown stop IDs', () => { - const station = makeStation() - station.addStops([makeStop(1)]) - - const result = station.findRoute(1, 999) - expect(result!.error).toBeTruthy() - expect(result!.path).toHaveLength(0) - }) - - test('uses traversal_time directly as edge cost', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b, { traversal_time: 42 }) - station.addStops([a, b]) - - const result = station.findRoute(1, 2) - expect(result!.distance).toBe(42) - }) - - test('finds the lower-cost path when multiple routes exist', () => { - const station = makeStation() - const a = makeColocatedStop(1) - const b = makeColocatedStop(2) - const mid = makeColocatedStop(3) - connectStops(a, b, { traversal_time: 100 }) // expensive direct - connectStops(a, mid, { traversal_time: 1 }) - connectStops(mid, b, { traversal_time: 1 }) - station.addStops([a, b, mid]) - - const result = station.findRoute(1, 2) - expect(result!.path).toEqual([1, 3, 2]) - expect(result!.distance).toBe(2) - }) - - test('WheelchairProfile blocks stairs (pathway_mode 2)', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b, { pathway_mode: 2 }) - station.addStops([a, b]) - - expect(station.findRoute(1, 2)!.path).toEqual([1, 2]) - expect(station.findRoute(1, 2, WheelchairProfile)!.path).toHaveLength(0) - }) - - test('WheelchairProfile falls back to accessible pathway when stairs are blocked', () => { - const station = makeStation() - const a = makeColocatedStop(1) - const b = makeColocatedStop(2) - const mid = makeColocatedStop(3) - connectStops(a, b, { pathway_mode: 2, traversal_time: 1 }) // stairs — blocked - connectStops(a, mid, { pathway_mode: 1, traversal_time: 2 }) - connectStops(mid, b, { pathway_mode: 1, traversal_time: 2 }) - station.addStops([a, b, mid]) - - const result = station.findRoute(1, 2, WheelchairProfile) - expect(result!.path).toEqual([1, 3, 2]) - }) - - test('includes pathway edges with IDs and costs in the result', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b, { traversal_time: 10 }) - station.addStops([a, b]) - - const result = station.findRoute(1, 2) - expect(result!.edges).toHaveLength(1) - const edge = result!.edges![0]! - expect(edge.pathway_id).toBe(pw.id) - expect(edge.from_stop_id).toBe(1) - expect(edge.to_stop_id).toBe(2) - expect(edge.cost).toBe(10) - }) - - test('caches the routing graph for the same profile', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - station.addStops([a, b]) - - station.findRoute(1, 2) - const firstGraph = station.graph - - station.findRoute(2, 1) - expect(station.graph).toBe(firstGraph) // same reference - }) - - test('rebuilds the routing graph when profile changes', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - station.addStops([a, b]) - - station.findRoute(1, 2) - const firstGraph = station.graph - - station.findRoute(1, 2, WheelchairProfile) - expect(station.graph).not.toBe(firstGraph) - }) -}) - -// ─── Station.addStops ───────────────────────────────────────────────────────── - -describe('Station.addStops', () => { - beforeEach(() => { nextPwId = 0 }) - - test('sets this.stops to the provided stops, excluding the station stop', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - station.addStops([a, b]) - - expect(station.stops.map(s => s.id)).toEqual(expect.arrayContaining([1, 2])) - expect(station.stops.map(s => s.id)).not.toContain(100) - }) - - test('returns IDs to fetch including provided stop IDs and pathway endpoint IDs', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - const unloaded = makeStop(3) - connectStops(a, unloaded) // stop 3 not in addStops call - - const toFetch = station.addStops([a, b]) - - expect(toFetch).toContain(1) - expect(toFetch).toContain(2) - expect(toFetch).toContain(3) // discovered via pathway - expect(toFetch).not.toContain(100) // station stop excluded - }) - - test('includes station stop children in the IDs to fetch', () => { - const station = new Station({ - id: 100, - stop_id: 'station', - location_type: 1, - geometry: { type: 'Point', coordinates: [-122.0, 37.0] }, - children: [{ id: 1 }, { id: 2 }] - }) - - const toFetch = station.addStops([]) - expect(toFetch).toContain(1) - expect(toFetch).toContain(2) - expect(toFetch).not.toContain(100) - }) - - test('includes parent IDs in the IDs to fetch', () => { - const station = makeStation() - const a = makeStop(1, { parent: { id: 50 } }) - - const toFetch = station.addStops([a]) - expect(toFetch).toContain(50) - }) - - test('includes level-mate stop IDs in the IDs to fetch', () => { - const station = makeStation() - const a = makeStop(1, { - level: { id: 10, level_name: 'Ground', stops: [{ id: 99 }] } - }) - - const toFetch = station.addStops([a]) - expect(toFetch).toContain(99) - }) - - test('accumulates stops across multiple calls', () => { - const station = makeStation() - station.addStops([makeStop(1)]) - station.addStops([makeStop(2)]) - - expect(station.stops).toHaveLength(2) - expect(station.stops.map(s => s.id)).toEqual(expect.arrayContaining([1, 2])) - }) - - test('deduplicates stops when the same stop is provided more than once', () => { - const station = makeStation() - const a = makeStop(1) - station.addStops([a]) - station.addStops([a]) // second call with same stop - - expect(station.stops).toHaveLength(1) - }) - - test('indexes pathways from pathways_from_stop', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - const pw = connectStops(a, b) - station.addStops([a, b]) - - expect(station.pathways).toHaveLength(1) - expect(station.pathways[0]!.id).toBe(pw.id) - }) - - test('does not duplicate a pathway that appears in both from and to stop lists', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) // pw in a.pathways_from_stop AND b.pathways_to_stop - station.addStops([a, b]) - - expect(station.pathways).toHaveLength(1) - }) - - test('groups stops into their assigned levels', () => { - const station = makeStation() - const a = makeStop(1, { level: { id: 10, level_name: 'Ground', level_index: 0 } }) - const b = makeStop(2, { level: { id: 10, level_name: 'Ground', level_index: 0 } }) - const c = makeStop(3, { level: { id: 20, level_name: 'Mezzanine', level_index: 1 } }) - station.addStops([a, b, c]) - - const ground = station.levels.find(l => l.id === 10) - const mezz = station.levels.find(l => l.id === 20) - expect(ground?.stops.map(s => s.id)).toEqual(expect.arrayContaining([1, 2])) - expect(mezz?.stops.map(s => s.id)).toEqual([3]) - }) - - test('stops without a level go into the unassigned level', () => { - const station = makeStation() - const a = makeStop(1) // no level override → Unassigned - station.addStops([a]) - - const unassigned = station.levels.find(l => !l.id) - expect(unassigned).toBeDefined() - expect(unassigned!.stops.map(s => s.id)).toContain(1) - }) - - test('invalidates the routing graph cache after update', () => { - const station = makeStation() - const a = makeStop(1) - const b = makeStop(2) - connectStops(a, b) - station.addStops([a, b]) - - station.findRoute(1, 2) // builds graph - expect(station.graph).not.toBeNull() - - station.addStops([makeStop(3)]) // should invalidate - expect(station.graph).toBeNull() - }) -}) diff --git a/src/runtime/apps/stations/station.ts b/src/runtime/apps/stations/station.ts deleted file mode 100644 index 70c87968..00000000 --- a/src/runtime/apps/stations/station.ts +++ /dev/null @@ -1,674 +0,0 @@ -import { gql } from 'graphql-tag' -import type { DocumentNode } from 'graphql' -import type { Point, MultiPolygon } from 'geojson' -import { RoutingGraph, DefaultCost } from '../../lib/pathways/graph' -import type { CostFunction, AStarResult } from '../../lib/pathways/graph' -import type { - FeedVersionData, - FeedInfo, - StopData, - PathwayData, - LevelData, - RouteStopData, - StopExternalReferenceData, - ValidationPath -} from './types' - -export const stationQuery: DocumentNode = gql` -fragment level on Level { - id - level_id - level_name - level_index - geometry -} - -query stationQuery ($stop_id: String, $feed_onestop_id: String!, $feed_version_ids: [Int!]) { - feed_versions(ids: $feed_version_ids, where: {feed_onestop_id: $feed_onestop_id}) { - stops(limit: 1, where: {stop_id: $stop_id}) { - id - stop_id - stop_name - location_type - geometry - children(limit:1000) { - id - location_type - } - parent { - id - location_type - } - level { - ...level - } - child_levels { - ...level - } - feed_version { - id - sha1 - file - feed { - id - name - onestop_id - } - } - } - } -}` - -export const stationStopQuery: DocumentNode = gql` -fragment pathwayStop on Stop { - id - stop_id - stop_name - geometry - location_type - platform_code - level { - id - level_id - level_name - level_index - } - parent { - id - } - feed_version { - id - feed { - id - onestop_id - } - } -} - -fragment childStop on Stop { - id - stop_id - stop_name - location_type - geometry - level { - id - } - feed_version { - id - feed { - id - onestop_id - } - } -} - -fragment level on Level { - id - level_id - level_name - level_index - geometry -} - -fragment pathway on Pathway { - id - pathway_id - is_bidirectional - pathway_mode - stair_count - signposted_as - reverse_signposted_as - length - traversal_time - min_width - max_slope - from_stop { - ...pathwayStop - } - to_stop { - ...pathwayStop - } -} - -query stationStopQuery($stop_ids: [Int!]!) { - stops(ids: $stop_ids, limit:1000) { - id - stop_id - stop_name - location_type - stop_code - stop_timezone - zone_id - wheelchair_boarding - stop_desc - platform_code - geometry - feed_version { - id - feed { - id - onestop_id - } - } - level { - ...level - stops { - id - } - } - parent { - ...childStop - } - children { - ...childStop - } - pathways_to_stop { - ...pathway - } - pathways_from_stop { - ...pathway - } - route_stops { - route { - id - route_type - route_short_name - route_long_name - agency { - id - agency_id - agency_name - } - } - } - external_reference { - id - target_stop_id - target_feed_onestop_id - target_active_stop { - ...childStop - route_stops { - route { - id - route_short_name - route_long_name - agency { - id - agency_id - agency_name - } - } - } - } - } - } -}` - -export function mapLevelKeyFn (level: LevelData): string { - return `mapLevelKey-${level.id || 'unassigned'}` -} - -function def (v: T | null | undefined, d: T): T { - if (v == null) { - return d - } - return v -} - -// Helper function to build route keys with prefix -export function getRouteKeys (prefix = 'editor'): Record { - return { - levels: `${prefix}-feedKey-feedVersionKey-stations-stationKey`, - stops: `${prefix}-feedKey-feedVersionKey-stations-stationKey-stops`, - pathways: `${prefix}-feedKey-feedVersionKey-stations-stationKey-pathways`, - diagram: `${prefix}-feedKey-feedVersionKey-stations-stationKey-diagram` - } -} - -export class FeedVersion { - id?: number - fetched_at?: string - name?: string - sha1?: string - file?: string - earliest_calendar_date?: string - latest_calendar_date?: string - feed: FeedInfo - - constructor (fv?: FeedVersionData) { - fv = fv || {} - this.id = fv.id - this.fetched_at = fv.fetched_at - this.name = fv.name - this.sha1 = fv.sha1 - this.file = fv.file - this.earliest_calendar_date = fv.earliest_calendar_date - this.latest_calendar_date = fv.latest_calendar_date - this.feed = {} - if (fv.feed) { - this.feed.id = fv.feed.id - this.feed.onestop_id = fv.feed.onestop_id - } - } -} - -export class Stop { - id?: number - stop_id?: string - stop_name?: string - stop_code?: string - platform_code?: string - stop_timezone?: string - zone_id?: string - wheelchair_boarding?: number - stop_desc?: string - stop_url?: string - geometry?: Point - location_type?: number - route_stops: RouteStopData[] - parent: Partial - children: Stop[] - level: Level - levels: Level[] - pathways_from_stop: Pathway[] - pathways_to_stop: Pathway[] - feed_version: FeedVersion - external_reference?: StopExternalReferenceData - - constructor (stop?: StopData) { - stop = stop || {} - this.id = stop.id - this.stop_id = stop.stop_id - this.stop_name = stop.stop_name - this.stop_code = stop.stop_code - this.platform_code = stop.platform_code - this.stop_timezone = stop.stop_timezone - this.zone_id = stop.zone_id - this.wheelchair_boarding = stop.wheelchair_boarding - this.stop_desc = stop.stop_desc - if (stop.geometry) { - this.geometry = { type: 'Point', coordinates: stop.geometry.coordinates } - } - this.location_type = stop.location_type - - // objects - this.route_stops = stop.route_stops || [] - this.parent = { id: undefined } - if (stop.parent) { - this.parent = new Stop(stop.parent) - } - this.children = [] - for (const c of (stop.children || [])) { - this.children.push(new Stop(c)) - } - - // levels - if (stop.level) { - this.level = new Level(stop.level) - } else { - this.level = new Level({ level_name: 'Unassigned' }) - } - - // Child levels - this.levels = [] - if (stop.child_levels) { - this.levels = stop.child_levels.map((s) => { return new Level(s) }) - } - - // pathways - this.pathways_from_stop = (stop.pathways_from_stop || []).map((s) => { return new Pathway(s) }) - this.pathways_to_stop = (stop.pathways_to_stop || []).map((s) => { return new Pathway(s) }) - - // feed version - this.feed_version = new FeedVersion(stop.feed_version) - - // stop ext - this.external_reference = stop.external_reference - } - - setCoords (lon: number, lat: number): void { - if (this.geometry) { - this.geometry.coordinates = [lon, lat] - } - } - - setDefaults (): this { - this.stop_id = def(this.stop_id, String(Date.now())) - this.stop_name = def(this.stop_name, '') - this.stop_code = def(this.stop_code, '') - this.platform_code = def(this.platform_code, '') - this.stop_desc = def(this.stop_desc, '') - this.zone_id = def(this.zone_id, '') - this.stop_url = def(this.stop_url, '') - this.stop_timezone = def(this.stop_timezone, '') - this.location_type = def(this.location_type, 3) - this.wheelchair_boarding = def(this.wheelchair_boarding, 0) - return this - } - - value (): Record { - return { - id: this.id, - stop_id: this.stop_id, - stop_name: this.stop_name, - stop_code: this.stop_code, - platform_code: this.platform_code, - stop_timezone: this.stop_timezone, - zone_id: this.zone_id, - stop_url: this.stop_url, - wheelchair_boarding: this.wheelchair_boarding, - stop_desc: this.stop_desc, - geometry: this.geometry, - location_type: this.location_type, - parent: this.parent?.id ? { id: this.parent.id } : { id: null }, - level: this.level?.id ? { id: this.level.id } : { id: null }, - feed_version: { id: this.feed_version.id }, - external_reference: this.external_reference - ? { - target_feed_onestop_id: this.external_reference?.target_feed_onestop_id || null, - target_stop_id: this.external_reference?.target_stop_id || null, - } - : null - } - } -} - -export class Pathway { - id?: number - length?: number - pathway_id?: string - pathway_mode?: number - max_slope?: number - min_width?: number - signposted_as?: string - reverse_signposted_as?: string - stair_count?: number - traversal_time?: number - is_bidirectional?: number - from_stop: Stop - to_stop: Stop - feed_version: Partial - - constructor (pw?: PathwayData) { - pw = pw || {} - this.id = pw.id - this.length = pw.length - this.pathway_id = pw.pathway_id - this.pathway_mode = pw.pathway_mode - this.max_slope = pw.max_slope - this.min_width = pw.min_width - this.signposted_as = pw.signposted_as - this.reverse_signposted_as = pw.reverse_signposted_as - this.stair_count = pw.stair_count - this.traversal_time = pw.traversal_time - this.is_bidirectional = pw.is_bidirectional - // objects - this.from_stop = new Stop(pw.from_stop) - this.to_stop = new Stop(pw.to_stop) - this.feed_version = new FeedVersion(pw.from_stop?.feed_version) - } - - setDefaults (): this { - this.feed_version = { id: def(this.feed_version.id, this.from_stop.feed_version.id) } - // length, max_slope, min_width, stair_count, traversal_time are optional - keep as-is - this.pathway_id = def(this.pathway_id, String(Date.now())) - this.pathway_mode = def(this.pathway_mode, 1) - this.signposted_as = def(this.signposted_as, '') - this.reverse_signposted_as = def(this.reverse_signposted_as, '') - this.is_bidirectional = def(this.is_bidirectional, 1) - return this - } - - value (): Record { - // Convert empty strings to undefined for numeric fields to avoid GraphQL validation errors - const toNumber = (val: any): number | undefined => { - if (val === '' || val === null || val === undefined) return undefined - const num = Number(val) - return Number.isNaN(num) ? undefined : num - } - - return { - id: this.id, - length: toNumber(this.length), - pathway_id: this.pathway_id, - pathway_mode: this.pathway_mode, - max_slope: toNumber(this.max_slope), - min_width: toNumber(this.min_width), - signposted_as: this.signposted_as, - reverse_signposted_as: this.reverse_signposted_as, - stair_count: toNumber(this.stair_count), - traversal_time: toNumber(this.traversal_time), - is_bidirectional: this.is_bidirectional, - from_stop: { id: this.from_stop.id }, - to_stop: { id: this.to_stop.id }, - feed_version: { id: this.feed_version.id } - } - } -} - -export class Level { - id?: number - level_id?: string - level_index?: number - level_name?: string - geometry?: MultiPolygon - feed_version: Partial - parent: Partial - stops: Stop[] - - constructor (lvl?: LevelData) { - lvl = lvl || {} - this.id = lvl.id - this.level_id = lvl.level_id - this.level_index = lvl.level_index - this.level_name = lvl.level_name - this.geometry = lvl.geometry - // objects - this.feed_version = { id: lvl.feed_version?.id } - this.parent = { id: lvl.parent?.id } - this.stops = [] - for (const s of (lvl.stops || [])) { - this.stops.push(new Stop(s)) - } - } - - setDefaults (): this { - this.level_index = def(this.level_index, 0.0) - this.level_name = def(this.level_name, String(Date.now())) - this.level_id = def(this.level_id, String(Date.now())) - return this - } - - value (): Record { - return { - id: this.id, - level_id: this.level_id, - level_index: this.level_index, - level_name: this.level_name, - geometry: this.geometry, - feed_version: { id: this.feed_version.id }, - parent: { id: this.parent?.id } - } - } -} - -export class Station { - client: string - graph: RoutingGraph | null - graphProfile: CostFunction | null - stop: Stop - pathways: Pathway[] - stops: Stop[] - levels: Level[] - - constructor (stop?: StopData) { - this.client = 'stationEditor' - this.graph = null - this.graphProfile = null - this.stop = new Stop(stop) - this.pathways = [] - this.stops = [] - this.levels = [] - for (const level of (this.stop.levels || [])) { - this.levels.push(new Level(level)) - } - // Only add an Unassigned level if one doesn't already exist - const hasUnassigned = this.levels.some(level => level.level_name === 'Unassigned' && level.level_index === null) - if (!hasUnassigned) { - this.levels.push(new Level({ level_name: 'Unassigned' })) - } - } - - get id (): number | undefined { - return this.stop.id - } - - get geometry (): Point | undefined { - return this.stop.geometry - } - - setDefaults (): this { - this.stop.location_type = 1 - this.stop.stop_name = def(this.stop.stop_name, String(Date.now())) - this.stop.stop_id = def(this.stop.stop_id, String(Date.now())) - this.stop.setDefaults() - return this - } - - getStop (stopId: number): Stop | null { - for (const stop of this.stops) { - if (stop.id === stopId) { - return stop - } - } - return null - } - - findRoute (start: number, goal: number, profile: CostFunction = DefaultCost): AStarResult | undefined { - if (this.stops.length === 0) { - return - } - if (!this.graph || this.graphProfile !== profile) { - this.graph = new RoutingGraph(this.stops, profile) - this.graphProfile = profile - } - return this.graph.aStar(start, goal) - } - - validatePathsToStops (source: Stop, targets: Stop[]): ValidationPath[] { - const paths: ValidationPath[] = [] - if (!source.id) { - return paths - } - for (const target of targets) { - if (!target.id) { - continue - } - const route = this.findRoute(source.id, target.id) - if (!route || route.path.length === 0) { - paths.push({ target, error: `no route between ${source.stop_name} (${source.id}) and ${target.stop_name} (${target.id})`, distance: route?.distance || 0 }) - } else { - paths.push({ target, info: `OK: route between ${source.stop_name} (${source.id}) and ${target.stop_name} (${target.id})`, distance: route.distance || 0 }) - } - } - return paths.sort((a, b) => { return b.distance - a.distance }) - } - - addStops (stops: Stop[]): number[] { - // Add these stops/levels to the station and return a list of new stops to fetch. - const currentStops = new Map() - if (this.stop.id) { - currentStops.set(this.stop.id, this.stop) - } - for (const i of this.stops) { - if (i.id) { - currentStops.set(i.id, i) - } - } - for (const i of stops) { - if (i.id) { - currentStops.set(i.id, i) - } - } - const pwIndex = new Map() - const checkStops = new Set() - for (const c of this.stop.children || []) { - if (c.id) { - checkStops.add(c.id) - } - } - for (const stop of stops) { - if (stop.parent?.id) { - checkStops.add(stop.parent.id) - } - for (const pw of stop.pathways_from_stop || []) { - if (pw.id && pw.to_stop.id) { - pwIndex.set(pw.id, pw) - checkStops.add(pw.to_stop.id) - } - } - for (const pw of stop.pathways_to_stop || []) { - if (pw.id && pw.from_stop.id) { - pwIndex.set(pw.id, pw) - checkStops.add(pw.from_stop.id) - } - } - for (const c of stop.children || []) { - if (c.id) { - checkStops.add(c.id) - } - } - for (const s of stop.level?.stops || []) { - if (s.id) { - checkStops.add(s.id) - } - } - } - const toFetch = new Set() - for (const i of checkStops) { - toFetch.add(i) - } - for (const i of currentStops.keys()) { - toFetch.add(i) - } - // remove self - if (this.stop.id) { - currentStops.delete(this.stop.id) - toFetch.delete(this.stop.id) - } - const newStops = Array.from(currentStops.values()) - // update levels - const lvls = new Map() - for (const lvl of this.levels || []) { - // Normalize null/undefined to a consistent key for unassigned levels - const levelKey = lvl.id ?? 'unassigned' - lvls.set(levelKey, lvl) - } - for (const stop of newStops) { - let lvl = stop.level - // Normalize null/undefined to a consistent key for unassigned levels - const levelKey = lvl?.id ?? 'unassigned' - if (lvl && lvls.has(levelKey)) { - const existingLevel = lvls.get(levelKey) - if (existingLevel) { - lvl = existingLevel - } - } else { - lvl = new Level(lvl) - } - lvl.stops.push(stop) - lvls.set(levelKey, lvl) - } - // Update - this.stops = newStops - this.pathways = Array.from(pwIndex.values()) - this.levels = Array.from(lvls.values()) - // Invalidate cached routing graph since stops/pathways have changed; - // findRoute() will lazily rebuild it on next call. - this.graph = null - this.graphProfile = null - // Update stoplist - return Array.from(toFetch) - } -} diff --git a/src/runtime/apps/stations/stop-editor.vue b/src/runtime/apps/stations/stop-editor.vue deleted file mode 100644 index 25e63933..00000000 --- a/src/runtime/apps/stations/stop-editor.vue +++ /dev/null @@ -1,399 +0,0 @@ - - - - - diff --git a/src/runtime/apps/stations/stop-table.vue b/src/runtime/apps/stations/stop-table.vue deleted file mode 100644 index 4b7a420a..00000000 --- a/src/runtime/apps/stations/stop-table.vue +++ /dev/null @@ -1,202 +0,0 @@ - - - diff --git a/src/runtime/apps/stations/types.ts b/src/runtime/apps/stations/types.ts deleted file mode 100644 index 9865a37a..00000000 --- a/src/runtime/apps/stations/types.ts +++ /dev/null @@ -1,226 +0,0 @@ -/** - * TypeScript type definitions for GTFS station editor - * Based on GraphQL schema types from transitland-lib - */ - -import type { Point, MultiPolygon } from 'geojson' - -/** - * Basic feed information - */ -export interface FeedInfo { - id?: number - onestop_id?: string -} - -/** - * GTFS feed version metadata from GraphQL - */ -export interface FeedVersionData { - id?: number - fetched_at?: string - name?: string - sha1?: string - file?: string - earliest_calendar_date?: string - latest_calendar_date?: string - feed?: FeedInfo -} - -/** - * GTFS level (floor) data from GraphQL - */ -export interface LevelData { - id?: number - level_id?: string - level_index?: number - level_name?: string - geometry?: MultiPolygon - parent?: StopData - stops?: StopData[] - feed_version?: FeedVersionData -} - -/** - * GTFS pathway data from GraphQL - */ -export interface PathwayData { - id?: number - length?: number - pathway_id?: string - pathway_mode?: number - max_slope?: number - min_width?: number - signposted_as?: string - reverse_signposted_as?: string - stair_count?: number - traversal_time?: number - is_bidirectional?: number - from_stop?: StopData - to_stop?: StopData - feed_version?: FeedVersionData -} - -/** - * GTFS route stop association from GraphQL - */ -export interface RouteStopData { - id?: number - route?: RouteData - agency?: AgencyData -} - -/** - * GTFS route data from GraphQL - */ -export interface RouteData { - id?: number - route_id?: string - route_type?: number - route_short_name?: string - route_long_name?: string - agency?: AgencyData -} - -/** - * GTFS agency data from GraphQL - */ -export interface AgencyData { - id?: number - agency_id?: string - agency_name?: string -} - -/** - * External reference for stop associations - */ -export interface StopExternalReferenceData { - id?: number - target_feed_onestop_id?: string - target_stop_id?: string - inactive?: boolean - target_active_stop?: StopData -} - -/** - * GTFS stop data from GraphQL - */ -export interface StopData { - id?: number - stop_id?: string - stop_name?: string - stop_code?: string - platform_code?: string - stop_timezone?: string - zone_id?: string - wheelchair_boarding?: number - stop_desc?: string - stop_url?: string - geometry?: Point - location_type?: number - parent?: StopData - children?: StopData[] - level?: LevelData - levels?: LevelData[] - child_levels?: LevelData[] - pathways_from_stop?: PathwayData[] - pathways_to_stop?: PathwayData[] - route_stops?: RouteStopData[] - feed_version?: FeedVersionData - external_reference?: StopExternalReferenceData -} - -/** - * Basemap layer configuration - */ -export interface BasemapLayer { - label: string - source: { - type: string - tiles: string[] - tileSize: number - attribution: string - } - layer: { - type: string - minzoom: number - maxzoom: number - layout?: { - visibility: string - } - } -} - -/** - * Pathway mode icon configuration - */ -export interface PathwayModeIcon { - icon: string - label: string - altIcon?: string -} - -/** - * Validation path result - */ -export interface ValidationPath { - target: StopData - error?: string - info?: string - distance: number -} - -/** - * GraphQL query response types - */ -export interface FeedQueryResponse { - id: number - name?: string - onestop_id: string - feed_versions: Array<{ - id: number - file?: string - name?: string - description?: string - sha1?: string - agencies?: AgencyData[] - stations?: Array<{ - feed_version: { id: number } - station_id: string - stationName: string - geometry?: Point - }> - }> -} - -export interface StationQueryResponse { - feed_versions: Array<{ - stops: StopData[] - }> -} - -export interface StopsQueryResponse { - stops: StopData[] -} - -/** - * Map change event from map components - */ -export interface MapChangeEvent { - features: Array<{ - geometry: Point | MultiPolygon - properties?: Record - }> -} - -/** - * Station data for editor components - */ -export interface StationData { - id?: number - feed_version_id?: number - geometry?: Point | null - stop?: StopData - levels: LevelData[] - stops: StopData[] -} diff --git a/src/runtime/apps/transfers/angle-table.vue b/src/runtime/apps/transfers/angle-table.vue deleted file mode 100644 index bb7a3064..00000000 --- a/src/runtime/apps/transfers/angle-table.vue +++ /dev/null @@ -1,30 +0,0 @@ - - - diff --git a/src/runtime/apps/transfers/bins.ts b/src/runtime/apps/transfers/bins.ts deleted file mode 100644 index 9689dac8..00000000 --- a/src/runtime/apps/transfers/bins.ts +++ /dev/null @@ -1,82 +0,0 @@ -// Transfer scoring histogram utilities - -export interface BinCount { - binMin: number - binMax: number - binName: string - count: number - percentOfTotal: number - scenarioName?: string -} - -const breakpointSecondsToMinutes = (b: number): number => { - if (b < 0 || b > 0) { - return Number.parseFloat((b / 60).toFixed(1)) - } else { - return 0 - } -} - -const breakpointMinutesToString = (b: number): string => { - if (b === 0) { - return '0' - } else if (b < 0) { - return b.toString() - } else if (b > 0) { - return '+' + b.toString() - } else { - return '' - } -} - -const binName = (binMin: number, binMax: number): string => { - return `${breakpointMinutesToString( - breakpointSecondsToMinutes(binMin) - )} to ${breakpointMinutesToString(breakpointSecondsToMinutes(binMax))}` -} - -export const binnedCounts = (times: number[], breakpoints: number[]): BinCount[] => { - const counts: BinCount[] = [ - { - binMin: breakpoints[0]!, - binMax: breakpoints[1]!, - binName: binName(breakpoints[0]!, breakpoints[1]!), - count: 0, - percentOfTotal: 0 - }, - { - binMin: breakpoints[1]!, - binMax: breakpoints[2]!, - binName: binName(breakpoints[1]!, breakpoints[2]!), - count: 0, - percentOfTotal: 0 - }, - { - binMin: breakpoints[2]!, - binMax: breakpoints[3]!, - binName: binName(breakpoints[2]!, breakpoints[3]!), - count: 0, - percentOfTotal: 0 - }, - { - binMin: breakpoints[3]!, - binMax: breakpoints[4]!, - binName: binName(breakpoints[3]!, breakpoints[4]!), - count: 0, - percentOfTotal: 0 - } - ] - times.forEach((t) => { - for (let i = 0; i < counts.length; i++) { - if (t > counts[i]!.binMin && t <= counts[i]!.binMax) { - counts[i]!.count += 1 - } - } - }) - const total = times.length - const result = counts.map((c) => { - c.percentOfTotal = c.count / total - return c - }) - return result -} diff --git a/src/runtime/apps/transfers/breadcrumbs.vue b/src/runtime/apps/transfers/breadcrumbs.vue deleted file mode 100644 index 891da362..00000000 --- a/src/runtime/apps/transfers/breadcrumbs.vue +++ /dev/null @@ -1,103 +0,0 @@ - - - - - diff --git a/src/runtime/apps/transfers/data-grid.vue b/src/runtime/apps/transfers/data-grid.vue deleted file mode 100644 index f823e739..00000000 --- a/src/runtime/apps/transfers/data-grid.vue +++ /dev/null @@ -1,164 +0,0 @@ - - -