@micro-zoe/micro-app
Version:
A lightweight, efficient and powerful micro front-end framework
580 lines (507 loc) โข 17.5 kB
TypeScript
declare module '@micro-app/types' {
type AttrType = string | null
type NormalKey = string | number
type Func = (...rest: any[]) => void
type microAppWindowType = Window & any
type AppName = string
type SourceAddress = string
type AttrsType = Map<string, string>
type RequestIdleCallbackOptions = {
timeout: number
}
type RequestIdleCallbackInfo = {
readonly didTimeout: boolean
timeRemaining: () => number
}
type fiberTasks = Array<() => Promise<void>> | null
type MicroEventListener = EventListenerOrEventListenerObject & Record<string, any>
type timeInfo = {
handler: TimerHandler,
timeout?: number,
args: any[],
}
interface MicroAppElementTagNameMap extends HTMLElementTagNameMap {
'micro-app': any,
}
interface CommonEffectHook {
reset(): void
record(): void
rebuild(): void
release(clearTimer?: boolean): void
}
interface SandBoxStartParams {
umdMode: boolean
baseroute: string
defaultPage: string
disablePatchRequest: boolean
}
interface SandBoxStopParams {
umdMode: boolean
keepRouteState: boolean
destroy: boolean
clearData: boolean
}
interface releaseGlobalEffectParams {
umdMode?: boolean,
clearData?: boolean,
isPrerender?: boolean,
keepAlive?: boolean,
destroy?: boolean,
}
interface BaseSandboxType {
// Properties that can only get and set in microAppWindow, will not escape to rawWindow
scopeProperties: PropertyKey[]
// Properties that can be escape to rawWindow
escapeProperties: PropertyKey[]
// Properties newly added to microAppWindow
injectedKeys: Set<PropertyKey>
// Properties escape to rawWindow, cleared when unmount
escapeKeys: Set<PropertyKey>
// Sandbox ready state
sandboxReady: Promise<void>
// Variables that can only assigned to rawWindow
rawWindowScopeKeyList: PropertyKey[]
// Variables that can escape to rawWindow
staticEscapeProperties: PropertyKey[]
// Variables that scoped in child app
staticScopeProperties: PropertyKey[]
// clear mount, unmount when stop in default mode
clearHijackUmdHooks: () => void
}
interface WithSandBoxInterface extends BaseSandboxType {
// proxy(microWindow)
proxyWindow: WindowProxy
// child window
microAppWindow: Window // Proxy target
start (startParams: SandBoxStartParams): void
stop (stopParams: SandBoxStopParams): void
recordAndReleaseEffect (options: releaseGlobalEffectParams, preventRecord?: boolean): void
// reset effect snapshot data
resetEffectSnapshot(): void
// record umd snapshot before the first execution of umdHookMount
recordEffectSnapshot (): void
// rebuild umd snapshot before remount umd app
rebuildEffectSnapshot (): void
releaseGlobalEffect (options: releaseGlobalEffectParams): void
setRouteInfoForKeepAliveApp (): void
removeRouteInfoForKeepAliveApp (): void
setPreRenderState (state: boolean): void
markUmdMode(state: boolean): void
patchStaticElement (container: Element | ShadowRoot): void
actionsBeforeExecScripts (container: Element | ShadowRoot, handleUmdHooks: Func): void
deleteIframeElement? (): void
setStaticAppState (state: string): void
}
type LinkSourceInfo = {
code: string, // source code
appSpace: Record<string, {
attrs: Map<string, string>, // active element.attributes
placeholder?: Comment | null, // placeholder comment
parsedCode?: string, // parsed code
prefix?: string, // micro-app[name=appName]
}>
}
type ScriptSourceInfo = {
code: string, // source code
isExternal: boolean, // external script
appSpace: Record<string, {
async: boolean, // async script
defer: boolean, // defer script
module: boolean, // module type script
inline: boolean, // run js with inline script
pure: boolean, // pure script
attrs: Map<string, string>, // element attributes
parsedCode?: string, // bind code
parsedFunction?: Function | null, // code to function
sandboxType?: 'with' | 'iframe' | 'disable' // sandbox type (with, iframe, disable)
}>
}
type sourceType = {
html: HTMLElement | null, // html address
links: Set<string>, // style/link address list
scripts: Set<string>, // script address list
}
interface MountParam {
container: HTMLElement | ShadowRoot // app container
inline: boolean // run js in inline mode
routerMode: string // virtual router mode
defaultPage: string // default page of virtual router
baseroute: string // route prefix, default is ''
disablePatchRequest: boolean // prevent rewrite request method of child app
fiber: boolean // run js in fiber mode
// hiddenRouter: boolean
}
interface OnLoadParam {
html: HTMLElement,
// below params is only for prerender app
defaultPage?: string // default page of virtual router
routerMode?: string // virtual router mode
baseroute?: string // route prefix, default is ''
disablePatchRequest?: boolean // prevent rewrite request method of child app
}
interface UnmountParam {
destroy: boolean, // completely destroy, delete cache resources
clearData: boolean // clear data of dateCenter
keepRouteState: boolean // keep route state when unmount, default is false
unmountcb?: CallableFunction // callback of unmount
}
// app instance
interface AppInterface extends Pick<Element, 'querySelector' | 'querySelectorAll'> {
source: sourceType // source list
// TODO: ๅปๆany
sandBox: WithSandBoxInterface | null | any // sandbox
name: string // app name
url: string // app url
scopecss: boolean // whether use css scoped, default is true
useSandbox: boolean // whether use js sandbox, default is true
inline: boolean // whether js runs in inline script mode, default is false
iframe: boolean // use iframe sandbox
ssrUrl: string // html path in ssr mode
container: HTMLElement | ShadowRoot | null // container maybe null, micro-app, shadowRoot, div(keep-alive)
umdMode: boolean // is umd mode
fiber: boolean // fiber mode
routerMode: string // virtual router mode
isPrefetch: boolean // whether prefetch app, default is false
isPrerender: boolean
isReloading?: boolean
prefetchLevel?: number
// defaultPage: string // default page when mount
// baseroute: string // route prefix, default is ''
// hiddenRouter: boolean // hide router info of child from browser url
// Load resources
loadSourceCode (): void
// resource is loaded
onLoad (onLoadParam: OnLoadParam): void
// Error loading HTML
onLoadError (e: Error): void
// mount app
mount (mountParams: MountParam): void
// unmount app
unmount (unmountParam: UnmountParam): void
// app rendering error
onerror (e: Error): void
// set app state
setAppState (state: string): void
// get app state
getAppState (): string
// get keep-alive state
getKeepAliveState(): string | null
parseHtmlString(htmlString: string): HTMLElement
// is app unmounted
isUnmounted (): boolean
// is app already hidden
isHidden (): boolean
// actions for completely destroy
actionsForCompletelyDestroy (): void
// hidden app when disconnectedCallback with keep-alive
hiddenKeepAliveApp (callback?: CallableFunction): void
// show app when connectedCallback with keep-alive
showKeepAliveApp (container: HTMLElement | ShadowRoot): void
}
interface prefetchParam {
name: string,
url: string,
// old config ๐
disableScopecss?: boolean
disableSandbox?: boolean
// old config ๐
'disable-scopecss'?: boolean
'disable-sandbox'?: boolean
inline?: boolean
iframe?: boolean
level?: number
// prerender only ๐
'default-page'?: string
'disable-patch-request'?: boolean
'router-mode'?: string
baseroute?: string
// prerender only ๐
}
// prefetch params
type prefetchParamList = Array<prefetchParam> | (() => Array<prefetchParam>)
// lifeCycles
interface lifeCyclesType {
created?(e: CustomEvent, appName: string): void
beforemount?(e: CustomEvent, appName: string): void
mounted?(e: CustomEvent, appName: string): void
unmount?(e: CustomEvent, appName: string): void
error?(e: CustomEvent, appName: string): void
beforeshow?(e: CustomEvent, appName: string): void
aftershow?(e: CustomEvent, appName: string): void
afterhidden?(e: CustomEvent, appName: string): void
}
type AssetsChecker = (url: string) => boolean;
type plugins = {
// global plugin
global?: Array<{
// Scoped global Properties
scopeProperties?: Array<PropertyKey>
// Properties that can be escape to rawWindow
escapeProperties?: Array<PropertyKey>
// Exclude JS or CSS
excludeChecker?: AssetsChecker
// Ignore JS or CSS
ignoreChecker?: AssetsChecker
// options for plugin as the third parameter of loader
options?: Record<string, unknown>
// handle function
loader?: (code: string, url: string) => string
// html processor
processHtml?: (code: string, url: string) => string
}>
// plugin for special app
modules?: {
[name: string]: Array<{
// Scoped global Properties
scopeProperties?: Array<PropertyKey>
// Properties that can be escape to rawWindow
escapeProperties?: Array<PropertyKey>
// Exclude JS or CSS
excludeChecker?: AssetsChecker
// Ignore JS or CSS
ignoreChecker?: AssetsChecker
// options for plugin as the third parameter of loader
options?: Record<string, unknown>
// handle function
loader?: (code: string, url: string) => string
// html processor
processHtml?: (code: string, url: string) => string
aHrefResolver?: (hrefValue: string, appName: string, appUrl: string) => string
}>
}
}
type GetActiveAppsParam = {
excludeHiddenApp?: boolean,
excludePreRender?: boolean,
}
type fetchType = (url: string, options: Record<string, unknown>, appName: string | null) => Promise<string>
type globalAssetsType = {
js?: string[],
css?: string[],
}
interface MicroAppConfig {
shadowDOM?: boolean
destroy?: boolean
destory?: boolean
inline?: boolean
// old config ๐
disableScopecss?: boolean
disableSandbox?: boolean
// old config ๐
'disable-scopecss'?: boolean
'disable-sandbox'?: boolean
'disable-memory-router'?: boolean
'disable-patch-request'?: boolean
'keep-router-state'?: boolean
'keep-alive'?: boolean
'clear-data'?: boolean
'router-mode'?: string
'router-event-delay'?: number | ((appName: string) => number),
iframe?: boolean
ssr?: boolean
fiber?: boolean
prefetchLevel?: number
prefetchDelay?: number
iframeSrc?: string
}
interface OptionsType extends MicroAppConfig {
tagName?: string
lifeCycles?: lifeCyclesType
preFetchApps?: prefetchParamList
plugins?: plugins
fetch?: fetchType
globalAssets?: globalAssetsType,
excludeAssetFilter?: (assetUrl: string) => boolean
excludeRunScriptFilter?: (scriptUrl: string, error: Error, appName: string, appUrl: string) => boolean
/* image video audio ๆฏๅฆ่ฎพ็ฝฎ crossOrigin = 'anonymous' */
includeCrossOrigin?: (assetUrl: string) => boolean
getRootElementParentNode?: (node: Node, appName: AppName) => void
customProxyDocumentProps?: Map<string | number | symbol, (value: unknown) => void>
aHrefResolver?: (hrefValue: string, appName: string, appUrl: string) => string
inheritBaseBody?:boolean
}
// MicroApp config
interface MicroAppBaseType {
tagName: string
hasInit: boolean
options: OptionsType
preFetch(apps: prefetchParamList): void
router: Router // eslint-disable-line
start(options?: OptionsType): void
}
interface MicroAppElementInterface {
appName: AttrType // app name
appUrl: AttrType // app url
// Hooks for element append to documents
connectedCallback (): void
// Hooks for element delete from documents
disconnectedCallback (): void
// Hooks for element attributes change
attributeChangedCallback (a: 'name' | 'url', o: string, n: string): void
// public mount action for micro_app_element & create_app
mount (app: AppInterface): void
// unmount app
unmount (destroy?: boolean, unmountcb?: CallableFunction): void
// Re render app from the command line
reload (destroy?: boolean): Promise<boolean>
// get delay time of router event
getRouterEventDelay (): number
// rewrite micro-app.setAttribute, process attr data
setAttribute (key: string, value: any): void
}
// special CallableFunction for interact
type CallableFunctionForInteract = CallableFunction & { __APP_NAME__?: string, __AUTO_TRIGGER__?: boolean }
type PopStateListener = (this: Window, e: PopStateEvent) => void
type MicroPopStateEvent = PopStateEvent & { onlyForBrowser?: boolean }
interface MicroLocation extends Location, URL {
fullPath: string
self: URL | Location
[key: string]: any
}
type MicroHistory = ProxyHandler<History>
type MicroState = any
interface MicroRouterInfoState {
fullPath: string | null,
state: MicroState,
mode: string,
}
type HistoryProxyValue =
Pick<
History,
'length' |
'scrollRestoration' |
'state' |
'back' |
'forward' |
'go' |
'pushState' |
'replaceState'
> | CallableFunction
interface MicroRouter {
microLocation: MicroLocation
microHistory: MicroHistory
}
type LocationQueryValue = string | null
type LocationQueryObject = Record<
string,
LocationQueryValue | LocationQueryValue[]
>
type LocationQuery = {
hashQuery?: LocationQueryObject,
searchQuery?: LocationQueryObject
}
type GuardLocation = Record<keyof MicroLocation, any>
type CurrentRoute = Map<string, GuardLocation>
interface RouterTarget {
name: string
path: string
state?: unknown
replace?: boolean
}
type navigationMethod = (to: RouterTarget) => Promise<void>
interface AccurateGuard {
[appName: string]: (to: GuardLocation, from: GuardLocation) => void
}
type GlobalNormalGuard = ((to: GuardLocation, from: GuardLocation, appName: string) => void)
type RouterGuard = AccurateGuard | GlobalNormalGuard
type SetDefaultPageOptions = {
name: string,
path: string,
}
type AttachAllToURLParam = {
includeHiddenApp?: boolean,
includePreRender?: boolean,
}
// Router API for developer
interface Router {
// current route of all apps
readonly current: CurrentRoute
/**
* encodeURI of microApp path
* @param path url path
*/
encode(path: string): string
/**
* decodeURI of microApp path
* @param path url path
*/
decode(path: string): ReturnType<Router['encode']>
/**
* Navigate to a new URL by pushing an entry in the history
* stack.
* @param to - Route location to navigate to
*/
push: navigationMethod
/**
* Navigate to a new URL by replacing the current entry in
* the history stack.
*
* @param to - Route location to navigate to
*/
replace: navigationMethod
/**
* Move forward or backward through the history. calling `history.go()`.
*
* @param delta - The position in the history to which you want to move,
* relative to the current page
*/
go: Func
/**
* Go back in history if possible by calling `history.back()`.
*/
back: Func
/**
* Go forward in history if possible by calling `history.forward()`.
*/
forward: Func
/**
* Add a navigation guard that executes before any navigation
* @param guard global hook for
*/
beforeEach(guard: RouterGuard): () => boolean
/**
* Add a navigation guard that executes after any navigation
* @param guard global hook for
*/
afterEach(guard: RouterGuard): () => boolean
/**
* Add defaultPage to control the first rendered page
* @param options SetDefaultPageOptions
*/
setDefaultPage(options: SetDefaultPageOptions): () => boolean
/**
* Clear data of defaultPage that set by setDefaultPage
*/
removeDefaultPage(appName: string): boolean
/**
* Get defaultPage that set by setDefaultPage
*/
getDefaultPage(key: PropertyKey): string | void
/**
* Attach specified active app router info to browser url
*/
attachToURL(appName: string): void
/**
* Attach all active app router info to browser url
*/
attachAllToURL(options: AttachAllToURLParam): void
/**
* Record base app router, let child app control base app navigation
* It is global data
* @param baseRouter router instance of base app
*/
setBaseAppRouter(baseRouter: unknown): void
/**
* get baseRouter from cache
*/
getBaseAppRouter(): unknown
}
// result of add/remove microApp path on browser url
type HandleMicroPathResult = {
fullPath: string,
isAttach2Hash: boolean,
}
}
declare module '@micro-zoe/micro-app/polyfill/jsx-custom-event'
declare const __DEV__: boolean
declare const __TEST__: boolean