@fastkit/vue-page
Version:
Middleware for more convenient control of routing in Vue applications.
363 lines (362 loc) • 16 kB
text/typescript
import { EV } from "@fastkit/ev";
import { App, Component, InjectionKey, PropType, VNode } from "vue";
import { RouteMatchedItem } from "@fastkit/vue-utils";
import { LocationAsRelativeRaw, LocationQueryRaw, MatcherLocationAsPath, RouteLocation, RouteLocationNormalized, RouteLocationNormalizedLoaded, RouteQueryAndHash, Router, RouterLink, RouterScrollBehavior, RouterView, useLink } from "vue-router";
import { Cookies } from "@fastkit/cookies";
import { IncomingMessage, ServerResponse } from "node:http";
//#region src/schemes.d.ts
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);
//#endregion
//#region src/composables/router/suspense-route-bucket.d.ts
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;
//#endregion
//#region src/composables/router/scroll-behavior.d.ts
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;
//#endregion
//#region src/composables/page-error.d.ts
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;
};
}
//#endregion
//#region src/composables/state.d.ts
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;
//#endregion
//#region src/composables/page-control.d.ts
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(): import("vue-router").RouteLocationNormalizedGeneric | null;
get to(): import("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<import("vue").RendererNode, import("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(): import("vue-router").RouteParamsGeneric;
get query(): import("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>;
//#endregion
//#region src/composables/plugin.d.ts
declare module 'vue' {
interface ComponentCustomProperties {
$vpc: VuePageControl;
}
}
declare function installVuePageControl(settings: VuePageControlSettings): VuePageControl;
//#endregion
//#region src/components/VPage.d.ts
declare const VPage: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
pageKey: {
type: PropType<VuePageKeyOverride>;
default: null;
};
}>, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
pageKey: {
type: PropType<VuePageKeyOverride>;
default: null;
};
}>> & Readonly<{}>, {
pageKey: VuePageKeyOverride;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
//#endregion
//#region src/components/VPageProgress/VPageProgress.d.ts
declare const VPageProgress: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
color: StringConstructor;
failedColor: StringConstructor;
height: {
type: import("vue").PropType<import("@fastkit/vue-utils").Numberish>;
};
throttle: {
type: import("vue").PropType<import("@fastkit/vue-utils").Numberish>;
};
duration: {
type: import("vue").PropType<import("@fastkit/vue-utils").Numberish>;
};
continuous: BooleanConstructor;
rtl: BooleanConstructor;
}>, () => import("vue/jsx-runtime").JSX.Element | undefined, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
color: StringConstructor;
failedColor: StringConstructor;
height: {
type: import("vue").PropType<import("@fastkit/vue-utils").Numberish>;
};
throttle: {
type: import("vue").PropType<import("@fastkit/vue-utils").Numberish>;
};
duration: {
type: import("vue").PropType<import("@fastkit/vue-utils").Numberish>;
};
continuous: BooleanConstructor;
rtl: BooleanConstructor;
}>> & Readonly<{}>, {
continuous: boolean;
rtl: boolean;
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
//#endregion
//#region src/components/VPageLink.d.ts
declare const VPageLink: typeof RouterLink;
//#endregion
//#region src/components/VPageRoot/VPageRoot.d.ts
declare const VPageRoot: import("vue").DefineComponent<{}, () => import("vue/jsx-runtime").JSX.Element | never[], {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
//#endregion
//#region src/components/VErrorPage/VErrorPage.d.ts
declare const VErrorPage: import("vue").DefineComponent<{}, () => import("vue/jsx-runtime").JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
//#endregion
//#region src/injections.d.ts
declare const VuePageControlInjectionKey: InjectionKey<VuePageControl>;
declare function useVuePageControl(opts?: UseVuePageControlOptions): VuePageControl;
//#endregion
export { PrefetchContext, PrefetchHandler, PrefetchHandlerContext, RawPrefetchContext, RawRouterScrollBehavior, RawVuePageControlRedirectSpec, RedirectFn, ResolvedRouteLocation, RouterViewSlotProps, ScrollBehaviorMessenger, ScrollBehaviorMessengerFn, StateInjectionKey, SuspenseRouteBucketEventMap, SuspenseRouteBucketPayload, SuspenseRouteBucketProgress, SuspenseRouteSource, UseVuePageControlOptions, VErrorPage, VPage, VPageLink, VPageProgress, VPageRoot, VuePageControl, VuePageControlError, VuePageControlErrorSettings, VuePageControlEventMap, VuePageControlInjectionKey, VuePageControlMiddlewareFn, VuePageControlRedirectSpec, VuePageControlSettings, VuePageInjectionKey, VuePageKeyOverride, VuePagePrefetchFn, VuePagePrefetchProgress, VuePagePrefetchQueue, VuePagePrefetchQueueEventMap, WatchQueryOption, WriteResponseFn, WrittenResponse, createMiddleware, createPrefetch, createScrollBehavior, extractRouteMatchedItemsWithPrefetch, getSuspenseRouteBucket, installVuePageControl, isVuePageControlError, provideState, useState, useVuePageControl };