@real-router/types 0.15.0 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -300,11 +300,11 @@ interface LimitsConfig {
300
300
  }
301
301
 
302
302
  /**
303
- * Base router types without Router class dependency.
303
+ * Router types and interfaces.
304
304
  *
305
- * Router-dependent types (Route, RouteConfigUpdate, ActivationFnFactory,
306
- * PluginFactory) are defined in @real-router/core
307
- * to avoid circular dependencies.
305
+ * Factory types (PluginFactory, GuardFnFactory) and
306
+ * route config types (Route, RouteConfigUpdate) use self-referencing Router<D>
307
+ * within this single file to resolve circular dependencies.
308
308
  */
309
309
 
310
310
  type LogLevel = "log" | "warn" | "error";
@@ -416,7 +416,6 @@ interface Options {
416
416
  */
417
417
  noValidate?: boolean;
418
418
  }
419
- type ActivationFn = (toState: State, fromState: State | undefined) => boolean | Promise<boolean | State | void> | State | void;
420
419
  type GuardFn = (toState: State, fromState: State | undefined) => boolean | Promise<boolean>;
421
420
  type DefaultDependencies = object;
422
421
  interface Config {
@@ -465,64 +464,94 @@ interface Navigator {
465
464
  subscribe: (listener: SubscribeFn) => Unsubscribe;
466
465
  }
467
466
  /**
468
- * Router interface - public API for route navigation and lifecycle management.
467
+ * Router interface full public API for route navigation and lifecycle management.
469
468
  *
470
- * Defines the contract for router implementations. The actual Router class in
471
- * @real-router/core implements this interface with full functionality.
472
- *
473
- * This interface uses `GuardFn | boolean` for guard types to avoid circular
474
- * dependencies. The concrete Router class in @real-router/core narrows this to
475
- * `GuardFnFactory | boolean` for more precise type checking.
469
+ * Generic parameter D constrains dependency injection types.
470
+ * Factory types (PluginFactory, GuardFnFactory) self-reference this interface
471
+ * within the same file to avoid circular dependencies.
476
472
  */
477
- interface Router {
478
- /**
479
- * Register an activation guard for a route.
480
- *
481
- * @param name - Route name
482
- * @param guard - Guard function or boolean
483
- * @returns this for method chaining
484
- */
485
- addActivateGuard: (name: string, guard: GuardFn | boolean) => this;
486
- /**
487
- * Register a deactivation guard for a route.
488
- *
489
- * @param name - Route name
490
- * @param guard - Guard function or boolean
491
- * @returns this for method chaining
492
- */
493
- addDeactivateGuard: (name: string, guard: GuardFn | boolean) => this;
494
- /**
495
- * Remove an activation guard from a route.
496
- *
497
- * @param name - Route name
498
- */
499
- removeActivateGuard: (name: string) => void;
500
- /**
501
- * Remove a deactivation guard from a route.
502
- *
503
- * @param name - Route name
504
- */
505
- removeDeactivateGuard: (name: string) => void;
473
+ interface Router<D extends DefaultDependencies = DefaultDependencies> {
474
+ [key: string]: unknown;
475
+ isActiveRoute: (name: string, params?: Params, strictEquality?: boolean, ignoreQueryParams?: boolean) => boolean;
476
+ buildPath: (route: string, params?: Params) => string;
477
+ getState: <P extends Params = Params, MP extends Params = Params>() => State<P, MP> | undefined;
478
+ getPreviousState: () => State | undefined;
479
+ areStatesEqual: (state1: State | undefined, state2: State | undefined, ignoreQueryParams?: boolean) => boolean;
480
+ shouldUpdateNode: (nodeName: string) => (toState: State, fromState?: State) => boolean;
481
+ isActive: () => boolean;
482
+ start: (startPath: string) => Promise<State>;
483
+ stop: () => this;
484
+ dispose: () => void;
485
+ canNavigateTo: (name: string, params?: Params) => boolean;
486
+ usePlugin: (...plugins: PluginFactory<D>[]) => Unsubscribe;
487
+ subscribe: (listener: SubscribeFn) => Unsubscribe;
488
+ navigate: (routeName: string, routeParams?: Params, options?: NavigationOptions) => Promise<State>;
489
+ navigateToDefault: (options?: NavigationOptions) => Promise<State>;
490
+ }
491
+ /**
492
+ * Factory function for creating plugins.
493
+ * Receives the router instance and a dependency getter.
494
+ */
495
+ type PluginFactory<Dependencies extends DefaultDependencies = DefaultDependencies> = (router: Router<Dependencies>, getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K]) => Plugin;
496
+ /**
497
+ * Factory function for creating guards.
498
+ * Receives the router instance and a dependency getter.
499
+ */
500
+ type GuardFnFactory<Dependencies extends DefaultDependencies = DefaultDependencies> = (router: Router<Dependencies>, getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K]) => GuardFn;
501
+ /**
502
+ * Route configuration.
503
+ */
504
+ interface Route<Dependencies extends DefaultDependencies = DefaultDependencies> {
505
+ [key: string]: unknown;
506
+ /** Route name (dot-separated for nested routes). */
507
+ name: string;
508
+ /** URL path pattern for this route. */
509
+ path: string;
510
+ /** Factory function that returns a guard for route activation. */
511
+ canActivate?: GuardFnFactory<Dependencies>;
512
+ /** Factory function that returns a guard for route deactivation. */
513
+ canDeactivate?: GuardFnFactory<Dependencies>;
506
514
  /**
507
- * Check if navigation to a route is allowed without performing actual navigation.
515
+ * Redirects navigation to another route.
508
516
  *
509
- * Synchronously checks all activation and deactivation guards in the transition path.
510
- * Async guards return false with a console warning.
517
+ * IMPORTANT: forwardTo creates a URL alias, not a transition chain.
518
+ * Guards (canActivate) on the source route are NOT executed.
519
+ * Only guards on the final destination are executed.
511
520
  *
512
- * @param name - Route name to check
513
- * @param params - Route parameters (optional)
514
- * @returns true if navigation is allowed, false otherwise
521
+ * This matches Vue Router and Angular Router behavior.
515
522
  */
516
- canNavigateTo: (name: string, params?: Params) => boolean;
523
+ forwardTo?: string | ForwardToCallback<Dependencies>;
524
+ /** Nested child routes. */
525
+ children?: Route<Dependencies>[];
526
+ /** Encodes state params to URL params. */
527
+ encodeParams?: (stateParams: Params) => Params;
528
+ /** Decodes URL params to state params. */
529
+ decodeParams?: (pathParams: Params) => Params;
517
530
  /**
518
- * Dispose the router and release all resources.
531
+ * Default parameters for this route.
519
532
  *
520
- * Stops the router if active, calls plugin teardown, clears all event
521
- * listeners, routes, and dependencies. After disposal, all
522
- * mutating methods throw a ROUTER_DISPOSED error. Idempotent — safe to
523
- * call multiple times.
533
+ * These values are merged into state.params when creating route states.
534
+ * Missing URL params are filled from defaultParams.
524
535
  */
525
- dispose: () => void;
536
+ defaultParams?: Params;
537
+ }
538
+ /**
539
+ * Configuration update options for updateRoute().
540
+ * All properties are optional. Set to null to remove the configuration.
541
+ */
542
+ interface RouteConfigUpdate<Dependencies extends DefaultDependencies = DefaultDependencies> {
543
+ /** Set to null to remove forwardTo */
544
+ forwardTo?: string | ForwardToCallback<Dependencies> | null;
545
+ /** Set to null to remove defaultParams */
546
+ defaultParams?: Params | null;
547
+ /** Set to null to remove decoder */
548
+ decodeParams?: ((params: Params) => Params) | null;
549
+ /** Set to null to remove encoder */
550
+ encodeParams?: ((params: Params) => Params) | null;
551
+ /** Set to null to remove canActivate */
552
+ canActivate?: GuardFnFactory<Dependencies> | null;
553
+ /** Set to null to remove canDeactivate */
554
+ canDeactivate?: GuardFnFactory<Dependencies> | null;
526
555
  }
527
556
 
528
557
  /**
@@ -567,6 +596,13 @@ interface EventToNameMap {
567
596
  TRANSITION_SUCCESS: "$$success";
568
597
  TRANSITION_ERROR: "$$error";
569
598
  }
599
+ /**
600
+ * Mapping of event names to plugin method names.
601
+ * Type-level computation from EventToNameMap + EventToPluginMap.
602
+ */
603
+ type EventMethodMap = {
604
+ [K in EventsKeys as EventToNameMap[K]]: EventToPluginMap[K];
605
+ };
570
606
  /**
571
607
  * Mapping of error code keys to their values
572
608
  */
@@ -583,4 +619,64 @@ interface ErrorCodeToValueMap {
583
619
  ROUTER_DISPOSED: "DISPOSED";
584
620
  }
585
621
 
586
- export type { ActivationFn, Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, GuardFn, LimitsConfig, Listener, NavigationOptions, Navigator, Options, Params, Plugin, PluginMethod, QueryParamsMode, QueryParamsOptions, RouteParams, RouteTreeState, Router, RouterError, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, TransitionMeta, TransitionPhase, TransitionReason, Unsubscribe };
622
+ /**
623
+ * API interfaces for modular router access.
624
+ * These interfaces are implemented by standalone API functions in @real-router/core.
625
+ */
626
+
627
+ /**
628
+ * Plugin API — for plugins and infrastructure packages.
629
+ * Hides plugin-internal methods from public autocomplete.
630
+ */
631
+ interface PluginApi {
632
+ makeState: <P extends Params = Params, MP extends Params = Params>(name: string, params?: P, path?: string, meta?: StateMetaInput<MP>, forceId?: number) => State<P, MP>;
633
+ buildState: (routeName: string, routeParams: Params) => RouteTreeState | undefined;
634
+ forwardState: <P extends Params = Params>(routeName: string, routeParams: P) => SimpleState<P>;
635
+ matchPath: <P extends Params = Params, MP extends Params = Params>(path: string) => State<P, MP> | undefined;
636
+ setRootPath: (rootPath: string) => void;
637
+ getRootPath: () => string;
638
+ navigateToState: (toState: State, fromState: State | undefined, opts: NavigationOptions) => Promise<State>;
639
+ addEventListener: <E extends EventName>(eventName: E, cb: Plugin[EventMethodMap[E]]) => Unsubscribe;
640
+ buildNavigationState: (name: string, params?: Params) => State | undefined;
641
+ getOptions: () => Options;
642
+ getTree: () => unknown;
643
+ getForwardState: () => <P extends Params = Params>(routeName: string, routeParams: P) => SimpleState<P>;
644
+ setForwardState: (fn: <P extends Params = Params>(routeName: string, routeParams: P) => SimpleState<P>) => void;
645
+ }
646
+ /**
647
+ * Routes API — for dynamic route mutation.
648
+ */
649
+ interface RoutesApi<Dependencies extends DefaultDependencies = DefaultDependencies> {
650
+ add: (routes: Route<Dependencies>[] | Route<Dependencies>, options?: {
651
+ parent?: string;
652
+ }) => void;
653
+ remove: (name: string) => void;
654
+ update: (name: string, updates: RouteConfigUpdate<Dependencies>) => void;
655
+ clear: () => void;
656
+ has: (name: string) => boolean;
657
+ get: (name: string) => Route<Dependencies> | undefined;
658
+ getConfig: (name: string) => Record<string, unknown> | undefined;
659
+ }
660
+ /**
661
+ * Dependencies API — CRUD for dependency injection.
662
+ */
663
+ interface DependenciesApi<Dependencies extends DefaultDependencies = DefaultDependencies> {
664
+ get: <K extends keyof Dependencies>(key: K) => Dependencies[K];
665
+ getAll: () => Partial<Dependencies>;
666
+ set: <K extends keyof Dependencies & string>(name: K, value: Dependencies[K]) => void;
667
+ setAll: (deps: Dependencies) => void;
668
+ remove: (name: keyof Dependencies) => void;
669
+ reset: () => void;
670
+ has: (name: keyof Dependencies) => boolean;
671
+ }
672
+ /**
673
+ * Lifecycle API — guard registration (addActivateGuard, addDeactivateGuard, etc.)
674
+ */
675
+ interface LifecycleApi<Dependencies extends DefaultDependencies = DefaultDependencies> {
676
+ addActivateGuard: (name: string, canActivateHandler: GuardFnFactory<Dependencies> | boolean) => void;
677
+ addDeactivateGuard: (name: string, canDeactivateHandler: GuardFnFactory<Dependencies> | boolean) => void;
678
+ removeActivateGuard: (name: string) => void;
679
+ removeDeactivateGuard: (name: string) => void;
680
+ }
681
+
682
+ export type { Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, DependenciesApi, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventMethodMap, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, GuardFn, GuardFnFactory, LifecycleApi, LimitsConfig, Listener, NavigationOptions, Navigator, Options, Params, Plugin, PluginApi, PluginFactory, PluginMethod, QueryParamsMode, QueryParamsOptions, Route, RouteConfigUpdate, RouteParams, RouteTreeState, Router, RouterError, RoutesApi, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, TransitionMeta, TransitionPhase, TransitionReason, Unsubscribe };
@@ -1 +1 @@
1
- {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/index.ts":{"bytes":1276,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":0}}}
1
+ {"inputs":{"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js":{"bytes":569,"imports":[],"format":"esm"},"src/index.ts":{"bytes":1349,"imports":[{"path":"/home/runner/work/real-router/real-router/node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js","kind":"import-statement","external":true}],"format":"esm"}},"outputs":{"dist/cjs/index.js":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":0}}}
@@ -300,11 +300,11 @@ interface LimitsConfig {
300
300
  }
301
301
 
302
302
  /**
303
- * Base router types without Router class dependency.
303
+ * Router types and interfaces.
304
304
  *
305
- * Router-dependent types (Route, RouteConfigUpdate, ActivationFnFactory,
306
- * PluginFactory) are defined in @real-router/core
307
- * to avoid circular dependencies.
305
+ * Factory types (PluginFactory, GuardFnFactory) and
306
+ * route config types (Route, RouteConfigUpdate) use self-referencing Router<D>
307
+ * within this single file to resolve circular dependencies.
308
308
  */
309
309
 
310
310
  type LogLevel = "log" | "warn" | "error";
@@ -416,7 +416,6 @@ interface Options {
416
416
  */
417
417
  noValidate?: boolean;
418
418
  }
419
- type ActivationFn = (toState: State, fromState: State | undefined) => boolean | Promise<boolean | State | void> | State | void;
420
419
  type GuardFn = (toState: State, fromState: State | undefined) => boolean | Promise<boolean>;
421
420
  type DefaultDependencies = object;
422
421
  interface Config {
@@ -465,64 +464,94 @@ interface Navigator {
465
464
  subscribe: (listener: SubscribeFn) => Unsubscribe;
466
465
  }
467
466
  /**
468
- * Router interface - public API for route navigation and lifecycle management.
467
+ * Router interface full public API for route navigation and lifecycle management.
469
468
  *
470
- * Defines the contract for router implementations. The actual Router class in
471
- * @real-router/core implements this interface with full functionality.
472
- *
473
- * This interface uses `GuardFn | boolean` for guard types to avoid circular
474
- * dependencies. The concrete Router class in @real-router/core narrows this to
475
- * `GuardFnFactory | boolean` for more precise type checking.
469
+ * Generic parameter D constrains dependency injection types.
470
+ * Factory types (PluginFactory, GuardFnFactory) self-reference this interface
471
+ * within the same file to avoid circular dependencies.
476
472
  */
477
- interface Router {
478
- /**
479
- * Register an activation guard for a route.
480
- *
481
- * @param name - Route name
482
- * @param guard - Guard function or boolean
483
- * @returns this for method chaining
484
- */
485
- addActivateGuard: (name: string, guard: GuardFn | boolean) => this;
486
- /**
487
- * Register a deactivation guard for a route.
488
- *
489
- * @param name - Route name
490
- * @param guard - Guard function or boolean
491
- * @returns this for method chaining
492
- */
493
- addDeactivateGuard: (name: string, guard: GuardFn | boolean) => this;
494
- /**
495
- * Remove an activation guard from a route.
496
- *
497
- * @param name - Route name
498
- */
499
- removeActivateGuard: (name: string) => void;
500
- /**
501
- * Remove a deactivation guard from a route.
502
- *
503
- * @param name - Route name
504
- */
505
- removeDeactivateGuard: (name: string) => void;
473
+ interface Router<D extends DefaultDependencies = DefaultDependencies> {
474
+ [key: string]: unknown;
475
+ isActiveRoute: (name: string, params?: Params, strictEquality?: boolean, ignoreQueryParams?: boolean) => boolean;
476
+ buildPath: (route: string, params?: Params) => string;
477
+ getState: <P extends Params = Params, MP extends Params = Params>() => State<P, MP> | undefined;
478
+ getPreviousState: () => State | undefined;
479
+ areStatesEqual: (state1: State | undefined, state2: State | undefined, ignoreQueryParams?: boolean) => boolean;
480
+ shouldUpdateNode: (nodeName: string) => (toState: State, fromState?: State) => boolean;
481
+ isActive: () => boolean;
482
+ start: (startPath: string) => Promise<State>;
483
+ stop: () => this;
484
+ dispose: () => void;
485
+ canNavigateTo: (name: string, params?: Params) => boolean;
486
+ usePlugin: (...plugins: PluginFactory<D>[]) => Unsubscribe;
487
+ subscribe: (listener: SubscribeFn) => Unsubscribe;
488
+ navigate: (routeName: string, routeParams?: Params, options?: NavigationOptions) => Promise<State>;
489
+ navigateToDefault: (options?: NavigationOptions) => Promise<State>;
490
+ }
491
+ /**
492
+ * Factory function for creating plugins.
493
+ * Receives the router instance and a dependency getter.
494
+ */
495
+ type PluginFactory<Dependencies extends DefaultDependencies = DefaultDependencies> = (router: Router<Dependencies>, getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K]) => Plugin;
496
+ /**
497
+ * Factory function for creating guards.
498
+ * Receives the router instance and a dependency getter.
499
+ */
500
+ type GuardFnFactory<Dependencies extends DefaultDependencies = DefaultDependencies> = (router: Router<Dependencies>, getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K]) => GuardFn;
501
+ /**
502
+ * Route configuration.
503
+ */
504
+ interface Route<Dependencies extends DefaultDependencies = DefaultDependencies> {
505
+ [key: string]: unknown;
506
+ /** Route name (dot-separated for nested routes). */
507
+ name: string;
508
+ /** URL path pattern for this route. */
509
+ path: string;
510
+ /** Factory function that returns a guard for route activation. */
511
+ canActivate?: GuardFnFactory<Dependencies>;
512
+ /** Factory function that returns a guard for route deactivation. */
513
+ canDeactivate?: GuardFnFactory<Dependencies>;
506
514
  /**
507
- * Check if navigation to a route is allowed without performing actual navigation.
515
+ * Redirects navigation to another route.
508
516
  *
509
- * Synchronously checks all activation and deactivation guards in the transition path.
510
- * Async guards return false with a console warning.
517
+ * IMPORTANT: forwardTo creates a URL alias, not a transition chain.
518
+ * Guards (canActivate) on the source route are NOT executed.
519
+ * Only guards on the final destination are executed.
511
520
  *
512
- * @param name - Route name to check
513
- * @param params - Route parameters (optional)
514
- * @returns true if navigation is allowed, false otherwise
521
+ * This matches Vue Router and Angular Router behavior.
515
522
  */
516
- canNavigateTo: (name: string, params?: Params) => boolean;
523
+ forwardTo?: string | ForwardToCallback<Dependencies>;
524
+ /** Nested child routes. */
525
+ children?: Route<Dependencies>[];
526
+ /** Encodes state params to URL params. */
527
+ encodeParams?: (stateParams: Params) => Params;
528
+ /** Decodes URL params to state params. */
529
+ decodeParams?: (pathParams: Params) => Params;
517
530
  /**
518
- * Dispose the router and release all resources.
531
+ * Default parameters for this route.
519
532
  *
520
- * Stops the router if active, calls plugin teardown, clears all event
521
- * listeners, routes, and dependencies. After disposal, all
522
- * mutating methods throw a ROUTER_DISPOSED error. Idempotent — safe to
523
- * call multiple times.
533
+ * These values are merged into state.params when creating route states.
534
+ * Missing URL params are filled from defaultParams.
524
535
  */
525
- dispose: () => void;
536
+ defaultParams?: Params;
537
+ }
538
+ /**
539
+ * Configuration update options for updateRoute().
540
+ * All properties are optional. Set to null to remove the configuration.
541
+ */
542
+ interface RouteConfigUpdate<Dependencies extends DefaultDependencies = DefaultDependencies> {
543
+ /** Set to null to remove forwardTo */
544
+ forwardTo?: string | ForwardToCallback<Dependencies> | null;
545
+ /** Set to null to remove defaultParams */
546
+ defaultParams?: Params | null;
547
+ /** Set to null to remove decoder */
548
+ decodeParams?: ((params: Params) => Params) | null;
549
+ /** Set to null to remove encoder */
550
+ encodeParams?: ((params: Params) => Params) | null;
551
+ /** Set to null to remove canActivate */
552
+ canActivate?: GuardFnFactory<Dependencies> | null;
553
+ /** Set to null to remove canDeactivate */
554
+ canDeactivate?: GuardFnFactory<Dependencies> | null;
526
555
  }
527
556
 
528
557
  /**
@@ -567,6 +596,13 @@ interface EventToNameMap {
567
596
  TRANSITION_SUCCESS: "$$success";
568
597
  TRANSITION_ERROR: "$$error";
569
598
  }
599
+ /**
600
+ * Mapping of event names to plugin method names.
601
+ * Type-level computation from EventToNameMap + EventToPluginMap.
602
+ */
603
+ type EventMethodMap = {
604
+ [K in EventsKeys as EventToNameMap[K]]: EventToPluginMap[K];
605
+ };
570
606
  /**
571
607
  * Mapping of error code keys to their values
572
608
  */
@@ -583,4 +619,64 @@ interface ErrorCodeToValueMap {
583
619
  ROUTER_DISPOSED: "DISPOSED";
584
620
  }
585
621
 
586
- export type { ActivationFn, Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, GuardFn, LimitsConfig, Listener, NavigationOptions, Navigator, Options, Params, Plugin, PluginMethod, QueryParamsMode, QueryParamsOptions, RouteParams, RouteTreeState, Router, RouterError, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, TransitionMeta, TransitionPhase, TransitionReason, Unsubscribe };
622
+ /**
623
+ * API interfaces for modular router access.
624
+ * These interfaces are implemented by standalone API functions in @real-router/core.
625
+ */
626
+
627
+ /**
628
+ * Plugin API — for plugins and infrastructure packages.
629
+ * Hides plugin-internal methods from public autocomplete.
630
+ */
631
+ interface PluginApi {
632
+ makeState: <P extends Params = Params, MP extends Params = Params>(name: string, params?: P, path?: string, meta?: StateMetaInput<MP>, forceId?: number) => State<P, MP>;
633
+ buildState: (routeName: string, routeParams: Params) => RouteTreeState | undefined;
634
+ forwardState: <P extends Params = Params>(routeName: string, routeParams: P) => SimpleState<P>;
635
+ matchPath: <P extends Params = Params, MP extends Params = Params>(path: string) => State<P, MP> | undefined;
636
+ setRootPath: (rootPath: string) => void;
637
+ getRootPath: () => string;
638
+ navigateToState: (toState: State, fromState: State | undefined, opts: NavigationOptions) => Promise<State>;
639
+ addEventListener: <E extends EventName>(eventName: E, cb: Plugin[EventMethodMap[E]]) => Unsubscribe;
640
+ buildNavigationState: (name: string, params?: Params) => State | undefined;
641
+ getOptions: () => Options;
642
+ getTree: () => unknown;
643
+ getForwardState: () => <P extends Params = Params>(routeName: string, routeParams: P) => SimpleState<P>;
644
+ setForwardState: (fn: <P extends Params = Params>(routeName: string, routeParams: P) => SimpleState<P>) => void;
645
+ }
646
+ /**
647
+ * Routes API — for dynamic route mutation.
648
+ */
649
+ interface RoutesApi<Dependencies extends DefaultDependencies = DefaultDependencies> {
650
+ add: (routes: Route<Dependencies>[] | Route<Dependencies>, options?: {
651
+ parent?: string;
652
+ }) => void;
653
+ remove: (name: string) => void;
654
+ update: (name: string, updates: RouteConfigUpdate<Dependencies>) => void;
655
+ clear: () => void;
656
+ has: (name: string) => boolean;
657
+ get: (name: string) => Route<Dependencies> | undefined;
658
+ getConfig: (name: string) => Record<string, unknown> | undefined;
659
+ }
660
+ /**
661
+ * Dependencies API — CRUD for dependency injection.
662
+ */
663
+ interface DependenciesApi<Dependencies extends DefaultDependencies = DefaultDependencies> {
664
+ get: <K extends keyof Dependencies>(key: K) => Dependencies[K];
665
+ getAll: () => Partial<Dependencies>;
666
+ set: <K extends keyof Dependencies & string>(name: K, value: Dependencies[K]) => void;
667
+ setAll: (deps: Dependencies) => void;
668
+ remove: (name: keyof Dependencies) => void;
669
+ reset: () => void;
670
+ has: (name: keyof Dependencies) => boolean;
671
+ }
672
+ /**
673
+ * Lifecycle API — guard registration (addActivateGuard, addDeactivateGuard, etc.)
674
+ */
675
+ interface LifecycleApi<Dependencies extends DefaultDependencies = DefaultDependencies> {
676
+ addActivateGuard: (name: string, canActivateHandler: GuardFnFactory<Dependencies> | boolean) => void;
677
+ addDeactivateGuard: (name: string, canDeactivateHandler: GuardFnFactory<Dependencies> | boolean) => void;
678
+ removeActivateGuard: (name: string) => void;
679
+ removeDeactivateGuard: (name: string) => void;
680
+ }
681
+
682
+ export type { Config, DefaultDependencies, DefaultParamsCallback, DefaultRouteCallback, DependenciesApi, ErrorCodeKeys, ErrorCodeToValueMap, ErrorCodeValues, EventMethodMap, EventName, EventToNameMap, EventToPluginMap, EventsKeys, ForwardToCallback, GuardFn, GuardFnFactory, LifecycleApi, LimitsConfig, Listener, NavigationOptions, Navigator, Options, Params, Plugin, PluginApi, PluginFactory, PluginMethod, QueryParamsMode, QueryParamsOptions, Route, RouteConfigUpdate, RouteParams, RouteTreeState, Router, RouterError, RoutesApi, SimpleState, State, StateMeta, StateMetaInput, SubscribeFn, SubscribeState, Subscription, TransitionMeta, TransitionPhase, TransitionReason, Unsubscribe };
@@ -1 +1 @@
1
- {"inputs":{"src/index.ts":{"bytes":1276,"imports":[],"format":"esm"}},"outputs":{"dist/esm/index.mjs":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":0}}}
1
+ {"inputs":{"src/index.ts":{"bytes":1349,"imports":[],"format":"esm"}},"outputs":{"dist/esm/index.mjs":{"imports":[],"exports":[],"entryPoint":"src/index.ts","inputs":{"src/index.ts":{"bytesInOutput":0}},"bytes":0}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/types",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "type": "commonjs",
5
5
  "description": "Shared TypeScript types for Real Router ecosystem",
6
6
  "types": "./dist/esm/index.d.mts",
package/src/api.ts ADDED
@@ -0,0 +1,145 @@
1
+ // packages/core-types/modules/api.ts
2
+
3
+ /**
4
+ * API interfaces for modular router access.
5
+ * These interfaces are implemented by standalone API functions in @real-router/core.
6
+ */
7
+
8
+ import type {
9
+ Params,
10
+ State,
11
+ SimpleState,
12
+ StateMetaInput,
13
+ NavigationOptions,
14
+ Unsubscribe,
15
+ } from "./base";
16
+ import type { EventMethodMap, EventName } from "./constants";
17
+ import type { RouteTreeState } from "./route-node-types";
18
+ import type {
19
+ DefaultDependencies,
20
+ GuardFnFactory,
21
+ Options,
22
+ Plugin,
23
+ Route,
24
+ RouteConfigUpdate,
25
+ } from "./router";
26
+
27
+ /**
28
+ * Plugin API — for plugins and infrastructure packages.
29
+ * Hides plugin-internal methods from public autocomplete.
30
+ */
31
+ export interface PluginApi {
32
+ makeState: <P extends Params = Params, MP extends Params = Params>(
33
+ name: string,
34
+ params?: P,
35
+ path?: string,
36
+ meta?: StateMetaInput<MP>,
37
+ forceId?: number,
38
+ ) => State<P, MP>;
39
+
40
+ buildState: (
41
+ routeName: string,
42
+ routeParams: Params,
43
+ ) => RouteTreeState | undefined;
44
+
45
+ forwardState: <P extends Params = Params>(
46
+ routeName: string,
47
+ routeParams: P,
48
+ ) => SimpleState<P>;
49
+
50
+ matchPath: <P extends Params = Params, MP extends Params = Params>(
51
+ path: string,
52
+ ) => State<P, MP> | undefined;
53
+
54
+ setRootPath: (rootPath: string) => void;
55
+ getRootPath: () => string;
56
+
57
+ navigateToState: (
58
+ toState: State,
59
+ fromState: State | undefined,
60
+ opts: NavigationOptions,
61
+ ) => Promise<State>;
62
+
63
+ addEventListener: <E extends EventName>(
64
+ eventName: E,
65
+ cb: Plugin[EventMethodMap[E]],
66
+ ) => Unsubscribe;
67
+
68
+ buildNavigationState: (name: string, params?: Params) => State | undefined;
69
+
70
+ getOptions: () => Options;
71
+
72
+ getTree: () => unknown;
73
+
74
+ getForwardState: () => <P extends Params = Params>(
75
+ routeName: string,
76
+ routeParams: P,
77
+ ) => SimpleState<P>;
78
+
79
+ setForwardState: (
80
+ fn: <P extends Params = Params>(
81
+ routeName: string,
82
+ routeParams: P,
83
+ ) => SimpleState<P>,
84
+ ) => void;
85
+ }
86
+
87
+ /**
88
+ * Routes API — for dynamic route mutation.
89
+ */
90
+ export interface RoutesApi<
91
+ Dependencies extends DefaultDependencies = DefaultDependencies,
92
+ > {
93
+ add: (
94
+ routes: Route<Dependencies>[] | Route<Dependencies>,
95
+ options?: { parent?: string },
96
+ ) => void;
97
+
98
+ remove: (name: string) => void;
99
+
100
+ update: (name: string, updates: RouteConfigUpdate<Dependencies>) => void;
101
+
102
+ clear: () => void;
103
+
104
+ has: (name: string) => boolean;
105
+
106
+ get: (name: string) => Route<Dependencies> | undefined;
107
+
108
+ getConfig: (name: string) => Record<string, unknown> | undefined;
109
+ }
110
+
111
+ /**
112
+ * Dependencies API — CRUD for dependency injection.
113
+ */
114
+ export interface DependenciesApi<
115
+ Dependencies extends DefaultDependencies = DefaultDependencies,
116
+ > {
117
+ get: <K extends keyof Dependencies>(key: K) => Dependencies[K];
118
+ getAll: () => Partial<Dependencies>;
119
+ set: <K extends keyof Dependencies & string>(
120
+ name: K,
121
+ value: Dependencies[K],
122
+ ) => void;
123
+ setAll: (deps: Dependencies) => void;
124
+ remove: (name: keyof Dependencies) => void;
125
+ reset: () => void;
126
+ has: (name: keyof Dependencies) => boolean;
127
+ }
128
+
129
+ /**
130
+ * Lifecycle API — guard registration (addActivateGuard, addDeactivateGuard, etc.)
131
+ */
132
+ export interface LifecycleApi<
133
+ Dependencies extends DefaultDependencies = DefaultDependencies,
134
+ > {
135
+ addActivateGuard: (
136
+ name: string,
137
+ canActivateHandler: GuardFnFactory<Dependencies> | boolean,
138
+ ) => void;
139
+ addDeactivateGuard: (
140
+ name: string,
141
+ canDeactivateHandler: GuardFnFactory<Dependencies> | boolean,
142
+ ) => void;
143
+ removeActivateGuard: (name: string) => void;
144
+ removeDeactivateGuard: (name: string) => void;
145
+ }
package/src/constants.ts CHANGED
@@ -87,6 +87,14 @@ export interface EventToNameMap {
87
87
  TRANSITION_ERROR: "$$error";
88
88
  }
89
89
 
90
+ /**
91
+ * Mapping of event names to plugin method names.
92
+ * Type-level computation from EventToNameMap + EventToPluginMap.
93
+ */
94
+ export type EventMethodMap = {
95
+ [K in EventsKeys as EventToNameMap[K]]: EventToPluginMap[K];
96
+ };
97
+
90
98
  /**
91
99
  * Mapping of error code keys to their values
92
100
  */
package/src/index.ts CHANGED
@@ -23,25 +23,26 @@ export type {
23
23
  TransitionMeta,
24
24
  } from "./base";
25
25
 
26
- // Router types (base types without Router dependency)
27
- // Note: Route, RouteConfigUpdate, ActivationFnFactory,
28
- // PluginFactory, BuildStateResultWithSegments are in @real-router/core
26
+ // Router types, factory types, and route config types
29
27
  export type {
28
+ Router,
29
+ Navigator,
30
+ Route,
31
+ Plugin,
32
+ Listener,
30
33
  Options,
31
34
  DefaultRouteCallback,
32
35
  ForwardToCallback,
33
36
  DefaultParamsCallback,
34
- ActivationFn,
35
37
  GuardFn,
36
38
  DefaultDependencies,
37
39
  Config,
38
- Plugin,
39
40
  SubscribeState,
40
41
  SubscribeFn,
41
- Listener,
42
42
  Subscription,
43
- Navigator,
44
- Router,
43
+ PluginFactory,
44
+ GuardFnFactory,
45
+ RouteConfigUpdate,
45
46
  } from "./router";
46
47
 
47
48
  // Limits configuration
@@ -56,7 +57,16 @@ export type {
56
57
  EventToPluginMap,
57
58
  EventToNameMap,
58
59
  ErrorCodeToValueMap,
60
+ EventMethodMap,
59
61
  } from "./constants";
60
62
 
63
+ // API interfaces (modular router access)
64
+ export type {
65
+ PluginApi,
66
+ RoutesApi,
67
+ DependenciesApi,
68
+ LifecycleApi,
69
+ } from "./api";
70
+
61
71
  // Note: RouterError type is a forward declaration matching the class in real-router package
62
72
  // Use import { RouterError } from "real-router" for the actual class implementation
package/src/router.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  // packages/core-types/modules/router.ts
2
2
 
3
3
  /**
4
- * Base router types without Router class dependency.
4
+ * Router types and interfaces.
5
5
  *
6
- * Router-dependent types (Route, RouteConfigUpdate, ActivationFnFactory,
7
- * PluginFactory) are defined in @real-router/core
8
- * to avoid circular dependencies.
6
+ * Factory types (PluginFactory, GuardFnFactory) and
7
+ * route config types (Route, RouteConfigUpdate) use self-referencing Router<D>
8
+ * within this single file to resolve circular dependencies.
9
9
  */
10
10
 
11
11
  import type {
@@ -155,12 +155,6 @@ export interface Options {
155
155
  noValidate?: boolean;
156
156
  }
157
157
 
158
- export type ActivationFn = (
159
- toState: State,
160
- fromState: State | undefined,
161
- // eslint-disable-next-line @typescript-eslint/no-invalid-void-type
162
- ) => boolean | Promise<boolean | State | void> | State | void;
163
-
164
158
  export type GuardFn = (
165
159
  toState: State,
166
160
  fromState: State | undefined,
@@ -238,67 +232,152 @@ export interface Navigator {
238
232
  }
239
233
 
240
234
  /**
241
- * Router interface - public API for route navigation and lifecycle management.
242
- *
243
- * Defines the contract for router implementations. The actual Router class in
244
- * @real-router/core implements this interface with full functionality.
235
+ * Router interface full public API for route navigation and lifecycle management.
245
236
  *
246
- * This interface uses `GuardFn | boolean` for guard types to avoid circular
247
- * dependencies. The concrete Router class in @real-router/core narrows this to
248
- * `GuardFnFactory | boolean` for more precise type checking.
237
+ * Generic parameter D constrains dependency injection types.
238
+ * Factory types (PluginFactory, GuardFnFactory) self-reference this interface
239
+ * within the same file to avoid circular dependencies.
249
240
  */
250
- export interface Router {
251
- /**
252
- * Register an activation guard for a route.
253
- *
254
- * @param name - Route name
255
- * @param guard - Guard function or boolean
256
- * @returns this for method chaining
257
- */
258
- addActivateGuard: (name: string, guard: GuardFn | boolean) => this;
241
+ export interface Router<D extends DefaultDependencies = DefaultDependencies> {
242
+ // Plugins add properties at runtime (e.g. browser-plugin adds buildUrl, matchUrl).
243
+ // Index signature allows property access when module augmentation isn't in scope.
244
+ [key: string]: unknown;
259
245
 
260
- /**
261
- * Register a deactivation guard for a route.
262
- *
263
- * @param name - Route name
264
- * @param guard - Guard function or boolean
265
- * @returns this for method chaining
266
- */
267
- addDeactivateGuard: (name: string, guard: GuardFn | boolean) => this;
246
+ isActiveRoute: (
247
+ name: string,
248
+ params?: Params,
249
+ strictEquality?: boolean,
250
+ ignoreQueryParams?: boolean,
251
+ ) => boolean;
268
252
 
269
- /**
270
- * Remove an activation guard from a route.
271
- *
272
- * @param name - Route name
273
- */
274
- removeActivateGuard: (name: string) => void;
253
+ buildPath: (route: string, params?: Params) => string;
275
254
 
276
- /**
277
- * Remove a deactivation guard from a route.
278
- *
279
- * @param name - Route name
280
- */
281
- removeDeactivateGuard: (name: string) => void;
255
+ getState: <P extends Params = Params, MP extends Params = Params>() =>
256
+ | State<P, MP>
257
+ | undefined;
258
+
259
+ getPreviousState: () => State | undefined;
260
+
261
+ areStatesEqual: (
262
+ state1: State | undefined,
263
+ state2: State | undefined,
264
+ ignoreQueryParams?: boolean,
265
+ ) => boolean;
266
+
267
+ shouldUpdateNode: (
268
+ nodeName: string,
269
+ ) => (toState: State, fromState?: State) => boolean;
270
+
271
+ isActive: () => boolean;
272
+
273
+ start: (startPath: string) => Promise<State>;
274
+
275
+ stop: () => this;
276
+
277
+ dispose: () => void;
278
+
279
+ canNavigateTo: (name: string, params?: Params) => boolean;
280
+
281
+ usePlugin: (...plugins: PluginFactory<D>[]) => Unsubscribe;
282
+
283
+ subscribe: (listener: SubscribeFn) => Unsubscribe;
284
+
285
+ navigate: (
286
+ routeName: string,
287
+ routeParams?: Params,
288
+ options?: NavigationOptions,
289
+ ) => Promise<State>;
290
+
291
+ navigateToDefault: (options?: NavigationOptions) => Promise<State>;
292
+ }
293
+
294
+ // =============================================================================
295
+ // Factory Types (self-reference Router<D>)
296
+ // =============================================================================
297
+
298
+ /**
299
+ * Factory function for creating plugins.
300
+ * Receives the router instance and a dependency getter.
301
+ */
302
+ export type PluginFactory<
303
+ Dependencies extends DefaultDependencies = DefaultDependencies,
304
+ > = (
305
+ router: Router<Dependencies>,
306
+ getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
307
+ ) => Plugin;
308
+
309
+ /**
310
+ * Factory function for creating guards.
311
+ * Receives the router instance and a dependency getter.
312
+ */
313
+ export type GuardFnFactory<
314
+ Dependencies extends DefaultDependencies = DefaultDependencies,
315
+ > = (
316
+ router: Router<Dependencies>,
317
+ getDependency: <K extends keyof Dependencies>(key: K) => Dependencies[K],
318
+ ) => GuardFn;
319
+
320
+ // =============================================================================
321
+ // Route Configuration Types (use GuardFnFactory<D> + ForwardToCallback<D>)
322
+ // =============================================================================
282
323
 
324
+ /**
325
+ * Route configuration.
326
+ */
327
+ export interface Route<
328
+ Dependencies extends DefaultDependencies = DefaultDependencies,
329
+ > {
330
+ [key: string]: unknown;
331
+ /** Route name (dot-separated for nested routes). */
332
+ name: string;
333
+ /** URL path pattern for this route. */
334
+ path: string;
335
+ /** Factory function that returns a guard for route activation. */
336
+ canActivate?: GuardFnFactory<Dependencies>;
337
+ /** Factory function that returns a guard for route deactivation. */
338
+ canDeactivate?: GuardFnFactory<Dependencies>;
283
339
  /**
284
- * Check if navigation to a route is allowed without performing actual navigation.
340
+ * Redirects navigation to another route.
285
341
  *
286
- * Synchronously checks all activation and deactivation guards in the transition path.
287
- * Async guards return false with a console warning.
342
+ * IMPORTANT: forwardTo creates a URL alias, not a transition chain.
343
+ * Guards (canActivate) on the source route are NOT executed.
344
+ * Only guards on the final destination are executed.
288
345
  *
289
- * @param name - Route name to check
290
- * @param params - Route parameters (optional)
291
- * @returns true if navigation is allowed, false otherwise
346
+ * This matches Vue Router and Angular Router behavior.
292
347
  */
293
- canNavigateTo: (name: string, params?: Params) => boolean;
294
-
348
+ forwardTo?: string | ForwardToCallback<Dependencies>;
349
+ /** Nested child routes. */
350
+ children?: Route<Dependencies>[];
351
+ /** Encodes state params to URL params. */
352
+ encodeParams?: (stateParams: Params) => Params;
353
+ /** Decodes URL params to state params. */
354
+ decodeParams?: (pathParams: Params) => Params;
295
355
  /**
296
- * Dispose the router and release all resources.
356
+ * Default parameters for this route.
297
357
  *
298
- * Stops the router if active, calls plugin teardown, clears all event
299
- * listeners, routes, and dependencies. After disposal, all
300
- * mutating methods throw a ROUTER_DISPOSED error. Idempotent — safe to
301
- * call multiple times.
358
+ * These values are merged into state.params when creating route states.
359
+ * Missing URL params are filled from defaultParams.
302
360
  */
303
- dispose: () => void;
361
+ defaultParams?: Params;
362
+ }
363
+
364
+ /**
365
+ * Configuration update options for updateRoute().
366
+ * All properties are optional. Set to null to remove the configuration.
367
+ */
368
+ export interface RouteConfigUpdate<
369
+ Dependencies extends DefaultDependencies = DefaultDependencies,
370
+ > {
371
+ /** Set to null to remove forwardTo */
372
+ forwardTo?: string | ForwardToCallback<Dependencies> | null;
373
+ /** Set to null to remove defaultParams */
374
+ defaultParams?: Params | null;
375
+ /** Set to null to remove decoder */
376
+ decodeParams?: ((params: Params) => Params) | null;
377
+ /** Set to null to remove encoder */
378
+ encodeParams?: ((params: Params) => Params) | null;
379
+ /** Set to null to remove canActivate */
380
+ canActivate?: GuardFnFactory<Dependencies> | null;
381
+ /** Set to null to remove canDeactivate */
382
+ canDeactivate?: GuardFnFactory<Dependencies> | null;
304
383
  }