diff --git a/change/@microsoft-fast-router-f63fdd62-300a-4780-acd5-cd5a87621df3.json b/change/@microsoft-fast-router-f63fdd62-300a-4780-acd5-cd5a87621df3.json new file mode 100644 index 00000000000..3e0aa9829d6 --- /dev/null +++ b/change/@microsoft-fast-router-f63fdd62-300a-4780-acd5-cd5a87621df3.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Export the events and titles modules so RoutingEventSink, DefaultRoutingEventSink, TitleBuilder and DefaultTitleBuilder can be used from the package entry point.", + "packageName": "@microsoft/fast-router", + "email": "144495202+AKnassa@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/fast-router/docs/api-report.api.md b/packages/fast-router/docs/api-report.api.md index 069c8eb731e..3f0ec85eefb 100644 --- a/packages/fast-router/docs/api-report.api.md +++ b/packages/fast-router/docs/api-report.api.md @@ -115,6 +115,29 @@ export class DefaultRouteRecognizer implements RouteRecognizer>): Promise | null>; } +// @beta (undocumented) +export class DefaultRoutingEventSink implements RoutingEventSink { + // (undocumented) + onNavigationBegin(router: Router, route: RecognizedRoute, command: NavigationCommand): void; + // (undocumented) + onNavigationEnd(router: Router, route: RecognizedRoute, command: NavigationCommand): void; + // (undocumented) + onPhaseBegin(phase: NavigationPhase): void; + // (undocumented) + onPhaseEnd(phase: NavigationPhase): void; + // (undocumented) + onUnhandledNavigationMessage(router: Router, message: NavigationMessage): void; +} + +// @beta (undocumented) +export class DefaultTitleBuilder implements TitleBuilder { + constructor(segmentSeparator?: string, fragmentSeparator?: string); + // (undocumented) + buildTitle(rootTitle: string, routeTitles: string[][]): string; + // (undocumented) + joinTitles(parentTitle: string, childTitle: string): string; +} + // @beta (undocumented) export type DefinitionCallback = () => Promise | FallbackRouteDefinition; @@ -531,8 +554,6 @@ export abstract class RouterConfiguration { construct(Type: Constructable): T; // (undocumented) readonly contributors: NavigationContributor[]; - // Warning: (ae-forgotten-export) The symbol "RoutingEventSink" needs to be exported by the entry point index.d.ts - // // (undocumented) createEventSink(): RoutingEventSink; // (undocumented) @@ -543,8 +564,6 @@ export abstract class RouterConfiguration { createNavigationQueue(): NavigationQueue; // (undocumented) createRouteRecognizer(): RouteRecognizer; - // Warning: (ae-forgotten-export) The symbol "TitleBuilder" needs to be exported by the entry point index.d.ts - // // (undocumented) createTitleBuilder(): TitleBuilder; // (undocumented) @@ -608,6 +627,20 @@ export interface RouteView { dispose(): void; } +// @beta (undocumented) +export interface RoutingEventSink { + // (undocumented) + onNavigationBegin(router: Router, route: RecognizedRoute, command: NavigationCommand): void; + // (undocumented) + onNavigationEnd(router: Router, route: RecognizedRoute, command: NavigationCommand): void; + // (undocumented) + onPhaseBegin(phase: NavigationPhase): void; + // (undocumented) + onPhaseEnd(phase: NavigationPhase): void; + // (undocumented) + onUnhandledNavigationMessage(router: Router, message: NavigationMessage): void; +} + // @beta (undocumented) export type SupportsSettings = { settings?: TSettings; @@ -619,6 +652,14 @@ export type TemplateFallbackRouteDefinition = LayoutAndTransiti // @beta (undocumented) export type TemplateRouteDefinition = NavigableRouteDefinition & HasTemplate; +// @beta (undocumented) +export interface TitleBuilder { + // (undocumented) + buildTitle(rootTitle: string, routeTitles: string[][]): string; + // (undocumented) + joinTitles(parentTitle: string, childTitle: string): string; +} + // @beta (undocumented) export interface Transition { // (undocumented) diff --git a/packages/fast-router/package.json b/packages/fast-router/package.json index b32988571f0..ff08c07b8ee 100644 --- a/packages/fast-router/package.json +++ b/packages/fast-router/package.json @@ -35,7 +35,7 @@ "prepublishOnly": "npm run clean:dist && npm run build", "lint": "biome-changed", "lint:fix": "biome-changed -- --fix", - "test:node": "tsgo -p ./tsconfig.json && node --test dist/esm/recognizer.spec.js", + "test:node": "tsgo -p ./tsconfig.json && node --test dist/esm/*.spec.js", "test": "npm run lint && npm run doc:ci && npm run test:node", "test:ci": "npm run doc:ci && npm run test:node" }, diff --git a/packages/fast-router/src/index.spec.ts b/packages/fast-router/src/index.spec.ts new file mode 100644 index 00000000000..d9da5abb75e --- /dev/null +++ b/packages/fast-router/src/index.spec.ts @@ -0,0 +1,28 @@ +import { strictEqual } from "node:assert/strict"; +import { describe, test } from "node:test"; +import { DefaultRoutingEventSink } from "./events.js"; +import type { RoutingEventSink, TitleBuilder } from "./index.js"; +import { DefaultTitleBuilder } from "./titles.js"; + +// The entry point has DOM-dependent side effects and cannot be imported at runtime under +// node:test, so it is asserted at the type level. Indexing the module type keeps the +// classes pinned as value exports rather than type-only ones. +type EntryPoint = typeof import("./index.js"); + +describe("index", () => { + test("re-exports the events module", () => { + const sink: RoutingEventSink = new DefaultRoutingEventSink(); + const ctor: EntryPoint["DefaultRoutingEventSink"] = DefaultRoutingEventSink; + + strictEqual(ctor, DefaultRoutingEventSink); + strictEqual(typeof sink.onNavigationBegin, "function"); + }); + + test("re-exports the titles module", () => { + const builder: TitleBuilder = new DefaultTitleBuilder(); + const ctor: EntryPoint["DefaultTitleBuilder"] = DefaultTitleBuilder; + + strictEqual(ctor, DefaultTitleBuilder); + strictEqual(builder.joinTitles("a", "b"), "a - b"); + }); +}); diff --git a/packages/fast-router/src/index.ts b/packages/fast-router/src/index.ts index a522469dd9c..3e91b7a8133 100644 --- a/packages/fast-router/src/index.ts +++ b/packages/fast-router/src/index.ts @@ -1,13 +1,15 @@ export * from "./commands.js"; export * from "./configuration.js"; +export * from "./contributors.js"; +export * from "./events.js"; export * from "./fast-router.js"; export * from "./links.js"; export * from "./navigation.js"; -export * from "./contributors.js"; export * from "./phases.js"; export * from "./process.js"; export * from "./query-string.js"; export * from "./recognizer.js"; export * from "./router.js"; export * from "./routes.js"; +export * from "./titles.js"; export * from "./view.js";