diff --git a/core/package.json b/core/package.json index 200143bd..764ec358 100644 --- a/core/package.json +++ b/core/package.json @@ -16,7 +16,6 @@ "@logux/core": "0.8.5", "@nanostores/i18n": "0.12.0", "@nanostores/persistent": "0.9.1", - "@nanostores/router": "0.12.1", "@slowreader/api": "link:../api", "just-debounce-it": "3.2.0", "nanoid": "5.0.4", diff --git a/core/router.ts b/core/router.ts index 874381b6..983cfff5 100644 --- a/core/router.ts +++ b/core/router.ts @@ -28,6 +28,12 @@ export interface Routes { export type RouteName = keyof Routes +type EmptyObject = Record + +type ParamlessRouteName = { + [K in RouteName]: Routes[K] extends EmptyObject ? K : never +}[RouteName] + export type Route = Name extends string ? { params: Routes[Name]; redirect?: boolean; route: Name } : never @@ -42,31 +48,24 @@ export type BaseRoute = Name extends string export type BaseRouter = ReadableAtom -const GUEST = new Set(['start', 'signin']) +const GUEST = new Set(['start', 'signin']) -const SETTINGS = new Set([ +const SETTINGS = new Set([ 'interface', 'profile', 'about', 'download' ]) -const ORGANIZE = new Set(['add', 'categories']) +const ORGANIZE = new Set(['add', 'categories']) -function redirect( - route: Name, - params: Routes[Name] -): Route { - // @ts-expect-error Too complex types - return { params, redirect: true, route } +function open(route: ParamlessRouteName | Route): Route { + if (typeof route === 'string') route = { params: {}, route } as Route + return route } -function open( - route: Name, - params: Routes[Name] -): Route { - // @ts-expect-error Too complex types - return { params, route } +function redirect(route: ParamlessRouteName | Route): Route { + return { ...open(route), redirect: true } } function isNumber(value: number | string): boolean { @@ -83,48 +82,54 @@ onEnvironment(({ baseRouter }) => { [baseRouter, userId, hasFeeds, fastCategories], (page, user, withFeeds, fast) => { if (!page) { - return open('notFound', {}) + return open('notFound') } else if (user) { if (GUEST.has(page.route) || page.route === 'home') { if (withFeeds) { - return redirect('slowAll', {}) + return redirect('slowAll') } else { - return redirect('welcome', {}) + return redirect('welcome') } } else if (page.route === 'welcome' && withFeeds) { - return redirect('slowAll', {}) + return redirect('slowAll') } else if (page.route === 'settings') { - return redirect('interface', {}) + return redirect('interface') } else if (page.route === 'feeds') { - return redirect('categories', {}) + return redirect({ params: {}, route: 'categories' }) } else if (page.route === 'fast') { if (!page.params.category && !fast.isLoading) { - return redirect('fast', { category: fast.categories[0].id }) + return redirect({ + params: { category: fast.categories[0].id }, + route: 'fast' + }) } if (page.params.category && !fast.isLoading) { let category = fast.categories.find( i => i.id === page.params.category ) if (!category) { - return open('notFound', {}) + return open('notFound') } } if (page.params.since) { let since = page.params.since if (isNumber(since)) { - return open('fast', { - category: page.params.category, - since: typeof since === 'number' ? since : parseInt(since) + return open({ + params: { + category: page.params.category, + since: typeof since === 'number' ? since : parseInt(since) + }, + route: 'fast' }) } else { - return open('notFound', {}) + return open('notFound') } } } } else if (!GUEST.has(page.route)) { - return open('start', {}) + return open('start') } - return open(page.route, page.params) + return page } ) }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd563937..26d58dbd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -109,9 +109,6 @@ importers: '@nanostores/persistent': specifier: 0.9.1 version: 0.9.1(nanostores@0.9.5) - '@nanostores/router': - specifier: 0.12.1 - version: 0.12.1(nanostores@0.9.5) '@slowreader/api': specifier: link:../api version: link:../api @@ -183,8 +180,8 @@ importers: specifier: 0.9.1 version: 0.9.1(nanostores@0.9.5) '@nanostores/router': - specifier: 0.12.1 - version: 0.12.1(nanostores@0.9.5) + specifier: 0.13.0 + version: 0.13.0(nanostores@0.9.5) '@rollup/plugin-node-resolve': specifier: 15.2.3 version: 15.2.3(rollup@4.9.5) @@ -283,7 +280,7 @@ packages: engines: {node: '>=6.0.0'} dependencies: '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.21 + '@jridgewell/trace-mapping': 0.3.22 /@asamuzakjp/dom-selector@2.0.2: resolution: {integrity: sha512-x1KXOatwofR6ZAYzXRBL5wrdV0vwNxlTCK9NCuLqAzQYARqGcvFwiJA6A1ERuh+dgeA4Dxm3JBYictIes+SqUQ==} @@ -339,7 +336,7 @@ packages: dependencies: '@babel/types': 7.23.6 '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.21 + '@jridgewell/trace-mapping': 0.3.22 jsesc: 2.5.2 /@babel/helper-annotate-as-pure@7.22.5: @@ -2163,7 +2160,7 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.21 + '@jridgewell/trace-mapping': 0.3.22 /@jridgewell/resolve-uri@3.1.1: resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} @@ -2176,8 +2173,8 @@ packages: /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - /@jridgewell/trace-mapping@0.3.21: - resolution: {integrity: sha512-SRfKmRe1KvYnxjEMtxEr+J4HIeMX5YBg/qhRHpxEIGjhX1rshcHlnFUE9K0GazhVKWM7B+nARSkV8LuvJdJ5/g==} + /@jridgewell/trace-mapping@0.3.22: + resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 @@ -2227,7 +2224,7 @@ packages: '@logux/core': 0.8.5 JSONStream: 1.3.5 cookie: 0.5.0 - dotenv: 16.3.1 + dotenv: 16.3.2 fast-glob: 3.3.2 ip: 1.1.8 nanodelay: 2.0.2 @@ -2281,8 +2278,8 @@ packages: nanostores: 0.9.5 dev: false - /@nanostores/router@0.12.1(nanostores@0.9.5): - resolution: {integrity: sha512-tY0nA2B/jBtqfGyVUFqJw8c7GLaagExhljhDfyS/Nif/HvuXS4ezqtHPcAdRAXBB1aYUWIRlYL78br35hr40IA==} + /@nanostores/router@0.13.0(nanostores@0.9.5): + resolution: {integrity: sha512-oMFlgPLM2iswDbDDxwQ2loA1GRFrkEPMwKPRN+D7Ixihu/gWWwMX4na0EAYogHgpl2+nU5AqplwftiikNZ/4GA==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: nanostores: ^0.9.0 @@ -4482,8 +4479,8 @@ packages: engines: {node: '>=12'} dev: true - /dotenv@16.3.1: - resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + /dotenv@16.3.2: + resolution: {integrity: sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==} engines: {node: '>=12'} /duplexify@3.7.1: @@ -6393,7 +6390,7 @@ packages: engines: {node: '>=14.0.0'} dependencies: app-root-dir: 1.0.2 - dotenv: 16.3.1 + dotenv: 16.3.2 dotenv-expand: 10.0.0 dev: true @@ -8259,7 +8256,7 @@ packages: peerDependencies: svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 dependencies: - '@jridgewell/trace-mapping': 0.3.21 + '@jridgewell/trace-mapping': 0.3.22 chokidar: 3.5.3 fast-glob: 3.3.2 import-fresh: 3.3.0 @@ -8359,7 +8356,7 @@ packages: dependencies: '@ampproject/remapping': 2.2.1 '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.21 + '@jridgewell/trace-mapping': 0.3.22 '@types/estree': 1.0.5 acorn: 8.11.3 aria-query: 5.3.0 @@ -8832,7 +8829,7 @@ packages: resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} engines: {node: '>=10.12.0'} dependencies: - '@jridgewell/trace-mapping': 0.3.21 + '@jridgewell/trace-mapping': 0.3.22 '@types/istanbul-lib-coverage': 2.0.6 convert-source-map: 2.0.0 dev: true diff --git a/web/main/environment.ts b/web/main/environment.ts index 78d5b2d0..47f6efb7 100644 --- a/web/main/environment.ts +++ b/web/main/environment.ts @@ -9,7 +9,7 @@ import { import { detectNetworkType } from '../lib/network.js' import { locale } from '../stores/locale.js' -import { openURL, urlRouter } from '../stores/router.js' +import { openRoute, urlRouter } from '../stores/router.js' setupEnvironment({ baseRouter: urlRouter, @@ -17,11 +17,7 @@ setupEnvironment({ locale, logStoreCreator: () => new IndexedStore(), networkType: detectNetworkType, - openRoute(page) { - // Too complex types - // @ts-expect-error - openURL(page.route, page.params) - }, + openRoute, persistentEvents: windowPersistentEvents, persistentStore: localStorage, restartApp() { @@ -34,9 +30,7 @@ setupEnvironment({ router.subscribe(page => { if (page.redirect) { - // Too complex types - // @ts-expect-error - openURL(page.route, page.params) + openRoute(page) } }) diff --git a/web/package.json b/web/package.json index a0808476..8de8dc41 100644 --- a/web/package.json +++ b/web/package.json @@ -29,7 +29,7 @@ "@mdi/js": "7.4.47", "@nanostores/i18n": "0.12.0", "@nanostores/persistent": "0.9.1", - "@nanostores/router": "0.12.1", + "@nanostores/router": "0.13.0", "@rollup/plugin-node-resolve": "15.2.3", "@slowreader/core": "link:../core", "@sveltejs/vite-plugin-svelte": "3.0.1", diff --git a/web/pages/feeds/categories.svelte b/web/pages/feeds/categories.svelte index 2db72ed7..1fa661ff 100644 --- a/web/pages/feeds/categories.svelte +++ b/web/pages/feeds/categories.svelte @@ -11,7 +11,7 @@ organizeMessages as t } from '@slowreader/core' - import { getURL, openURL } from '../../stores/router.js' + import { getURL, openRoute } from '../../stores/router.js' import Button from '../../ui/button.svelte' import CardLink from '../../ui/card-link.svelte' import CardLinks from '../../ui/card-links.svelte' @@ -97,7 +97,7 @@ { - openURL('categories') + openRoute({ params: {}, route: 'categories' }) }} /> {/if} diff --git a/web/stores/router.ts b/web/stores/router.ts index a229e82e..5d77dbfe 100644 --- a/web/stores/router.ts +++ b/web/stores/router.ts @@ -4,6 +4,7 @@ import { getPagePath, type ParamsArg } from '@nanostores/router' +import type { BaseRoute } from '@slowreader/core' export const urlRouter = createRouter({ about: '/settings/about', @@ -34,9 +35,6 @@ export function getURL( return getPagePath(urlRouter, name, ...params) } -export function openURL( - name: Name, - ...params: ParamsArg -): void { - urlRouter.open(getURL(name, ...params)) +export function openRoute(route: BaseRoute): void { + urlRouter.open(getPagePath(urlRouter, route)) }