From 23399bf1b9bb98549c62977994f057c35b8ca1f9 Mon Sep 17 00:00:00 2001 From: dangreen Date: Mon, 15 Jun 2026 19:12:46 +0400 Subject: [PATCH] fix(next-router,preact-router,react-router,svelte-router): fix link component types --- packages/next-router/package.json | 4 +++- packages/preact-router/package.json | 4 +++- packages/preact-router/src/link.tsx | 5 +++-- packages/preact-router/src/link.types.ts | 5 +++++ packages/react-router/package.json | 4 +++- packages/react-router/src/link.tsx | 5 +++-- packages/react-router/src/link.types.ts | 7 ++++++- packages/svelte-router/package.json | 3 ++- packages/svelte-router/src/link.ts | 10 ++++++---- packages/svelte-router/src/link.types.ts | 10 +++++++++- scripts/check-dist-app-routes.js | 18 ++++++++++++++++++ scripts/oxlint.config.ts | 11 +++++++++++ 12 files changed, 72 insertions(+), 14 deletions(-) create mode 100644 scripts/check-dist-app-routes.js create mode 100644 scripts/oxlint.config.ts diff --git a/packages/next-router/package.json b/packages/next-router/package.json index df440f41..59cee8af 100644 --- a/packages/next-router/package.json +++ b/packages/next-router/package.json @@ -64,7 +64,9 @@ "test:unit": "vitest run --coverage", "test:unit:watch": "vitest watch", "test:size": "size-limit", - "test:types": "tsgo --noEmit", + "test:ts": "tsgo --noEmit", + "test:dist-types": "run emitDeclarations [ node ../../scripts/check-dist-app-routes.js dist/link.d.ts ]", + "test:types": "run -p test:ts test:dist-types", "test": "run -p lint test:unit test:types" }, "peerDependencies": { diff --git a/packages/preact-router/package.json b/packages/preact-router/package.json index 03fc58f8..0a389883 100644 --- a/packages/preact-router/package.json +++ b/packages/preact-router/package.json @@ -62,7 +62,9 @@ "test:unit": "vitest run --coverage", "test:unit:watch": "vitest watch", "test:size": "size-limit", - "test:types": "tsgo --noEmit", + "test:ts": "tsgo --noEmit", + "test:dist-types": "run emitDeclarations [ node ../../scripts/check-dist-app-routes.js dist/link.d.ts ]", + "test:types": "run -p test:ts test:dist-types", "test": "run -p lint test:unit test:types" }, "peerDependencies": { diff --git a/packages/preact-router/src/link.tsx b/packages/preact-router/src/link.tsx index 905d0923..3f06b866 100644 --- a/packages/preact-router/src/link.tsx +++ b/packages/preact-router/src/link.tsx @@ -15,6 +15,7 @@ import { listenLinks } from '@nano_kit/router' import type { + LinkComponent, LinkSettingsHook, LinkProps, LinkSettings @@ -31,7 +32,7 @@ export type * from './link.types.js' function createLinkComponent( useSettings: () => LinkSettings, usePaths: () => Paths -) { +): LinkComponent { return function Link(props: LinkProps) { const { onClick: onClickProp, @@ -150,7 +151,7 @@ export function LinkSettings$(): LinkSettings { * Link component for navigation. * Should be used inside injection context with navigation and paths provided. */ -export const Link = /* @__PURE__ */ createLinkComponent( +export const Link: LinkComponent = /* @__PURE__ */ createLinkComponent( () => useInject(LinkSettings$), () => usePaths() ) diff --git a/packages/preact-router/src/link.types.ts b/packages/preact-router/src/link.types.ts index 00caecc9..a7c7366f 100644 --- a/packages/preact-router/src/link.types.ts +++ b/packages/preact-router/src/link.types.ts @@ -1,5 +1,6 @@ import type { AnchorHTMLAttributes, + ComponentChildren, TargetedMouseEvent } from 'preact' import type { @@ -54,6 +55,10 @@ export type LinkProps = AnchorHTML href?: string }) +export type LinkComponent = ( + props: LinkProps +) => ComponentChildren + export type LinkSettingsHook = ( props: Partial>, settings: S diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 9988bc21..52d63f5b 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -62,7 +62,9 @@ "test:unit": "vitest run --coverage", "test:unit:watch": "vitest watch", "test:size": "size-limit", - "test:types": "tsgo --noEmit", + "test:ts": "tsgo --noEmit", + "test:dist-types": "run emitDeclarations [ node ../../scripts/check-dist-app-routes.js dist/link.d.ts ]", + "test:types": "run -p test:ts test:dist-types", "test": "run -p lint test:unit test:types" }, "peerDependencies": { diff --git a/packages/react-router/src/link.tsx b/packages/react-router/src/link.tsx index 751a68a4..3b43e636 100644 --- a/packages/react-router/src/link.tsx +++ b/packages/react-router/src/link.tsx @@ -18,6 +18,7 @@ import { listenLinks } from '@nano_kit/router' import type { + LinkComponent, LinkSettingsHook, LinkProps, LinkSettings @@ -34,7 +35,7 @@ export type * from './link.types.js' function createLinkComponent( useSettings: () => LinkSettings, usePaths: () => Paths -) { +): LinkComponent { return function Link(props: LinkProps) { const { onClick: onClickProp, @@ -153,7 +154,7 @@ export function LinkSettings$(): LinkSettings { * Link component for navigation. * Should be used inside injection context with navigation and paths provided. */ -export const Link = /* @__PURE__ */ createLinkComponent( +export const Link: LinkComponent = /* @__PURE__ */ createLinkComponent( () => useInject(LinkSettings$), () => usePaths() ) diff --git a/packages/react-router/src/link.types.ts b/packages/react-router/src/link.types.ts index f44c9f88..dd10dc07 100644 --- a/packages/react-router/src/link.types.ts +++ b/packages/react-router/src/link.types.ts @@ -1,6 +1,7 @@ import type { AnchorHTMLAttributes, - MouseEvent + MouseEvent, + ReactNode } from 'react' import type { Routes, @@ -54,6 +55,10 @@ export type LinkProps = AnchorHTML href?: string }) +export type LinkComponent = ( + props: LinkProps +) => ReactNode + export type LinkSettingsHook = ( props: Partial>, settings: S diff --git a/packages/svelte-router/package.json b/packages/svelte-router/package.json index 3a2710e1..9ed2003c 100644 --- a/packages/svelte-router/package.json +++ b/packages/svelte-router/package.json @@ -64,7 +64,8 @@ "test:unit:watch": "vitest watch", "test:ts": "tsgo --noEmit", "test:svelte": "svelte-check --tsconfig ./tsconfig.json", - "test:types": "run -p test:ts test:svelte", + "test:dist-types": "run build:dist [ node ../../scripts/check-dist-app-routes.js dist/link.d.ts ]", + "test:types": "run -p test:ts test:svelte test:dist-types", "test": "run -p lint test:unit test:types" }, "peerDependencies": { diff --git a/packages/svelte-router/src/link.ts b/packages/svelte-router/src/link.ts index 5fb39c21..ac8ba212 100644 --- a/packages/svelte-router/src/link.ts +++ b/packages/svelte-router/src/link.ts @@ -10,6 +10,7 @@ import { import { inject as storeInject } from '@nano_kit/store' import { getInject } from '@nano_kit/svelte' import { + type AppRoutes, type Navigation, type Paths, type Routes, @@ -19,11 +20,12 @@ import { onLinkClick } from '@nano_kit/router' import type { + LinkComponent, LinkProps, LinkSettings, LinkSettingsHook } from './link.types.js' -import LinkComponent from './LinkComponent.svelte' +import LinkView from './LinkComponent.svelte' export type * from './link.types.js' @@ -31,11 +33,11 @@ export type * from './link.types.js' function createLinkComponent( useSettings: () => LinkSettings, usePaths: () => Paths -) { +): LinkComponent { return ( internals: ComponentInternals, props: LinkProps - ) => LinkComponent(internals, Object.assign(props, { + ) => LinkView(internals, Object.assign(props, { // Suppress conflict with AppRoutes paths: usePaths() as unknown as Paths, settings: useSettings() @@ -113,7 +115,7 @@ export function LinkSettings$(): LinkSettings { * Link component for navigation. * Should be used inside injection context with navigation and paths provided. */ -export const Link = /* @__PURE__ */ createLinkComponent( +export const Link: LinkComponent = /* @__PURE__ */ createLinkComponent( () => getInject(LinkSettings$), () => getInject(Paths$) ) diff --git a/packages/svelte-router/src/link.types.ts b/packages/svelte-router/src/link.types.ts index 85b89462..c44f32c1 100644 --- a/packages/svelte-router/src/link.types.ts +++ b/packages/svelte-router/src/link.types.ts @@ -1,4 +1,7 @@ -import type { Snippet } from 'svelte' +import type { + ComponentInternals, + Snippet +} from 'svelte' import type { HTMLAnchorAttributes, MouseEventHandler @@ -60,6 +63,11 @@ export type LinkProps = AnchorAttr href?: string }) +export type LinkComponent = ( + internals: ComponentInternals, + props: LinkProps +) => object + export type LinkSettingsHook = ( props: Readable>>, settings: S diff --git a/scripts/check-dist-app-routes.js b/scripts/check-dist-app-routes.js new file mode 100644 index 00000000..4be864ba --- /dev/null +++ b/scripts/check-dist-app-routes.js @@ -0,0 +1,18 @@ +import { readFileSync } from 'node:fs' +import { resolve } from 'node:path' + +const [file] = process.argv.slice(2) + +if (!file) { + throw new Error('Expected a declaration file path.') +} + +const path = resolve(process.cwd(), file) +const content = readFileSync(path, 'utf8') + +if ( + !content.includes('LinkComponent') + && !content.includes('LinkProps