@fastkit/vue-page
Version:
Middleware for more convenient control of routing in Vue applications.
355 lines (340 loc) • 15.7 kB
TypeScript
import * as vue_router from 'vue-router';
import { RouteLocation, RouterView, RouteLocationNormalizedLoaded, RouterScrollBehavior, Router, RouterLink, useLink, RouteQueryAndHash, MatcherLocationAsPath, LocationAsRelativeRaw, RouteLocationNormalized, LocationQueryRaw } from 'vue-router';
import { EV } from '@fastkit/ev';
import * as vue from 'vue';
import { VNode, App, Component, InjectionKey, PropType } from 'vue';
import * as _fastkit_vue_utils from '@fastkit/vue-utils';
import { RouteMatchedItem } from '@fastkit/vue-utils';
import { IncomingMessage, ServerResponse } from 'node:http';
import { Cookies } from '@fastkit/cookies';
import * as vue_jsx_runtime from 'vue/jsx-runtime';
interface ResolvedRouteLocation extends RouteLocation {
href: string;
}
type InstanceOf<T> = T extends new (...args: any[]) => infer R ? R : never;
type RouterViewSlotProps = Parameters<NonNullable<InstanceOf<typeof RouterView>['$slots']['default']>>[0];
type WatchQueryOption = boolean | string[];
type VuePageKeyOverride = string | null | ((route: RouteLocationNormalizedLoaded) => string);
type SuspenseRouteSource = VNode;
interface SuspenseRouteBucketPayload {
bucket: SuspenseRouteBucket;
source: SuspenseRouteSource;
}
interface SuspenseRouteBucketEventMap {
push: SuspenseRouteBucketPayload;
remove: SuspenseRouteBucketPayload;
start: SuspenseRouteBucketPayload;
finish: SuspenseRouteBucketPayload;
}
interface SuspenseRouteBucketProgress {
total: number;
resolved: number;
}
declare class SuspenseRouteBucket extends EV<SuspenseRouteBucketEventMap> {
private readonly _sources;
private readonly _total;
private readonly _progress;
get sources(): SuspenseRouteSource[];
get total(): number;
get progress(): SuspenseRouteBucketProgress;
constructor();
push(source?: SuspenseRouteSource): void;
remove(source?: SuspenseRouteSource): void;
ensureReady(): Promise<void>;
}
declare function getSuspenseRouteBucket(): SuspenseRouteBucket;
type RawRouterScrollBehavior = 'top' | RouterScrollBehavior;
declare module 'vue' {
interface ComponentCustomOptions {
scrollBehavior?: RawRouterScrollBehavior;
}
}
type ScrollBehaviorMessengerFn = (canceled: boolean) => any;
declare class ScrollBehaviorMessenger {
private static fns;
static trigger(): void;
static reserveNextPosition(position: any): Promise<any>;
static release(): void;
}
declare function createScrollBehavior(): RouterScrollBehavior;
interface VuePageControlErrorSettings {
statusCode?: number;
message?: string;
stack?: string;
}
declare function isVuePageControlError(source: unknown): source is VuePageControlError;
declare class VuePageControlError extends Error {
readonly name = "VuePageControlError";
readonly statusCode: number;
constructor(rawSettings?: VuePageControlErrorSettings | unknown | string | Error);
toJSON(): {
name: string;
statusCode: number;
message: string;
stack: string | undefined;
};
}
type StateInjectionKey<T extends object> = string;
declare function useState<T extends object>(key: StateInjectionKey<T>): T | undefined;
declare function useState<T extends object>(key: StateInjectionKey<T>, defaultValue: T | (() => T)): T;
declare function provideState<T extends object>(key: StateInjectionKey<T>, value: T): void;
type InitialState = Record<string, unknown>;
type VuePageInjectionKey<T> = string;
type VuePagePrefetchFn = (this: void, queue: VuePagePrefetchQueue) => void | Promise<void>;
type RawPrefetchContext = VuePagePrefetchFn | PrefetchContext;
interface WrittenResponse {
status?: number;
statusText?: string;
headers?: Record<string, string>;
}
type WriteResponseFn = (params: WrittenResponse) => void;
type RedirectFn = (location: string, status?: number) => void;
interface PrefetchHandlerContext {
control: VuePageControl;
to: RouteLocationNormalized;
from: RouteLocationNormalized;
matched: {
from?: RouteMatchedItem;
to: RouteMatchedItem;
};
pageKey: string;
}
type PrefetchHandler = (ctx: PrefetchHandlerContext) => boolean | void;
declare module 'vue' {
interface ComponentCustomOptions {
prefetch?: RawPrefetchContext;
prefetchHandler?: PrefetchHandler;
watchQuery?: WatchQueryOption;
middleware?: VuePageControlMiddlewareFn | VuePageControlMiddlewareFn[];
}
}
interface RouteMatchedItemWithPrefetch extends RouteMatchedItem {
prefetch?: RawPrefetchContext;
middleware: VuePageControlMiddlewareFn[];
updateQueries(queries: string[]): void;
}
interface RequiredRouteMatchedItemWithPrefetch extends RouteMatchedItemWithPrefetch {
prefetch: RawPrefetchContext;
}
declare function extractRouteMatchedItemsWithPrefetch(control: VuePageControl, to: RouteLocationNormalized, from: RouteLocationNormalized): {
extracted: RouteMatchedItemWithPrefetch[];
matched: RouteMatchedItem[];
};
type VuePageControlMiddlewareFn = (ctx: VuePageControl) => void | Promise<void>;
declare function createMiddleware(source: VuePageControlMiddlewareFn): VuePageControlMiddlewareFn;
type RedirectOptions = {
statusCode?: number;
};
type RawVuePageControlRedirectSpec = string | (RouteQueryAndHash & MatcherLocationAsPath & RedirectOptions) | (RouteQueryAndHash & LocationAsRelativeRaw & RedirectOptions);
interface VuePageControlRedirectSpec extends RouteQueryAndHash, MatcherLocationAsPath, Omit<LocationAsRelativeRaw, 'path'> {
statusCode: number;
query?: LocationQueryRaw;
}
interface VuePageControlSettings {
app: App;
router: Router;
RouterLink?: any;
useLink?: typeof useLink;
initialState?: InitialState;
initialRoute: ResolvedRouteLocation;
ErrorComponent?: Component;
request?: IncomingMessage;
response?: ServerResponse;
serverRedirect?: RedirectFn;
writeResponse?: WriteResponseFn;
middleware?: VuePageControlMiddlewareFn[];
}
type RawProvided<T> = T | ((queue: VuePagePrefetchQueue) => T | Promise<T>);
interface VuePagePrefetchProgress {
resolved: number;
total: number;
per: number;
finished: boolean;
}
interface VuePageControlEventMap {
start: VuePagePrefetchProgress;
finish: VuePagePrefetchProgress;
error: VuePageControlError;
}
declare class VuePageControl extends EV<VuePageControlEventMap> {
readonly app: App;
readonly router: Router;
readonly cookies: Cookies;
readonly RouterLink: typeof RouterLink;
readonly useLink: typeof useLink;
private _from;
private _to;
private _initialState;
private _beforeRoute;
private _route;
private _stopFn?;
private _prefetchQueues;
private _initialStateConsumed;
private _runningQueues;
private _preftechProgress;
private _suspenseComponents;
private _err;
private _ErrorComponent;
readonly request?: IncomingMessage;
readonly response?: ServerResponse;
private readonly _serverRedirect?;
private readonly _writeResponse?;
readonly isClient: boolean;
readonly middleware: VuePageControlMiddlewareFn[];
private _redirectSpec?;
private _providedMap;
private _transitioning;
private _serverRedirected;
get isServer(): boolean;
get serverRedirected(): boolean;
get from(): vue_router.RouteLocationNormalizedGeneric | null;
get to(): vue_router.RouteLocationNormalizedGeneric | null;
get initialState(): InitialState;
get beforeRoute(): ResolvedRouteLocation | null;
get route(): ResolvedRouteLocation;
get prefetchQueues(): VuePagePrefetchQueue[];
get initialStateConsumed(): boolean;
get runningQueues(): VuePagePrefetchQueue[];
get preftechProgress(): VuePagePrefetchProgress;
get suspenseComponents(): VNode<vue.RendererNode, vue.RendererElement, {
[key: string]: any;
}>[];
get pageError(): VuePageControlError | null;
get ErrorComponent(): Component;
get transitioning(): boolean;
constructor(settings: VuePageControlSettings);
/** @private */
_getQueryBucket(provideKey: string): string[];
/** @private */
_pushQueryToBucket(provideKey: string, query: string): void;
initState<T extends object>(key: StateInjectionKey<T>, initializer: () => T | Promise<T>): Promise<T>;
useState<T extends object>(key: StateInjectionKey<T>): T | undefined;
useState<T extends object>(key: StateInjectionKey<T>, defaultValue: T | (() => T)): T;
provide<T>(key: InjectionKey<T> | string, value: T): void;
inject<T>(key: InjectionKey<T> | string): T | undefined;
inject<T>(key: InjectionKey<T> | string, defaultValue: T, treatDefaultAsFactory?: false): T;
inject<T>(key: InjectionKey<T> | string, defaultValue: T | (() => T), treatDefaultAsFactory: true): T;
addMiddleware(middleware: VuePageControlMiddlewareFn): void;
writeResponse(params: WrittenResponse): void;
onSuspensePending(Component: VNode): void;
onSuspenseResolved(Component: VNode): void;
setInitialState(key: string, data: any): void;
consumeInitialState(key: string): unknown;
injectData<T, D extends T | undefined, N extends boolean>(key: VuePageInjectionKey<T>, defaultData?: D, allowNull?: N): D extends T ? T : N extends true ? T | D : T;
private _stop;
private _init;
private _handleAfterEach;
private _closePrefetchs;
redirect(redirectSpec: RawVuePageControlRedirectSpec): void;
private _triggerRedirect;
private _handleBeforeResolve;
private _deletePageError;
private _setPageError;
private _writeStates;
}
interface VuePagePrefetchQueueEventMap {
close: void;
}
declare class VuePagePrefetchQueue extends EV<VuePagePrefetchQueueEventMap> {
readonly control: VuePageControl;
readonly item: RouteMatchedItemWithPrefetch;
readonly route: RouteLocationNormalized;
private readonly _resolved;
private readonly _canceled;
private readonly _running;
private _resolvedData?;
/** @private */
_providePromise?: Promise<any>;
/** @private */
_provideKey?: string;
/** @private */
_setupPromise?: void | Promise<void>;
get resolved(): boolean;
get canceled(): boolean;
get provideKey(): string | undefined;
get resolvedData(): any;
get params(): vue_router.RouteParamsGeneric;
get query(): vue_router.LocationQuery;
get running(): boolean;
constructor(control: VuePageControl, item: RequiredRouteMatchedItemWithPrefetch, to: RouteLocationNormalized);
getQuery(key: string): string | undefined;
getQuery(key: string, type: undefined, defaultValue: string): string;
getQuery(key: string, type: StringConstructor): string | undefined;
getQuery(key: string, type: StringConstructor, defaultValue: string): string;
getQuery(key: string, type: NumberConstructor): number | undefined;
getQuery(key: string, type: NumberConstructor, defaultValue: number): number;
getQuery(key: string, type: BooleanConstructor): boolean;
getQuery(key: string, type: BooleanConstructor, defaultValue: boolean): boolean;
close(): void;
cancel(): void;
provide<T>(key: VuePageInjectionKey<T>, data: RawProvided<T>): Promise<any>;
injectOtherQueue<T, D extends T | undefined>(key: VuePageInjectionKey<T>, defaultData?: D): Promise<T | D>;
}
interface UseVuePageControlOptions {
onStart?: (progress: VuePagePrefetchProgress) => any;
onFinish?: (progress: VuePagePrefetchProgress) => any;
onError?: (error: VuePageControlError) => any;
}
type PrefetchContext<T = any> = {
key: VuePageInjectionKey<T>;
prefetch: VuePagePrefetchFn;
inject: <D extends T | undefined, N extends boolean = false>(defaultValue?: D, allowNull?: N) => D extends T ? T : N extends true ? T | D : T;
};
declare function createPrefetch<T>(key: VuePageInjectionKey<T>, data: RawProvided<T>): PrefetchContext<T>;
declare module 'vue' {
interface ComponentCustomProperties {
$vpc: VuePageControl;
}
}
declare function installVuePageControl(settings: VuePageControlSettings): VuePageControl;
declare const VPage: vue.DefineComponent<vue.ExtractPropTypes<{
pageKey: {
type: PropType<VuePageKeyOverride>;
default: null;
};
}>, () => vue_jsx_runtime.JSX.Element, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
pageKey: {
type: PropType<VuePageKeyOverride>;
default: null;
};
}>> & Readonly<{}>, {
pageKey: VuePageKeyOverride;
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
declare const VPageProgress: vue.DefineComponent<vue.ExtractPropTypes<{
color: StringConstructor;
failedColor: StringConstructor;
height: {
type: vue.PropType<_fastkit_vue_utils.Numberish>;
};
throttle: {
type: vue.PropType<_fastkit_vue_utils.Numberish>;
};
duration: {
type: vue.PropType<_fastkit_vue_utils.Numberish>;
};
continuous: BooleanConstructor;
rtl: BooleanConstructor;
}>, () => vue_jsx_runtime.JSX.Element | undefined, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
color: StringConstructor;
failedColor: StringConstructor;
height: {
type: vue.PropType<_fastkit_vue_utils.Numberish>;
};
throttle: {
type: vue.PropType<_fastkit_vue_utils.Numberish>;
};
duration: {
type: vue.PropType<_fastkit_vue_utils.Numberish>;
};
continuous: BooleanConstructor;
rtl: BooleanConstructor;
}>> & Readonly<{}>, {
continuous: boolean;
rtl: boolean;
}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
declare const VPageLink: typeof RouterLink;
declare const VPageRoot: vue.DefineComponent<{}, () => never[] | vue_jsx_runtime.JSX.Element, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
declare const VErrorPage: vue.DefineComponent<{}, () => vue_jsx_runtime.JSX.Element, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
declare const VuePageControlInjectionKey: InjectionKey<VuePageControl>;
declare function useVuePageControl(opts?: UseVuePageControlOptions): VuePageControl;
export { type PrefetchContext, type PrefetchHandler, type PrefetchHandlerContext, type RawPrefetchContext, type RawRouterScrollBehavior, type RawVuePageControlRedirectSpec, type RedirectFn, type ResolvedRouteLocation, type RouterViewSlotProps, ScrollBehaviorMessenger, type ScrollBehaviorMessengerFn, type StateInjectionKey, type SuspenseRouteBucketEventMap, type SuspenseRouteBucketPayload, type SuspenseRouteBucketProgress, type SuspenseRouteSource, type UseVuePageControlOptions, VErrorPage, VPage, VPageLink, VPageProgress, VPageRoot, VuePageControl, VuePageControlError, type VuePageControlErrorSettings, type VuePageControlEventMap, VuePageControlInjectionKey, type VuePageControlMiddlewareFn, type VuePageControlRedirectSpec, type VuePageControlSettings, type VuePageInjectionKey, type VuePageKeyOverride, type VuePagePrefetchFn, type VuePagePrefetchProgress, VuePagePrefetchQueue, type VuePagePrefetchQueueEventMap, type WatchQueryOption, type WriteResponseFn, type WrittenResponse, createMiddleware, createPrefetch, createScrollBehavior, extractRouteMatchedItemsWithPrefetch, getSuspenseRouteBucket, installVuePageControl, isVuePageControlError, provideState, useState, useVuePageControl };