UNPKG

@fastkit/vue-page

Version:

Middleware for more convenient control of routing in Vue applications.

363 lines (362 loc) 16 kB
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 };