@qiankunjs/single-spa 0.0.1-rc.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.
- package/LICENSE +21 -0
- package/README.md +52 -0
- package/dist/cjs/applications/app-errors.d.ts +11 -0
- package/dist/cjs/applications/app-errors.js +57 -0
- package/dist/cjs/applications/app-errors.js.map +1 -0
- package/dist/cjs/applications/app.helpers.d.ts +52 -0
- package/dist/cjs/applications/app.helpers.js +47 -0
- package/dist/cjs/applications/app.helpers.js.map +1 -0
- package/dist/cjs/applications/apps.d.ts +23 -0
- package/dist/cjs/applications/apps.js +234 -0
- package/dist/cjs/applications/apps.js.map +1 -0
- package/dist/cjs/applications/timeouts.d.ts +19 -0
- package/dist/cjs/applications/timeouts.js +115 -0
- package/dist/cjs/applications/timeouts.js.map +1 -0
- package/dist/cjs/declarations.d.ts +4 -0
- package/dist/cjs/devtools/devtools.d.ts +16 -0
- package/dist/cjs/devtools/devtools.js +24 -0
- package/dist/cjs/devtools/devtools.js.map +1 -0
- package/dist/cjs/devtools/profiler.d.ts +11 -0
- package/dist/cjs/devtools/profiler.js +25 -0
- package/dist/cjs/devtools/profiler.js.map +1 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +32 -0
- package/dist/cjs/jquery-support.d.ts +7 -0
- package/dist/cjs/jquery-support.js +34 -0
- package/dist/cjs/jquery-support.js.map +1 -0
- package/dist/cjs/lifecycles/bootstrap.d.ts +2 -0
- package/dist/cjs/lifecycles/bootstrap.js +27 -0
- package/dist/cjs/lifecycles/bootstrap.js.map +1 -0
- package/dist/cjs/lifecycles/lifecycle.helpers.d.ts +90 -0
- package/dist/cjs/lifecycles/lifecycle.helpers.js +33 -0
- package/dist/cjs/lifecycles/lifecycle.helpers.js.map +1 -0
- package/dist/cjs/lifecycles/load.d.ts +3 -0
- package/dist/cjs/lifecycles/load.js +73 -0
- package/dist/cjs/lifecycles/load.js.map +1 -0
- package/dist/cjs/lifecycles/mount.d.ts +2 -0
- package/dist/cjs/lifecycles/mount.js +40 -0
- package/dist/cjs/lifecycles/mount.js.map +1 -0
- package/dist/cjs/lifecycles/prop.helpers.d.ts +9 -0
- package/dist/cjs/lifecycles/prop.helpers.js +23 -0
- package/dist/cjs/lifecycles/prop.helpers.js.map +1 -0
- package/dist/cjs/lifecycles/unload.d.ts +12 -0
- package/dist/cjs/lifecycles/unload.js +63 -0
- package/dist/cjs/lifecycles/unload.js.map +1 -0
- package/dist/cjs/lifecycles/unmount.d.ts +2 -0
- package/dist/cjs/lifecycles/unmount.js +32 -0
- package/dist/cjs/lifecycles/unmount.js.map +1 -0
- package/dist/cjs/lifecycles/update.d.ts +2 -0
- package/dist/cjs/lifecycles/update.js +22 -0
- package/dist/cjs/lifecycles/update.js.map +1 -0
- package/dist/cjs/navigation/navigation-events.d.ts +8 -0
- package/dist/cjs/navigation/navigation-events.js +102 -0
- package/dist/cjs/navigation/navigation-events.js.map +1 -0
- package/dist/cjs/navigation/reroute.d.ts +9 -0
- package/dist/cjs/navigation/reroute.js +182 -0
- package/dist/cjs/navigation/reroute.js.map +1 -0
- package/dist/cjs/parcels/mount-parcel.d.ts +3 -0
- package/dist/cjs/parcels/mount-parcel.js +122 -0
- package/dist/cjs/parcels/mount-parcel.js.map +1 -0
- package/dist/cjs/single-spa.d.ts +19 -0
- package/dist/cjs/single-spa.js +39 -0
- package/dist/cjs/single-spa.js.map +1 -0
- package/dist/cjs/start.d.ts +5 -0
- package/dist/cjs/start.js +21 -0
- package/dist/cjs/start.js.map +1 -0
- package/dist/cjs/utils/runtime-environment.d.ts +1 -0
- package/dist/cjs/utils/runtime-environment.js +7 -0
- package/dist/cjs/utils/runtime-environment.js.map +1 -0
- package/dist/cjs/window-globals.d.ts +8 -0
- package/dist/esm/applications/app-errors.d.ts +11 -0
- package/dist/esm/applications/app-errors.js +52 -0
- package/dist/esm/applications/app-errors.js.map +1 -0
- package/dist/esm/applications/app.helpers.d.ts +52 -0
- package/dist/esm/applications/app.helpers.js +41 -0
- package/dist/esm/applications/app.helpers.js.map +1 -0
- package/dist/esm/applications/apps.d.ts +23 -0
- package/dist/esm/applications/apps.js +223 -0
- package/dist/esm/applications/apps.js.map +1 -0
- package/dist/esm/applications/timeouts.d.ts +19 -0
- package/dist/esm/applications/timeouts.js +109 -0
- package/dist/esm/applications/timeouts.js.map +1 -0
- package/dist/esm/declarations.d.ts +4 -0
- package/dist/esm/devtools/devtools.d.ts +16 -0
- package/dist/esm/devtools/devtools.js +20 -0
- package/dist/esm/devtools/devtools.js.map +1 -0
- package/dist/esm/devtools/profiler.d.ts +11 -0
- package/dist/esm/devtools/profiler.js +22 -0
- package/dist/esm/devtools/profiler.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +10 -0
- package/dist/esm/jquery-support.d.ts +7 -0
- package/dist/esm/jquery-support.js +33 -0
- package/dist/esm/jquery-support.js.map +1 -0
- package/dist/esm/lifecycles/bootstrap.d.ts +2 -0
- package/dist/esm/lifecycles/bootstrap.js +26 -0
- package/dist/esm/lifecycles/bootstrap.js.map +1 -0
- package/dist/esm/lifecycles/lifecycle.helpers.d.ts +90 -0
- package/dist/esm/lifecycles/lifecycle.helpers.js +30 -0
- package/dist/esm/lifecycles/lifecycle.helpers.js.map +1 -0
- package/dist/esm/lifecycles/load.d.ts +3 -0
- package/dist/esm/lifecycles/load.js +72 -0
- package/dist/esm/lifecycles/load.js.map +1 -0
- package/dist/esm/lifecycles/mount.d.ts +2 -0
- package/dist/esm/lifecycles/mount.js +39 -0
- package/dist/esm/lifecycles/mount.js.map +1 -0
- package/dist/esm/lifecycles/prop.helpers.d.ts +9 -0
- package/dist/esm/lifecycles/prop.helpers.js +22 -0
- package/dist/esm/lifecycles/prop.helpers.js.map +1 -0
- package/dist/esm/lifecycles/unload.d.ts +12 -0
- package/dist/esm/lifecycles/unload.js +60 -0
- package/dist/esm/lifecycles/unload.js.map +1 -0
- package/dist/esm/lifecycles/unmount.d.ts +2 -0
- package/dist/esm/lifecycles/unmount.js +31 -0
- package/dist/esm/lifecycles/unmount.js.map +1 -0
- package/dist/esm/lifecycles/update.d.ts +2 -0
- package/dist/esm/lifecycles/update.js +21 -0
- package/dist/esm/lifecycles/update.js.map +1 -0
- package/dist/esm/navigation/navigation-events.d.ts +8 -0
- package/dist/esm/navigation/navigation-events.js +92 -0
- package/dist/esm/navigation/navigation-events.js.map +1 -0
- package/dist/esm/navigation/reroute.d.ts +9 -0
- package/dist/esm/navigation/reroute.js +180 -0
- package/dist/esm/navigation/reroute.js.map +1 -0
- package/dist/esm/parcels/mount-parcel.d.ts +3 -0
- package/dist/esm/parcels/mount-parcel.js +120 -0
- package/dist/esm/parcels/mount-parcel.js.map +1 -0
- package/dist/esm/single-spa.d.ts +19 -0
- package/dist/esm/single-spa.js +17 -0
- package/dist/esm/single-spa.js.map +1 -0
- package/dist/esm/start.d.ts +5 -0
- package/dist/esm/start.js +19 -0
- package/dist/esm/start.js.map +1 -0
- package/dist/esm/utils/runtime-environment.d.ts +1 -0
- package/dist/esm/utils/runtime-environment.js +6 -0
- package/dist/esm/utils/runtime-environment.js.map +1 -0
- package/dist/esm/window-globals.d.ts +8 -0
- package/package.json +25 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { AppOrParcelStatus, InternalApplication, AppDevtools } from '../applications/app.helpers';
|
|
2
|
+
import { AppOrParcelTimeouts } from '../applications/timeouts';
|
|
3
|
+
export declare function validLifecycleFn(fn: LifeCycleFn<unknown> | LifeCycleFn<unknown>[]): boolean;
|
|
4
|
+
export declare function flattenFnArray(appOrParcel: LifeCycles<unknown>, lifecycle: string, isParcel: boolean): LifeCycleFn<unknown>;
|
|
5
|
+
export declare function smellsLikeAPromise(promise: any): boolean;
|
|
6
|
+
export interface CustomProps {
|
|
7
|
+
[str: string]: any;
|
|
8
|
+
[num: number]: any;
|
|
9
|
+
}
|
|
10
|
+
export interface ParcelCustomProps extends CustomProps {
|
|
11
|
+
domElement: HTMLElement;
|
|
12
|
+
}
|
|
13
|
+
export type CustomPropsFn<ExtraProps extends CustomProps = CustomProps> = (name: string, location: Location) => ExtraProps;
|
|
14
|
+
export type AppProps = {
|
|
15
|
+
name: string;
|
|
16
|
+
mountParcel(parcelConfig: ParcelConfig, customProps: ParcelProps & CustomProps): Parcel;
|
|
17
|
+
};
|
|
18
|
+
export type ParcelConfig<ExtraProps = CustomProps> = ParcelConfigObject<ExtraProps> | (() => Promise<ParcelConfigObject<ExtraProps>>);
|
|
19
|
+
type ParcelProps = {
|
|
20
|
+
domElement: HTMLElement;
|
|
21
|
+
};
|
|
22
|
+
export type ParcelConfigObject<ExtraProps = CustomProps> = {
|
|
23
|
+
name?: string;
|
|
24
|
+
timeouts?: AppOrParcelTimeouts;
|
|
25
|
+
} & LifeCycles<ExtraProps>;
|
|
26
|
+
export type LifeCycleFn<ExtraProps> = (config: ExtraProps & AppProps) => Promise<any>;
|
|
27
|
+
export type LifeCycles<ExtraProps = {}> = {
|
|
28
|
+
bootstrap?: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;
|
|
29
|
+
mount: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;
|
|
30
|
+
unmount: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;
|
|
31
|
+
update?: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;
|
|
32
|
+
unload?: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;
|
|
33
|
+
devtools?: AppDevtools;
|
|
34
|
+
timeouts?: AppOrParcelTimeouts;
|
|
35
|
+
};
|
|
36
|
+
export type Parcel<ExtraProps = CustomProps> = {
|
|
37
|
+
mount(): Promise<null>;
|
|
38
|
+
unmount(): Promise<null>;
|
|
39
|
+
update?(customProps: ExtraProps): Promise<any>;
|
|
40
|
+
getStatus(): AppOrParcelStatus;
|
|
41
|
+
loadPromise: Promise<null>;
|
|
42
|
+
bootstrapPromise: Promise<null>;
|
|
43
|
+
mountPromise: Promise<null>;
|
|
44
|
+
unmountPromise: Promise<null>;
|
|
45
|
+
_parcel: InternalParcel;
|
|
46
|
+
};
|
|
47
|
+
export interface ParcelOwner {
|
|
48
|
+
name: string;
|
|
49
|
+
parcels: ParcelMap;
|
|
50
|
+
}
|
|
51
|
+
export interface ParcelMap {
|
|
52
|
+
[parcelId: number]: InternalParcel;
|
|
53
|
+
}
|
|
54
|
+
export interface InternalParcel {
|
|
55
|
+
id: number;
|
|
56
|
+
name: string;
|
|
57
|
+
bootstrap: LifeCycles['bootstrap'];
|
|
58
|
+
mount: LifeCycles['mount'];
|
|
59
|
+
unmount: LifeCycles['unmount'];
|
|
60
|
+
update: LifeCycles['update'];
|
|
61
|
+
parcels: ParcelMap;
|
|
62
|
+
status: AppOrParcelStatus;
|
|
63
|
+
customProps: CustomProps;
|
|
64
|
+
parentName: string;
|
|
65
|
+
unmountThisParcel(): Promise<AppOrParcel>;
|
|
66
|
+
currentTask: Promise<LoadedAppOrParcel>;
|
|
67
|
+
timeouts: AppOrParcelTimeouts;
|
|
68
|
+
}
|
|
69
|
+
export type AppOrParcel = InternalApplication | InternalParcel;
|
|
70
|
+
interface Loaded extends LifeCycles {
|
|
71
|
+
loadPromise?: Promise<LoadedApp | InternalApplication>;
|
|
72
|
+
}
|
|
73
|
+
export type LoadedAppOrParcel = (InternalApplication & Loaded) | (InternalParcel & Loaded);
|
|
74
|
+
export type LoadedApp = InternalApplication & Loaded;
|
|
75
|
+
export type Application<ExtraProps = {}> = LifeCycles<ExtraProps> | LoadApp<ExtraProps>;
|
|
76
|
+
export type LoadApp<ExtraProps = {}> = (config: ExtraProps & AppProps) => Promise<LifeCycles<ExtraProps>>;
|
|
77
|
+
export interface SingleSpaLocation {
|
|
78
|
+
pathname: URL['pathname'];
|
|
79
|
+
hash?: URL['hash'];
|
|
80
|
+
search?: string;
|
|
81
|
+
}
|
|
82
|
+
export type ActivityFn = (location: SingleSpaLocation) => boolean;
|
|
83
|
+
export type Activity = ActivityFn | string | (ActivityFn | string)[];
|
|
84
|
+
export type RegisterApplicationConfig<ExtraProps extends CustomProps = {}> = {
|
|
85
|
+
name: string;
|
|
86
|
+
app: Application<ExtraProps>;
|
|
87
|
+
activeWhen: Activity;
|
|
88
|
+
customProps?: ExtraProps | CustomPropsFn<ExtraProps>;
|
|
89
|
+
};
|
|
90
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { toName } from "../applications/app.helpers.js";
|
|
2
|
+
import { formatErrorMessage } from "../applications/app-errors.js";
|
|
3
|
+
//#region src/lifecycles/lifecycle.helpers.ts
|
|
4
|
+
function validLifecycleFn(fn) {
|
|
5
|
+
return fn && (typeof fn === "function" || isArrayOfFns(fn));
|
|
6
|
+
function isArrayOfFns(arr) {
|
|
7
|
+
return Array.isArray(arr) && !arr.find((item) => typeof item !== "function");
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function flattenFnArray(appOrParcel, lifecycle, isParcel) {
|
|
11
|
+
let fns = Array.isArray(appOrParcel[lifecycle]) ? appOrParcel[lifecycle] : [appOrParcel[lifecycle]].filter(Boolean);
|
|
12
|
+
if (fns.length === 0) fns = [() => Promise.resolve()];
|
|
13
|
+
const type = isParcel ? "parcel" : "application";
|
|
14
|
+
const name = toName(appOrParcel);
|
|
15
|
+
return function(props) {
|
|
16
|
+
return fns.reduce((resultPromise, fn, index) => {
|
|
17
|
+
return resultPromise.then(() => {
|
|
18
|
+
const thisPromise = fn(props);
|
|
19
|
+
return smellsLikeAPromise(thisPromise) ? thisPromise : Promise.reject(formatErrorMessage(15, process.env.NODE_ENV !== "production" && `Within ${type} ${name}, the lifecycle function ${lifecycle} at array index ${index} did not return a promise`, type, name, lifecycle, index));
|
|
20
|
+
});
|
|
21
|
+
}, Promise.resolve());
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function smellsLikeAPromise(promise) {
|
|
25
|
+
return promise && typeof promise.then === "function" && typeof promise.catch === "function";
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
export { flattenFnArray, smellsLikeAPromise, validLifecycleFn };
|
|
29
|
+
|
|
30
|
+
//# sourceMappingURL=lifecycle.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.helpers.js","names":[],"sources":["../../../src/lifecycles/lifecycle.helpers.ts"],"sourcesContent":["import { toName, AppOrParcelStatus, InternalApplication, AppDevtools } from '../applications/app.helpers';\nimport { formatErrorMessage } from '../applications/app-errors';\nimport { AppOrParcelTimeouts } from '../applications/timeouts';\n\nexport function validLifecycleFn(fn: LifeCycleFn<unknown> | LifeCycleFn<unknown>[]): boolean {\n return fn && (typeof fn === 'function' || isArrayOfFns(fn));\n\n function isArrayOfFns(arr) {\n return Array.isArray(arr) && !arr.find((item) => typeof item !== 'function');\n }\n}\n\nexport function flattenFnArray(\n appOrParcel: LifeCycles<unknown>,\n lifecycle: string,\n isParcel: boolean,\n): LifeCycleFn<unknown> {\n let fns: LifeCycleFn<unknown>[] = Array.isArray(appOrParcel[lifecycle])\n ? (appOrParcel[lifecycle] as LifeCycleFn<unknown>[])\n : [appOrParcel[lifecycle] as LifeCycleFn<unknown>].filter(Boolean);\n if (fns.length === 0) {\n fns = [() => Promise.resolve()];\n }\n\n const type = isParcel ? 'parcel' : 'application';\n const name = toName(appOrParcel);\n\n return function (props: AppProps): Promise<unknown> {\n return fns.reduce((resultPromise, fn, index) => {\n return resultPromise.then(() => {\n const thisPromise = fn(props);\n return smellsLikeAPromise(thisPromise)\n ? thisPromise\n : Promise.reject(\n formatErrorMessage(\n 15,\n __DEV__ &&\n `Within ${type} ${name}, the lifecycle function ${lifecycle} at array index ${index} did not return a promise`,\n type,\n name,\n lifecycle,\n index,\n ),\n );\n });\n }, Promise.resolve());\n };\n}\n\nexport function smellsLikeAPromise(promise) {\n return promise && typeof promise.then === 'function' && typeof promise.catch === 'function';\n}\n\nexport interface CustomProps {\n [str: string]: any;\n [num: number]: any;\n}\n\nexport interface ParcelCustomProps extends CustomProps {\n domElement: HTMLElement;\n}\n\nexport type CustomPropsFn<ExtraProps extends CustomProps = CustomProps> = (\n name: string,\n location: Location,\n) => ExtraProps;\n\nexport type AppProps = {\n name: string;\n mountParcel(parcelConfig: ParcelConfig, customProps: ParcelProps & CustomProps): Parcel;\n};\n\nexport type ParcelConfig<ExtraProps = CustomProps> =\n ParcelConfigObject<ExtraProps> | (() => Promise<ParcelConfigObject<ExtraProps>>);\n\ntype ParcelProps = { domElement: HTMLElement };\nexport type ParcelConfigObject<ExtraProps = CustomProps> = {\n name?: string;\n timeouts?: AppOrParcelTimeouts;\n} & LifeCycles<ExtraProps>;\n\nexport type LifeCycleFn<ExtraProps> = (config: ExtraProps & AppProps) => Promise<any>;\nexport type LifeCycles<ExtraProps = {}> = {\n // qiankun fork: bootstrap is the lifecycle name, reverting upstream #1307's rename to init\n // (re-align if upstream ever ships a stable v7 — see the fork README)\n bootstrap?: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;\n mount: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;\n unmount: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;\n update?: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;\n unload?: LifeCycleFn<ExtraProps> | Array<LifeCycleFn<ExtraProps>>;\n devtools?: AppDevtools;\n timeouts?: AppOrParcelTimeouts;\n};\n\nexport type Parcel<ExtraProps = CustomProps> = {\n mount(): Promise<null>;\n unmount(): Promise<null>;\n update?(customProps: ExtraProps): Promise<any>;\n getStatus(): AppOrParcelStatus;\n loadPromise: Promise<null>;\n bootstrapPromise: Promise<null>;\n mountPromise: Promise<null>;\n unmountPromise: Promise<null>;\n // Intended for internal use only\n _parcel: InternalParcel;\n};\n\nexport interface ParcelOwner {\n name: string;\n parcels: ParcelMap;\n}\n\nexport interface ParcelMap {\n [parcelId: number]: InternalParcel;\n}\n\n// Intended for internal use only\nexport interface InternalParcel {\n id: number;\n name: string;\n bootstrap: LifeCycles['bootstrap'];\n mount: LifeCycles['mount'];\n unmount: LifeCycles['unmount'];\n update: LifeCycles['update'];\n parcels: ParcelMap;\n status: AppOrParcelStatus;\n customProps: CustomProps;\n parentName: string;\n unmountThisParcel(): Promise<AppOrParcel>;\n currentTask: Promise<LoadedAppOrParcel>;\n timeouts: AppOrParcelTimeouts;\n}\n\nexport type AppOrParcel = InternalApplication | InternalParcel;\n\ninterface Loaded extends LifeCycles {\n // loadPromise sometimes bails early if there is an error,\n // which results in it being an InternalApplication\n loadPromise?: Promise<LoadedApp | InternalApplication>;\n}\n\nexport type LoadedAppOrParcel = (InternalApplication & Loaded) | (InternalParcel & Loaded);\n\nexport type LoadedApp = InternalApplication & Loaded;\n\nexport type Application<ExtraProps = {}> = LifeCycles<ExtraProps> | LoadApp<ExtraProps>;\n\nexport type LoadApp<ExtraProps = {}> = (config: ExtraProps & AppProps) => Promise<LifeCycles<ExtraProps>>;\n\nexport interface SingleSpaLocation {\n pathname: URL['pathname'];\n hash?: URL['hash'];\n search?: string;\n}\n\nexport type ActivityFn = (location: SingleSpaLocation) => boolean;\n\nexport type Activity = ActivityFn | string | (ActivityFn | string)[];\n\nexport type RegisterApplicationConfig<ExtraProps extends CustomProps = {}> = {\n name: string;\n app: Application<ExtraProps>;\n activeWhen: Activity;\n customProps?: ExtraProps | CustomPropsFn<ExtraProps>;\n};\n"],"mappings":";;;AAIA,SAAgB,iBAAiB,IAA4D;CAC3F,OAAO,OAAO,OAAO,OAAO,cAAc,aAAa,EAAE;CAEzD,SAAS,aAAa,KAAK;EACzB,OAAO,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,MAAM,SAAS,OAAO,SAAS,UAAU;CAC7E;AACF;AAEA,SAAgB,eACd,aACA,WACA,UACsB;CACtB,IAAI,MAA8B,MAAM,QAAQ,YAAY,UAAU,IACjE,YAAY,aACb,CAAC,YAAY,UAAkC,CAAC,CAAC,OAAO,OAAO;CACnE,IAAI,IAAI,WAAW,GACjB,MAAM,OAAO,QAAQ,QAAQ,CAAC;CAGhC,MAAM,OAAO,WAAW,WAAW;CACnC,MAAM,OAAO,OAAO,WAAW;CAE/B,OAAO,SAAU,OAAmC;EAClD,OAAO,IAAI,QAAQ,eAAe,IAAI,UAAU;GAC9C,OAAO,cAAc,WAAW;IAC9B,MAAM,cAAc,GAAG,KAAK;IAC5B,OAAO,mBAAmB,WAAW,IACjC,cACA,QAAQ,OACN,mBACE,IAAA,QAAA,IAAA,aAAA,gBAEE,UAAU,KAAK,GAAG,KAAK,2BAA2B,UAAU,kBAAkB,MAAM,4BACtF,MACA,MACA,WACA,KACF,CACF;GACN,CAAC;EACH,GAAG,QAAQ,QAAQ,CAAC;CACtB;AACF;AAEA,SAAgB,mBAAmB,SAAS;CAC1C,OAAO,WAAW,OAAO,QAAQ,SAAS,cAAc,OAAO,QAAQ,UAAU;AACnF"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AppOrParcelStatus, toName } from "../applications/app.helpers.js";
|
|
2
|
+
import { formatErrorMessage, handleAppError } from "../applications/app-errors.js";
|
|
3
|
+
import { flattenFnArray, smellsLikeAPromise, validLifecycleFn } from "./lifecycle.helpers.js";
|
|
4
|
+
import "../devtools/profiler.js";
|
|
5
|
+
import { getProps } from "./prop.helpers.js";
|
|
6
|
+
import { ensureValidAppTimeouts } from "../applications/timeouts.js";
|
|
7
|
+
//#region src/lifecycles/load.ts
|
|
8
|
+
function toLoadPromise(app) {
|
|
9
|
+
return Promise.resolve().then(() => {
|
|
10
|
+
if (app.loadPromise) return app.loadPromise;
|
|
11
|
+
if (app.status !== AppOrParcelStatus.NOT_LOADED && app.status !== AppOrParcelStatus.LOAD_ERROR) return app;
|
|
12
|
+
const appBeingLoaded = app;
|
|
13
|
+
appBeingLoaded.status = AppOrParcelStatus.LOADING_SOURCE_CODE;
|
|
14
|
+
let lifecycles, isUserErr;
|
|
15
|
+
return appBeingLoaded.loadPromise = Promise.resolve().then(() => {
|
|
16
|
+
const loadPromise = appBeingLoaded.loadApp(getProps(app));
|
|
17
|
+
if (!smellsLikeAPromise(loadPromise)) {
|
|
18
|
+
isUserErr = true;
|
|
19
|
+
throw Error(formatErrorMessage(33, process.env.NODE_ENV !== "production" && `single-spa loading function did not return a promise. Check the second argument to registerApplication('${toName(app)}', loadingFunction, activityFunction)`, toName(appBeingLoaded)));
|
|
20
|
+
}
|
|
21
|
+
return loadPromise.then((val) => {
|
|
22
|
+
appBeingLoaded.loadErrorTime = null;
|
|
23
|
+
lifecycles = val;
|
|
24
|
+
let validationErrMessage, validationErrCode;
|
|
25
|
+
if (typeof lifecycles !== "object") {
|
|
26
|
+
validationErrCode = 34;
|
|
27
|
+
if (process.env.NODE_ENV !== "production") validationErrMessage = `does not export anything`;
|
|
28
|
+
}
|
|
29
|
+
if (!validLifecycleFn(lifecycles.mount)) {
|
|
30
|
+
validationErrCode = 36;
|
|
31
|
+
if (process.env.NODE_ENV !== "production") validationErrMessage = `does not export a mount function or array of functions`;
|
|
32
|
+
}
|
|
33
|
+
if (!validLifecycleFn(lifecycles.unmount)) {
|
|
34
|
+
validationErrCode = 37;
|
|
35
|
+
if (process.env.NODE_ENV !== "production") validationErrMessage = `does not export a unmount function or array of functions`;
|
|
36
|
+
}
|
|
37
|
+
if (validationErrCode) {
|
|
38
|
+
let appOptsStr;
|
|
39
|
+
try {
|
|
40
|
+
appOptsStr = JSON.stringify(lifecycles);
|
|
41
|
+
} catch (_unused) {}
|
|
42
|
+
console.error(formatErrorMessage(validationErrCode, process.env.NODE_ENV !== "production" && `The loading function for single-spa application '${toName(appBeingLoaded)}' resolved with the following, which does not have mount and unmount functions`, "application", toName(appBeingLoaded), appOptsStr), lifecycles);
|
|
43
|
+
handleAppError(validationErrMessage, appBeingLoaded, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
44
|
+
return appBeingLoaded;
|
|
45
|
+
}
|
|
46
|
+
if (lifecycles.devtools && lifecycles.devtools.overlays) appBeingLoaded.devtools.overlays = Object.assign({}, app.devtools.overlays, lifecycles.devtools.overlays);
|
|
47
|
+
appBeingLoaded.status = AppOrParcelStatus.NOT_BOOTSTRAPPED;
|
|
48
|
+
appBeingLoaded.bootstrap = flattenFnArray(lifecycles, "bootstrap", false);
|
|
49
|
+
appBeingLoaded.mount = flattenFnArray(lifecycles, "mount", false);
|
|
50
|
+
appBeingLoaded.unmount = flattenFnArray(lifecycles, "unmount", false);
|
|
51
|
+
appBeingLoaded.unload = flattenFnArray(lifecycles, "unload", false);
|
|
52
|
+
appBeingLoaded.timeouts = ensureValidAppTimeouts(lifecycles.timeouts);
|
|
53
|
+
delete appBeingLoaded.loadPromise;
|
|
54
|
+
return appBeingLoaded;
|
|
55
|
+
});
|
|
56
|
+
}).catch((err) => {
|
|
57
|
+
delete appBeingLoaded.loadPromise;
|
|
58
|
+
let newStatus;
|
|
59
|
+
if (isUserErr) newStatus = AppOrParcelStatus.SKIP_BECAUSE_BROKEN;
|
|
60
|
+
else {
|
|
61
|
+
newStatus = AppOrParcelStatus.LOAD_ERROR;
|
|
62
|
+
appBeingLoaded.loadErrorTime = (/* @__PURE__ */ new Date()).getTime();
|
|
63
|
+
}
|
|
64
|
+
handleAppError(err, appBeingLoaded, newStatus);
|
|
65
|
+
return appBeingLoaded;
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
export { toLoadPromise };
|
|
71
|
+
|
|
72
|
+
//# sourceMappingURL=load.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"load.js","names":[],"sources":["../../../src/lifecycles/load.ts"],"sourcesContent":["import { AppOrParcelStatus, toName, InternalApplication } from '../applications/app.helpers';\nimport { ensureValidAppTimeouts } from '../applications/timeouts';\nimport { handleAppError, formatErrorMessage } from '../applications/app-errors';\nimport { LifeCycles, LoadedApp, flattenFnArray, smellsLikeAPromise, validLifecycleFn } from './lifecycle.helpers';\nimport { getProps } from './prop.helpers';\nimport { addProfileEntry } from '../devtools/profiler';\n\nexport function toLoadPromise(app: InternalApplication | LoadedApp): Promise<LoadedApp | InternalApplication> {\n return Promise.resolve().then(() => {\n if ((app as LoadedApp).loadPromise) {\n return (app as LoadedApp).loadPromise;\n }\n\n if (app.status !== AppOrParcelStatus.NOT_LOADED && app.status !== AppOrParcelStatus.LOAD_ERROR) {\n return app;\n }\n\n let startTime: number;\n if (__PROFILE__) {\n startTime = performance.now();\n }\n\n const appBeingLoaded: InternalApplication & Partial<LoadedApp> = app;\n\n appBeingLoaded.status = AppOrParcelStatus.LOADING_SOURCE_CODE;\n\n let lifecycles: LifeCycles, isUserErr: boolean;\n\n return (appBeingLoaded.loadPromise = Promise.resolve()\n .then(() => {\n const loadPromise = appBeingLoaded.loadApp(getProps(app));\n if (!smellsLikeAPromise(loadPromise)) {\n // The name of the app will be prepended to this error message inside of the handleAppError function\n isUserErr = true;\n throw Error(\n formatErrorMessage(\n 33,\n __DEV__ &&\n `single-spa loading function did not return a promise. Check the second argument to registerApplication('${toName(\n app,\n )}', loadingFunction, activityFunction)`,\n toName(appBeingLoaded),\n ),\n );\n }\n return loadPromise.then((val) => {\n appBeingLoaded.loadErrorTime = null;\n\n lifecycles = val;\n\n let validationErrMessage, validationErrCode;\n\n if (typeof lifecycles !== 'object') {\n validationErrCode = 34;\n if (__DEV__) {\n validationErrMessage = `does not export anything`;\n }\n }\n\n if (!validLifecycleFn(lifecycles.mount)) {\n validationErrCode = 36;\n if (__DEV__) {\n validationErrMessage = `does not export a mount function or array of functions`;\n }\n }\n\n if (!validLifecycleFn(lifecycles.unmount)) {\n validationErrCode = 37;\n if (__DEV__) {\n validationErrMessage = `does not export a unmount function or array of functions`;\n }\n }\n\n if (validationErrCode) {\n let appOptsStr;\n try {\n appOptsStr = JSON.stringify(lifecycles);\n } catch {}\n console.error(\n formatErrorMessage(\n validationErrCode,\n __DEV__ &&\n `The loading function for single-spa application '${toName(\n appBeingLoaded,\n )}' resolved with the following, which does not have mount and unmount functions`,\n 'application',\n toName(appBeingLoaded),\n appOptsStr,\n ),\n lifecycles,\n );\n handleAppError(validationErrMessage, appBeingLoaded, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n return appBeingLoaded;\n }\n\n if (lifecycles.devtools && lifecycles.devtools.overlays) {\n appBeingLoaded.devtools.overlays = Object.assign({}, app.devtools.overlays, lifecycles.devtools.overlays);\n }\n\n appBeingLoaded.status = AppOrParcelStatus.NOT_BOOTSTRAPPED;\n appBeingLoaded.bootstrap = flattenFnArray(lifecycles, 'bootstrap', false);\n appBeingLoaded.mount = flattenFnArray(lifecycles, 'mount', false);\n appBeingLoaded.unmount = flattenFnArray(lifecycles, 'unmount', false);\n appBeingLoaded.unload = flattenFnArray(lifecycles, 'unload', false);\n appBeingLoaded.timeouts = ensureValidAppTimeouts(lifecycles.timeouts);\n\n delete appBeingLoaded.loadPromise;\n\n if (__PROFILE__) {\n addProfileEntry('application', toName(appBeingLoaded), 'load', startTime, performance.now(), true);\n }\n\n return appBeingLoaded as LoadedApp;\n });\n })\n .catch((err) => {\n delete appBeingLoaded.loadPromise;\n\n let newStatus;\n if (isUserErr) {\n newStatus = AppOrParcelStatus.SKIP_BECAUSE_BROKEN;\n } else {\n newStatus = AppOrParcelStatus.LOAD_ERROR;\n appBeingLoaded.loadErrorTime = new Date().getTime();\n }\n handleAppError(err, appBeingLoaded, newStatus);\n\n if (__PROFILE__) {\n addProfileEntry('application', toName(appBeingLoaded), 'load', startTime, performance.now(), false);\n }\n\n return appBeingLoaded as LoadedApp;\n }));\n });\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,cAAc,KAAgF;CAC5G,OAAO,QAAQ,QAAQ,CAAC,CAAC,WAAW;EAClC,IAAK,IAAkB,aACrB,OAAQ,IAAkB;EAG5B,IAAI,IAAI,WAAW,kBAAkB,cAAc,IAAI,WAAW,kBAAkB,YAClF,OAAO;EAQT,MAAM,iBAA2D;EAEjE,eAAe,SAAS,kBAAkB;EAE1C,IAAI,YAAwB;EAE5B,OAAQ,eAAe,cAAc,QAAQ,QAAQ,CAAC,CACnD,WAAW;GACV,MAAM,cAAc,eAAe,QAAQ,SAAS,GAAG,CAAC;GACxD,IAAI,CAAC,mBAAmB,WAAW,GAAG;IAEpC,YAAY;IACZ,MAAM,MACJ,mBACE,IAAA,QAAA,IAAA,aAAA,gBAEE,2GAA2G,OACzG,GACF,EAAE,wCACJ,OAAO,cAAc,CACvB,CACF;GACF;GACA,OAAO,YAAY,MAAM,QAAQ;IAC/B,eAAe,gBAAgB;IAE/B,aAAa;IAEb,IAAI,sBAAsB;IAE1B,IAAI,OAAO,eAAe,UAAU;KAClC,oBAAoB;KACpB,IAAA,QAAA,IAAA,aAAA,cACE,uBAAuB;IAE3B;IAEA,IAAI,CAAC,iBAAiB,WAAW,KAAK,GAAG;KACvC,oBAAoB;KACpB,IAAA,QAAA,IAAA,aAAA,cACE,uBAAuB;IAE3B;IAEA,IAAI,CAAC,iBAAiB,WAAW,OAAO,GAAG;KACzC,oBAAoB;KACpB,IAAA,QAAA,IAAA,aAAA,cACE,uBAAuB;IAE3B;IAEA,IAAI,mBAAmB;KACrB,IAAI;KACJ,IAAI;MACF,aAAa,KAAK,UAAU,UAAU;KACxC,SAAA,SAAQ,CAAC;KACT,QAAQ,MACN,mBACE,mBAAA,QAAA,IAAA,aAAA,gBAEE,oDAAoD,OAClD,cACF,EAAE,iFACJ,eACA,OAAO,cAAc,GACrB,UACF,GACA,UACF;KACA,eAAe,sBAAsB,gBAAgB,kBAAkB,mBAAmB;KAC1F,OAAO;IACT;IAEA,IAAI,WAAW,YAAY,WAAW,SAAS,UAC7C,eAAe,SAAS,WAAW,OAAO,OAAO,CAAC,GAAG,IAAI,SAAS,UAAU,WAAW,SAAS,QAAQ;IAG1G,eAAe,SAAS,kBAAkB;IAC1C,eAAe,YAAY,eAAe,YAAY,aAAa,KAAK;IACxE,eAAe,QAAQ,eAAe,YAAY,SAAS,KAAK;IAChE,eAAe,UAAU,eAAe,YAAY,WAAW,KAAK;IACpE,eAAe,SAAS,eAAe,YAAY,UAAU,KAAK;IAClE,eAAe,WAAW,uBAAuB,WAAW,QAAQ;IAEpE,OAAO,eAAe;IAMtB,OAAO;GACT,CAAC;EACH,CAAC,CAAC,CACD,OAAO,QAAQ;GACd,OAAO,eAAe;GAEtB,IAAI;GACJ,IAAI,WACF,YAAY,kBAAkB;QACzB;IACL,YAAY,kBAAkB;IAC9B,eAAe,iCAAgB,IAAI,KAAK,EAAC,CAAC,QAAQ;GACpD;GACA,eAAe,KAAK,gBAAgB,SAAS;GAM7C,OAAO;EACT,CAAC;CACL,CAAC;AACH"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { AppOrParcelStatus } from "../applications/app.helpers.js";
|
|
2
|
+
import { handleAppError, transformErr } from "../applications/app-errors.js";
|
|
3
|
+
import "../devtools/profiler.js";
|
|
4
|
+
import { toUnmountPromise } from "./unmount.js";
|
|
5
|
+
import { reasonableTime } from "../applications/timeouts.js";
|
|
6
|
+
//#region src/lifecycles/mount.ts
|
|
7
|
+
var beforeFirstMountFired = false;
|
|
8
|
+
var firstMountFired = false;
|
|
9
|
+
function toMountPromise(appOrParcel, hardFail) {
|
|
10
|
+
return Promise.resolve().then(() => {
|
|
11
|
+
if (appOrParcel.status !== AppOrParcelStatus.NOT_MOUNTED) return appOrParcel;
|
|
12
|
+
if (!beforeFirstMountFired) {
|
|
13
|
+
window.dispatchEvent(new CustomEvent("single-spa:before-first-mount"));
|
|
14
|
+
beforeFirstMountFired = true;
|
|
15
|
+
}
|
|
16
|
+
appOrParcel.status = AppOrParcelStatus.MOUNTING;
|
|
17
|
+
return reasonableTime(appOrParcel, "mount").then(() => {
|
|
18
|
+
appOrParcel.status = AppOrParcelStatus.MOUNTED;
|
|
19
|
+
if (!firstMountFired) {
|
|
20
|
+
window.dispatchEvent(new CustomEvent("single-spa:first-mount"));
|
|
21
|
+
firstMountFired = true;
|
|
22
|
+
}
|
|
23
|
+
return appOrParcel;
|
|
24
|
+
}).catch((err) => {
|
|
25
|
+
appOrParcel.status = AppOrParcelStatus.MOUNTED;
|
|
26
|
+
return toUnmountPromise(appOrParcel, true).then(setSkipBecauseBroken, setSkipBecauseBroken);
|
|
27
|
+
function setSkipBecauseBroken() {
|
|
28
|
+
if (!hardFail) {
|
|
29
|
+
handleAppError(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
30
|
+
return appOrParcel;
|
|
31
|
+
} else throw transformErr(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { toMountPromise };
|
|
38
|
+
|
|
39
|
+
//# sourceMappingURL=mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount.js","names":[],"sources":["../../../src/lifecycles/mount.ts"],"sourcesContent":["import { toName, isParcel, AppOrParcelStatus } from '../applications/app.helpers';\nimport { handleAppError, transformErr } from '../applications/app-errors';\nimport { reasonableTime } from '../applications/timeouts';\nimport { toUnmountPromise } from './unmount';\nimport { ProfileEntry, addProfileEntry } from '../devtools/profiler';\nimport { LoadedAppOrParcel } from './lifecycle.helpers';\n\nlet beforeFirstMountFired: boolean = false;\nlet firstMountFired: boolean = false;\n\nexport function toMountPromise(appOrParcel: LoadedAppOrParcel, hardFail?: boolean): Promise<LoadedAppOrParcel> {\n return Promise.resolve().then(() => {\n if (appOrParcel.status !== AppOrParcelStatus.NOT_MOUNTED) {\n return appOrParcel;\n }\n\n let startTime: number, profileEventType: ProfileEntry['type'];\n\n if (__PROFILE__) {\n profileEventType = isParcel(appOrParcel) ? 'parcel' : 'application';\n startTime = performance.now();\n }\n\n if (!beforeFirstMountFired) {\n window.dispatchEvent(new CustomEvent('single-spa:before-first-mount'));\n beforeFirstMountFired = true;\n }\n\n appOrParcel.status = AppOrParcelStatus.MOUNTING;\n\n return reasonableTime(appOrParcel, 'mount')\n .then(() => {\n appOrParcel.status = AppOrParcelStatus.MOUNTED;\n\n if (!firstMountFired) {\n window.dispatchEvent(new CustomEvent('single-spa:first-mount'));\n firstMountFired = true;\n }\n\n if (__PROFILE__) {\n addProfileEntry(profileEventType, toName(appOrParcel), 'mount', startTime, performance.now(), true);\n }\n\n return appOrParcel;\n })\n .catch((err) => {\n // If we fail to mount the appOrParcel, we should attempt to unmount it before putting in SKIP_BECAUSE_BROKEN\n // We temporarily put the appOrParcel into MOUNTED status so that toUnmountPromise actually attempts to unmount it\n // instead of just doing a no-op.\n appOrParcel.status = AppOrParcelStatus.MOUNTED;\n return toUnmountPromise(appOrParcel, true).then(setSkipBecauseBroken, setSkipBecauseBroken);\n\n function setSkipBecauseBroken() {\n if (__PROFILE__) {\n addProfileEntry(profileEventType, toName(appOrParcel), 'mount', startTime, performance.now(), false);\n }\n\n if (!hardFail) {\n handleAppError(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n return appOrParcel;\n } else {\n throw transformErr(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n }\n }\n });\n });\n}\n"],"mappings":";;;;;;AAOA,IAAI,wBAAiC;AACrC,IAAI,kBAA2B;AAE/B,SAAgB,eAAe,aAAgC,UAAgD;CAC7G,OAAO,QAAQ,QAAQ,CAAC,CAAC,WAAW;EAClC,IAAI,YAAY,WAAW,kBAAkB,aAC3C,OAAO;EAUT,IAAI,CAAC,uBAAuB;GAC1B,OAAO,cAAc,IAAI,YAAY,+BAA+B,CAAC;GACrE,wBAAwB;EAC1B;EAEA,YAAY,SAAS,kBAAkB;EAEvC,OAAO,eAAe,aAAa,OAAO,CAAC,CACxC,WAAW;GACV,YAAY,SAAS,kBAAkB;GAEvC,IAAI,CAAC,iBAAiB;IACpB,OAAO,cAAc,IAAI,YAAY,wBAAwB,CAAC;IAC9D,kBAAkB;GACpB;GAMA,OAAO;EACT,CAAC,CAAC,CACD,OAAO,QAAQ;GAId,YAAY,SAAS,kBAAkB;GACvC,OAAO,iBAAiB,aAAa,IAAI,CAAC,CAAC,KAAK,sBAAsB,oBAAoB;GAE1F,SAAS,uBAAuB;IAK9B,IAAI,CAAC,UAAU;KACb,eAAe,KAAK,aAAa,kBAAkB,mBAAmB;KACtE,OAAO;IACT,OACE,MAAM,aAAa,KAAK,aAAa,kBAAkB,mBAAmB;GAE9E;EACF,CAAC;CACL,CAAC;AACH"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { mountParcel } from '../parcels/mount-parcel';
|
|
2
|
+
import { AppOrParcel, CustomProps } from './lifecycle.helpers';
|
|
3
|
+
interface SingleSpaProps {
|
|
4
|
+
name: string;
|
|
5
|
+
mountParcel: typeof mountParcel;
|
|
6
|
+
unmountSelf(): Promise<AppOrParcel>;
|
|
7
|
+
}
|
|
8
|
+
export declare function getProps(appOrParcel: AppOrParcel): SingleSpaProps & CustomProps;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { isParcel, toName } from "../applications/app.helpers.js";
|
|
2
|
+
import { formatErrorMessage } from "../applications/app-errors.js";
|
|
3
|
+
import { mountParcel } from "../parcels/mount-parcel.js";
|
|
4
|
+
//#region src/lifecycles/prop.helpers.ts
|
|
5
|
+
function getProps(appOrParcel) {
|
|
6
|
+
const name = toName(appOrParcel);
|
|
7
|
+
let customProps = typeof appOrParcel.customProps === "function" ? appOrParcel.customProps(name, window.location) : appOrParcel.customProps;
|
|
8
|
+
if (typeof customProps !== "object" || customProps === null || Array.isArray(customProps)) {
|
|
9
|
+
customProps = {};
|
|
10
|
+
console.warn(formatErrorMessage(40, process.env.NODE_ENV !== "production" && `single-spa: ${name}'s customProps function must return an object. Received ${customProps}`), name, customProps);
|
|
11
|
+
}
|
|
12
|
+
const result = Object.assign({}, customProps, {
|
|
13
|
+
name,
|
|
14
|
+
mountParcel: mountParcel.bind(appOrParcel)
|
|
15
|
+
});
|
|
16
|
+
if (isParcel(appOrParcel)) result.unmountSelf = appOrParcel.unmountThisParcel;
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { getProps };
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=prop.helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prop.helpers.js","names":[],"sources":["../../../src/lifecycles/prop.helpers.ts"],"sourcesContent":["import { mountParcel } from '../parcels/mount-parcel';\nimport { isParcel, toName } from '../applications/app.helpers';\nimport { formatErrorMessage } from '../applications/app-errors';\nimport { AppOrParcel, CustomProps, InternalParcel } from './lifecycle.helpers';\n\ninterface SingleSpaProps {\n name: string;\n mountParcel: typeof mountParcel;\n unmountSelf(): Promise<AppOrParcel>;\n}\n\nexport function getProps(appOrParcel: AppOrParcel): SingleSpaProps & CustomProps {\n const name = toName(appOrParcel);\n let customProps =\n typeof appOrParcel.customProps === 'function'\n ? appOrParcel.customProps(name, window.location)\n : appOrParcel.customProps;\n if (typeof customProps !== 'object' || customProps === null || Array.isArray(customProps)) {\n customProps = {};\n console.warn(\n formatErrorMessage(\n 40,\n __DEV__ && `single-spa: ${name}'s customProps function must return an object. Received ${customProps}`,\n ),\n name,\n customProps,\n );\n }\n const result: SingleSpaProps = Object.assign({}, customProps, {\n name,\n mountParcel: mountParcel.bind(appOrParcel),\n });\n\n if (isParcel(appOrParcel)) {\n result.unmountSelf = appOrParcel.unmountThisParcel;\n }\n\n return result;\n}\n"],"mappings":";;;;AAWA,SAAgB,SAAS,aAAwD;CAC/E,MAAM,OAAO,OAAO,WAAW;CAC/B,IAAI,cACF,OAAO,YAAY,gBAAgB,aAC/B,YAAY,YAAY,MAAM,OAAO,QAAQ,IAC7C,YAAY;CAClB,IAAI,OAAO,gBAAgB,YAAY,gBAAgB,QAAQ,MAAM,QAAQ,WAAW,GAAG;EACzF,cAAc,CAAC;EACf,QAAQ,KACN,mBACE,IAAA,QAAA,IAAA,aAAA,gBACW,eAAe,KAAK,0DAA0D,aAC3F,GACA,MACA,WACF;CACF;CACA,MAAM,SAAyB,OAAO,OAAO,CAAC,GAAG,aAAa;EAC5D;EACA,aAAa,YAAY,KAAK,WAAW;CAC3C,CAAC;CAED,IAAI,SAAS,WAAW,GACtB,OAAO,cAAc,YAAY;CAGnC,OAAO;AACT"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InternalApplication } from '../applications/app.helpers';
|
|
2
|
+
import { LoadedApp } from './lifecycle.helpers';
|
|
3
|
+
interface UnloadInfo {
|
|
4
|
+
app: InternalApplication;
|
|
5
|
+
promise?: Promise<any>;
|
|
6
|
+
resolve: (val?: any) => void;
|
|
7
|
+
reject: (val?: any) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare function toUnloadPromise(app: LoadedApp): Promise<LoadedApp>;
|
|
10
|
+
export declare function addAppToUnload(app: InternalApplication, promiseGetter: () => Promise<any>, resolve: (val?: any) => any, reject: (val?: any) => any): void;
|
|
11
|
+
export declare function getAppUnloadInfo(appName: string): UnloadInfo;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AppOrParcelStatus, toName } from "../applications/app.helpers.js";
|
|
2
|
+
import { handleAppError } from "../applications/app-errors.js";
|
|
3
|
+
import "../devtools/profiler.js";
|
|
4
|
+
import { reasonableTime } from "../applications/timeouts.js";
|
|
5
|
+
//#region src/lifecycles/unload.ts
|
|
6
|
+
var appsToUnload = {};
|
|
7
|
+
function toUnloadPromise(app) {
|
|
8
|
+
return Promise.resolve().then(() => {
|
|
9
|
+
const unloadInfo = appsToUnload[toName(app)];
|
|
10
|
+
if (!unloadInfo) return app;
|
|
11
|
+
if (app.status === AppOrParcelStatus.NOT_LOADED) {
|
|
12
|
+
finishUnloadingApp(app, unloadInfo);
|
|
13
|
+
return app;
|
|
14
|
+
}
|
|
15
|
+
if (app.status === AppOrParcelStatus.UNLOADING) return unloadInfo.promise.then(() => app);
|
|
16
|
+
if (app.status !== AppOrParcelStatus.NOT_MOUNTED && app.status !== AppOrParcelStatus.LOAD_ERROR && app.status !== AppOrParcelStatus.SKIP_BECAUSE_BROKEN) return app;
|
|
17
|
+
const unloadPromise = app.unload ? reasonableTime(app, "unload") : Promise.resolve();
|
|
18
|
+
app.status = AppOrParcelStatus.UNLOADING;
|
|
19
|
+
return unloadPromise.then(() => {
|
|
20
|
+
finishUnloadingApp(app, unloadInfo);
|
|
21
|
+
return app;
|
|
22
|
+
}).catch((err) => {
|
|
23
|
+
errorUnloadingApp(app, unloadInfo, err);
|
|
24
|
+
return app;
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function finishUnloadingApp(app, unloadInfo) {
|
|
29
|
+
delete appsToUnload[toName(app)];
|
|
30
|
+
delete app.bootstrap;
|
|
31
|
+
delete app.mount;
|
|
32
|
+
delete app.unmount;
|
|
33
|
+
delete app.unload;
|
|
34
|
+
app.status = AppOrParcelStatus.NOT_LOADED;
|
|
35
|
+
unloadInfo.resolve();
|
|
36
|
+
}
|
|
37
|
+
function errorUnloadingApp(app, unloadInfo, err) {
|
|
38
|
+
delete appsToUnload[toName(app)];
|
|
39
|
+
delete app.bootstrap;
|
|
40
|
+
delete app.mount;
|
|
41
|
+
delete app.unmount;
|
|
42
|
+
delete app.unload;
|
|
43
|
+
handleAppError(err, app, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
44
|
+
unloadInfo.reject(err);
|
|
45
|
+
}
|
|
46
|
+
function addAppToUnload(app, promiseGetter, resolve, reject) {
|
|
47
|
+
appsToUnload[toName(app)] = {
|
|
48
|
+
app,
|
|
49
|
+
resolve,
|
|
50
|
+
reject
|
|
51
|
+
};
|
|
52
|
+
Object.defineProperty(appsToUnload[toName(app)], "promise", { get: promiseGetter });
|
|
53
|
+
}
|
|
54
|
+
function getAppUnloadInfo(appName) {
|
|
55
|
+
return appsToUnload[appName];
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { addAppToUnload, getAppUnloadInfo, toUnloadPromise };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=unload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unload.js","names":[],"sources":["../../../src/lifecycles/unload.ts"],"sourcesContent":["import { toName, AppOrParcelStatus, InternalApplication } from '../applications/app.helpers';\nimport { handleAppError } from '../applications/app-errors';\nimport { reasonableTime } from '../applications/timeouts';\nimport { addProfileEntry } from '../devtools/profiler';\nimport { LoadedApp } from './lifecycle.helpers';\n\ninterface UnloadInfo {\n app: InternalApplication;\n promise?: Promise<any>;\n resolve: (val?) => void;\n reject: (val?) => void;\n}\n\nconst appsToUnload: Record<string, UnloadInfo> = {};\n\nexport function toUnloadPromise(app: LoadedApp): Promise<LoadedApp> {\n return Promise.resolve().then(() => {\n const unloadInfo = appsToUnload[toName(app)];\n\n if (!unloadInfo) {\n /* No one has called unloadApplication for this app,\n */\n return app;\n }\n\n if (app.status === AppOrParcelStatus.NOT_LOADED) {\n /* This app is already unloaded. We just need to clean up\n * anything that still thinks we need to unload the app.\n */\n finishUnloadingApp(app, unloadInfo);\n return app;\n }\n\n if (app.status === AppOrParcelStatus.UNLOADING) {\n /* Both unloadApplication and reroute want to unload this app.\n * It only needs to be done once, though.\n */\n return unloadInfo.promise!.then(() => app);\n }\n\n if (\n app.status !== AppOrParcelStatus.NOT_MOUNTED &&\n app.status !== AppOrParcelStatus.LOAD_ERROR &&\n app.status !== AppOrParcelStatus.SKIP_BECAUSE_BROKEN\n ) {\n /* The app cannot be unloaded unless in certain statuses\n */\n return app;\n }\n\n let startTime: number;\n\n if (__PROFILE__) {\n startTime = performance.now();\n }\n\n const unloadPromise = app.unload ? reasonableTime(app, 'unload') : Promise.resolve();\n\n app.status = AppOrParcelStatus.UNLOADING;\n\n return unloadPromise\n .then(() => {\n if (__PROFILE__) {\n addProfileEntry('application', toName(app), 'unload', startTime, performance.now(), true);\n }\n\n finishUnloadingApp(app, unloadInfo);\n\n return app;\n })\n .catch((err) => {\n if (__PROFILE__) {\n addProfileEntry('application', toName(app), 'unload', startTime, performance.now(), false);\n }\n\n errorUnloadingApp(app, unloadInfo, err);\n\n return app;\n });\n });\n}\n\nfunction finishUnloadingApp(app: LoadedApp, unloadInfo: UnloadInfo) {\n delete appsToUnload[toName(app)];\n\n // Unloaded apps don't have lifecycles\n delete app.bootstrap;\n delete app.mount;\n delete app.unmount;\n delete app.unload;\n\n app.status = AppOrParcelStatus.NOT_LOADED;\n\n /* resolve the promise of whoever called unloadApplication.\n * This should be done after all other cleanup/bookkeeping\n */\n unloadInfo.resolve();\n}\n\nfunction errorUnloadingApp(app: LoadedApp, unloadInfo: UnloadInfo, err: Error) {\n delete appsToUnload[toName(app)];\n\n // Unloaded apps don't have lifecycles\n delete app.bootstrap;\n delete app.mount;\n delete app.unmount;\n delete app.unload;\n\n handleAppError(err, app, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n unloadInfo.reject(err);\n}\n\nexport function addAppToUnload(\n app: InternalApplication,\n promiseGetter: () => Promise<any>,\n resolve: (val?) => any,\n reject: (val?) => any,\n) {\n appsToUnload[toName(app)] = { app, resolve, reject };\n Object.defineProperty(appsToUnload[toName(app)], 'promise', {\n get: promiseGetter,\n });\n}\n\nexport function getAppUnloadInfo(appName: string): UnloadInfo {\n return appsToUnload[appName];\n}\n"],"mappings":";;;;;AAaA,IAAM,eAA2C,CAAC;AAElD,SAAgB,gBAAgB,KAAoC;CAClE,OAAO,QAAQ,QAAQ,CAAC,CAAC,WAAW;EAClC,MAAM,aAAa,aAAa,OAAO,GAAG;EAE1C,IAAI,CAAC,YAGH,OAAO;EAGT,IAAI,IAAI,WAAW,kBAAkB,YAAY;GAI/C,mBAAmB,KAAK,UAAU;GAClC,OAAO;EACT;EAEA,IAAI,IAAI,WAAW,kBAAkB,WAInC,OAAO,WAAW,QAAS,WAAW,GAAG;EAG3C,IACE,IAAI,WAAW,kBAAkB,eACjC,IAAI,WAAW,kBAAkB,cACjC,IAAI,WAAW,kBAAkB,qBAIjC,OAAO;EAST,MAAM,gBAAgB,IAAI,SAAS,eAAe,KAAK,QAAQ,IAAI,QAAQ,QAAQ;EAEnF,IAAI,SAAS,kBAAkB;EAE/B,OAAO,cACJ,WAAW;GAKV,mBAAmB,KAAK,UAAU;GAElC,OAAO;EACT,CAAC,CAAC,CACD,OAAO,QAAQ;GAKd,kBAAkB,KAAK,YAAY,GAAG;GAEtC,OAAO;EACT,CAAC;CACL,CAAC;AACH;AAEA,SAAS,mBAAmB,KAAgB,YAAwB;CAClE,OAAO,aAAa,OAAO,GAAG;CAG9B,OAAO,IAAI;CACX,OAAO,IAAI;CACX,OAAO,IAAI;CACX,OAAO,IAAI;CAEX,IAAI,SAAS,kBAAkB;CAK/B,WAAW,QAAQ;AACrB;AAEA,SAAS,kBAAkB,KAAgB,YAAwB,KAAY;CAC7E,OAAO,aAAa,OAAO,GAAG;CAG9B,OAAO,IAAI;CACX,OAAO,IAAI;CACX,OAAO,IAAI;CACX,OAAO,IAAI;CAEX,eAAe,KAAK,KAAK,kBAAkB,mBAAmB;CAC9D,WAAW,OAAO,GAAG;AACvB;AAEA,SAAgB,eACd,KACA,eACA,SACA,QACA;CACA,aAAa,OAAO,GAAG,KAAK;EAAE;EAAK;EAAS;CAAO;CACnD,OAAO,eAAe,aAAa,OAAO,GAAG,IAAI,WAAW,EAC1D,KAAK,cACP,CAAC;AACH;AAEA,SAAgB,iBAAiB,SAA6B;CAC5D,OAAO,aAAa;AACtB"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AppOrParcelStatus } from "../applications/app.helpers.js";
|
|
2
|
+
import { handleAppError, transformErr } from "../applications/app-errors.js";
|
|
3
|
+
import "../devtools/profiler.js";
|
|
4
|
+
import { reasonableTime } from "../applications/timeouts.js";
|
|
5
|
+
//#region src/lifecycles/unmount.ts
|
|
6
|
+
function toUnmountPromise(appOrParcel, hardFail) {
|
|
7
|
+
return Promise.resolve().then(() => {
|
|
8
|
+
if (appOrParcel.status !== AppOrParcelStatus.MOUNTED) return appOrParcel;
|
|
9
|
+
appOrParcel.status = AppOrParcelStatus.UNMOUNTING;
|
|
10
|
+
const unmountChildrenParcels = Object.keys(appOrParcel.parcels).map((parcelId) => appOrParcel.parcels[parcelId].unmountThisParcel());
|
|
11
|
+
return Promise.all(unmountChildrenParcels).then(unmountAppOrParcel, (parcelError) => {
|
|
12
|
+
return unmountAppOrParcel().then(() => {
|
|
13
|
+
const parentError = Error(parcelError.message);
|
|
14
|
+
if (hardFail) throw transformErr(parentError, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
15
|
+
else handleAppError(parentError, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
16
|
+
});
|
|
17
|
+
}).then(() => appOrParcel);
|
|
18
|
+
function unmountAppOrParcel() {
|
|
19
|
+
return reasonableTime(appOrParcel, "unmount").then(() => {
|
|
20
|
+
appOrParcel.status = AppOrParcelStatus.NOT_MOUNTED;
|
|
21
|
+
}, (err) => {
|
|
22
|
+
if (hardFail) throw transformErr(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
23
|
+
else handleAppError(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { toUnmountPromise };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=unmount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unmount.js","names":[],"sources":["../../../src/lifecycles/unmount.ts"],"sourcesContent":["import { AppOrParcelStatus, toName, isParcel } from '../applications/app.helpers';\nimport { handleAppError, transformErr } from '../applications/app-errors';\nimport { reasonableTime } from '../applications/timeouts';\nimport { ProfileEntry, addProfileEntry } from '../devtools/profiler';\nimport { LoadedAppOrParcel } from './lifecycle.helpers';\n\nexport function toUnmountPromise(appOrParcel: LoadedAppOrParcel, hardFail?: boolean): Promise<LoadedAppOrParcel> {\n return Promise.resolve().then(() => {\n if (appOrParcel.status !== AppOrParcelStatus.MOUNTED) {\n return appOrParcel;\n }\n\n let startTime: number, profileEventType: ProfileEntry['type'];\n\n if (__PROFILE__) {\n startTime = performance.now();\n profileEventType = isParcel(appOrParcel) ? 'parcel' : 'application';\n }\n\n appOrParcel.status = AppOrParcelStatus.UNMOUNTING;\n\n const unmountChildrenParcels = Object.keys(appOrParcel.parcels).map((parcelId) =>\n appOrParcel.parcels[parcelId].unmountThisParcel(),\n );\n\n let parcelError: Error;\n\n return Promise.all(unmountChildrenParcels)\n .then(unmountAppOrParcel, (parcelError) => {\n // There is a parcel unmount error\n return unmountAppOrParcel().then(() => {\n // Unmounting the app/parcel succeeded, but unmounting its children parcels did not\n const parentError = Error(parcelError.message);\n if (hardFail) {\n throw transformErr(parentError, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n } else {\n handleAppError(parentError, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n }\n });\n })\n .then(() => appOrParcel);\n\n function unmountAppOrParcel() {\n // We always try to unmount the appOrParcel, even if the children parcels failed to unmount.\n return reasonableTime(appOrParcel, 'unmount').then(\n () => {\n // The appOrParcel needs to stay in a broken status if its children parcels fail to unmount\n if (!parcelError) {\n appOrParcel.status = AppOrParcelStatus.NOT_MOUNTED;\n }\n\n if (__PROFILE__) {\n addProfileEntry(profileEventType, toName(appOrParcel), 'unmount', startTime, performance.now(), true);\n }\n },\n (err) => {\n if (__PROFILE__) {\n addProfileEntry(profileEventType, toName(appOrParcel), 'unmount', startTime, performance.now(), false);\n }\n\n if (hardFail) {\n throw transformErr(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n } else {\n handleAppError(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n }\n },\n );\n }\n });\n}\n"],"mappings":";;;;;AAMA,SAAgB,iBAAiB,aAAgC,UAAgD;CAC/G,OAAO,QAAQ,QAAQ,CAAC,CAAC,WAAW;EAClC,IAAI,YAAY,WAAW,kBAAkB,SAC3C,OAAO;EAUT,YAAY,SAAS,kBAAkB;EAEvC,MAAM,yBAAyB,OAAO,KAAK,YAAY,OAAO,CAAC,CAAC,KAAK,aACnE,YAAY,QAAQ,SAAS,CAAC,kBAAkB,CAClD;EAIA,OAAO,QAAQ,IAAI,sBAAsB,CAAC,CACvC,KAAK,qBAAqB,gBAAgB;GAEzC,OAAO,mBAAmB,CAAC,CAAC,WAAW;IAErC,MAAM,cAAc,MAAM,YAAY,OAAO;IAC7C,IAAI,UACF,MAAM,aAAa,aAAa,aAAa,kBAAkB,mBAAmB;SAElF,eAAe,aAAa,aAAa,kBAAkB,mBAAmB;GAElF,CAAC;EACH,CAAC,CAAC,CACD,WAAW,WAAW;EAEzB,SAAS,qBAAqB;GAE5B,OAAO,eAAe,aAAa,SAAS,CAAC,CAAC,WACtC;IAGF,YAAY,SAAS,kBAAkB;GAM3C,IACC,QAAQ;IAKP,IAAI,UACF,MAAM,aAAa,KAAK,aAAa,kBAAkB,mBAAmB;SAE1E,eAAe,KAAK,aAAa,kBAAkB,mBAAmB;GAE1E,CACF;EACF;CACF,CAAC;AACH"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AppOrParcelStatus, toName } from "../applications/app.helpers.js";
|
|
2
|
+
import { formatErrorMessage, transformErr } from "../applications/app-errors.js";
|
|
3
|
+
import "../devtools/profiler.js";
|
|
4
|
+
import { reasonableTime } from "../applications/timeouts.js";
|
|
5
|
+
//#region src/lifecycles/update.ts
|
|
6
|
+
function toUpdatePromise(appOrParcel) {
|
|
7
|
+
return Promise.resolve().then(() => {
|
|
8
|
+
if (appOrParcel.status !== AppOrParcelStatus.MOUNTED) throw Error(formatErrorMessage(32, process.env.NODE_ENV !== "production" && `Cannot update parcel '${toName(appOrParcel)}' because it is not mounted`, toName(appOrParcel)));
|
|
9
|
+
appOrParcel.status = AppOrParcelStatus.UPDATING;
|
|
10
|
+
return reasonableTime(appOrParcel, "update").then(() => {
|
|
11
|
+
appOrParcel.status = AppOrParcelStatus.MOUNTED;
|
|
12
|
+
return appOrParcel;
|
|
13
|
+
}).catch((err) => {
|
|
14
|
+
throw transformErr(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
19
|
+
export { toUpdatePromise };
|
|
20
|
+
|
|
21
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","names":[],"sources":["../../../src/lifecycles/update.ts"],"sourcesContent":["import { AppOrParcelStatus, toName, isParcel } from '../applications/app.helpers';\nimport { transformErr, formatErrorMessage } from '../applications/app-errors';\nimport { reasonableTime } from '../applications/timeouts';\nimport { ProfileEntry, addProfileEntry } from '../devtools/profiler';\nimport { LoadedAppOrParcel } from './lifecycle.helpers';\n\nexport function toUpdatePromise(appOrParcel: LoadedAppOrParcel): Promise<LoadedAppOrParcel> {\n return Promise.resolve().then(() => {\n let startTime: number, profileEventType: ProfileEntry['type'];\n\n if (__PROFILE__) {\n profileEventType = isParcel(appOrParcel) ? 'parcel' : 'application';\n startTime = performance.now();\n }\n\n if (appOrParcel.status !== AppOrParcelStatus.MOUNTED) {\n throw Error(\n formatErrorMessage(\n 32,\n __DEV__ && `Cannot update parcel '${toName(appOrParcel)}' because it is not mounted`,\n toName(appOrParcel),\n ),\n );\n }\n\n appOrParcel.status = AppOrParcelStatus.UPDATING;\n\n return reasonableTime(appOrParcel, 'update')\n .then(() => {\n appOrParcel.status = AppOrParcelStatus.MOUNTED;\n\n if (__PROFILE__) {\n addProfileEntry(profileEventType, toName(appOrParcel), 'update', startTime, performance.now(), true);\n }\n\n return appOrParcel;\n })\n .catch((err) => {\n if (__PROFILE__) {\n addProfileEntry(profileEventType, toName(appOrParcel), 'update', startTime, performance.now(), false);\n }\n\n throw transformErr(err, appOrParcel, AppOrParcelStatus.SKIP_BECAUSE_BROKEN);\n });\n });\n}\n"],"mappings":";;;;;AAMA,SAAgB,gBAAgB,aAA4D;CAC1F,OAAO,QAAQ,QAAQ,CAAC,CAAC,WAAW;EAQlC,IAAI,YAAY,WAAW,kBAAkB,SAC3C,MAAM,MACJ,mBACE,IAAA,QAAA,IAAA,aAAA,gBACW,yBAAyB,OAAO,WAAW,EAAE,8BACxD,OAAO,WAAW,CACpB,CACF;EAGF,YAAY,SAAS,kBAAkB;EAEvC,OAAO,eAAe,aAAa,QAAQ,CAAC,CACzC,WAAW;GACV,YAAY,SAAS,kBAAkB;GAMvC,OAAO;EACT,CAAC,CAAC,CACD,OAAO,QAAQ;GAKd,MAAM,aAAa,KAAK,aAAa,kBAAkB,mBAAmB;EAC5E,CAAC;CACL,CAAC;AACH"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StartOpts } from '../start';
|
|
2
|
+
export declare const routingEventsListeningTo: string[];
|
|
3
|
+
type NavigateArg = string | HTMLAnchorElement | MouseEvent;
|
|
4
|
+
export declare function navigateToUrl(obj: NavigateArg): void;
|
|
5
|
+
export declare function callCapturedEventListeners(eventArguments: [HashChangeEvent | PopStateEvent]): void;
|
|
6
|
+
export declare let originalReplaceState: (data: any, unused: string, url?: string | URL) => void;
|
|
7
|
+
export declare function patchHistoryApi(opts?: StartOpts): void;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { formatErrorMessage } from "../applications/app-errors.js";
|
|
2
|
+
import { isInBrowser } from "../utils/runtime-environment.js";
|
|
3
|
+
import { reroute } from "./reroute.js";
|
|
4
|
+
//#region src/navigation/navigation-events.ts
|
|
5
|
+
var capturedEventListeners = {
|
|
6
|
+
hashchange: [],
|
|
7
|
+
popstate: []
|
|
8
|
+
};
|
|
9
|
+
var routingEventsListeningTo = ["hashchange", "popstate"];
|
|
10
|
+
function navigateToUrl(obj) {
|
|
11
|
+
let url;
|
|
12
|
+
if (typeof obj === "string") url = obj;
|
|
13
|
+
else if (this && this.href) url = this.href;
|
|
14
|
+
else if (obj && "currentTarget" in obj && "href" in obj.currentTarget && "preventDefault" in obj) {
|
|
15
|
+
url = obj.currentTarget.href;
|
|
16
|
+
obj.preventDefault();
|
|
17
|
+
} else throw Error(formatErrorMessage(14, process.env.NODE_ENV !== "production" && `singleSpaNavigate/navigateToUrl must be either called with a string url, with an <a> tag as its context, or with an event whose currentTarget is an <a> tag`));
|
|
18
|
+
const current = new URL(window.location.href);
|
|
19
|
+
const destination = new URL(url, window.location.href);
|
|
20
|
+
if (url.indexOf("#") === 0) window.location.hash = destination.hash;
|
|
21
|
+
else if (current.host !== destination.host && destination.host) window.location.href = url;
|
|
22
|
+
else if (destination.pathname === current.pathname && destination.search === current.search) window.location.hash = destination.hash;
|
|
23
|
+
else window.history.pushState(null, null, url);
|
|
24
|
+
}
|
|
25
|
+
function callCapturedEventListeners(eventArguments) {
|
|
26
|
+
if (eventArguments) {
|
|
27
|
+
const eventType = eventArguments[0].type;
|
|
28
|
+
if (routingEventsListeningTo.indexOf(eventType) >= 0) capturedEventListeners[eventType].forEach((listener) => {
|
|
29
|
+
try {
|
|
30
|
+
listener.apply(this, eventArguments);
|
|
31
|
+
} catch (e) {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
throw e;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
var urlRerouteOnly;
|
|
40
|
+
function urlReroute(evt) {
|
|
41
|
+
reroute([], [evt]);
|
|
42
|
+
}
|
|
43
|
+
function patchedUpdateState(updateState, methodName) {
|
|
44
|
+
return function() {
|
|
45
|
+
const urlBefore = window.location.href;
|
|
46
|
+
const result = updateState.apply(this, arguments);
|
|
47
|
+
const urlAfter = window.location.href;
|
|
48
|
+
if (!urlRerouteOnly || urlBefore !== urlAfter) window.dispatchEvent(createPopStateEvent(window.history.state, methodName));
|
|
49
|
+
return result;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function createPopStateEvent(state, originalMethodName) {
|
|
53
|
+
let evt = new PopStateEvent("popstate", { state });
|
|
54
|
+
evt.singleSpa = true;
|
|
55
|
+
evt.singleSpaTrigger = originalMethodName;
|
|
56
|
+
return evt;
|
|
57
|
+
}
|
|
58
|
+
var originalReplaceState = null;
|
|
59
|
+
var historyApiIsPatched = false;
|
|
60
|
+
function patchHistoryApi(opts) {
|
|
61
|
+
if (historyApiIsPatched) throw Error(formatErrorMessage(43, process.env.NODE_ENV !== "production" && `single-spa: patchHistoryApi() was called after the history api was already patched.`));
|
|
62
|
+
urlRerouteOnly = (opts === null || opts === void 0 ? void 0 : opts.hasOwnProperty("urlRerouteOnly")) ? opts.urlRerouteOnly : true;
|
|
63
|
+
historyApiIsPatched = true;
|
|
64
|
+
originalReplaceState = window.history.replaceState;
|
|
65
|
+
window.addEventListener("hashchange", urlReroute);
|
|
66
|
+
window.addEventListener("popstate", urlReroute);
|
|
67
|
+
const originalAddEventListener = window.addEventListener;
|
|
68
|
+
const originalRemoveEventListener = window.removeEventListener;
|
|
69
|
+
window.addEventListener = function(eventName, fn) {
|
|
70
|
+
if (typeof fn === "function") {
|
|
71
|
+
if (routingEventsListeningTo.indexOf(eventName) >= 0 && !capturedEventListeners[eventName].find((listener) => listener === fn)) {
|
|
72
|
+
capturedEventListeners[eventName].push(fn);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return originalAddEventListener.apply(this, arguments);
|
|
77
|
+
};
|
|
78
|
+
window.removeEventListener = function(eventName, listenerFn) {
|
|
79
|
+
if (typeof listenerFn === "function") {
|
|
80
|
+
if (routingEventsListeningTo.includes(eventName)) capturedEventListeners[eventName] = capturedEventListeners[eventName].filter((fn) => fn !== listenerFn);
|
|
81
|
+
}
|
|
82
|
+
return originalRemoveEventListener.apply(this, arguments);
|
|
83
|
+
};
|
|
84
|
+
window.history.pushState = patchedUpdateState(window.history.pushState, "pushState");
|
|
85
|
+
window.history.replaceState = patchedUpdateState(originalReplaceState, "replaceState");
|
|
86
|
+
}
|
|
87
|
+
if (isInBrowser) if (window.singleSpaNavigate) console.warn(formatErrorMessage(41, process.env.NODE_ENV !== "production" && "single-spa has been loaded twice on the page. This can result in unexpected behavior."));
|
|
88
|
+
else window.singleSpaNavigate = navigateToUrl;
|
|
89
|
+
//#endregion
|
|
90
|
+
export { callCapturedEventListeners, navigateToUrl, originalReplaceState, patchHistoryApi, routingEventsListeningTo };
|
|
91
|
+
|
|
92
|
+
//# sourceMappingURL=navigation-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-events.js","names":[],"sources":["../../../src/navigation/navigation-events.ts"],"sourcesContent":["import { reroute } from './reroute';\nimport { formatErrorMessage } from '../applications/app-errors';\nimport { isInBrowser } from '../utils/runtime-environment';\nimport { StartOpts } from '../start';\n\n/* We capture navigation event listeners so that we can make sure\n * that application navigation listeners are not called until\n * single-spa has ensured that the correct applications are\n * unmounted and mounted.\n */\nconst capturedEventListeners: CapturedEventListeners = {\n hashchange: [],\n popstate: [],\n};\n\ninterface CapturedEventListeners {\n hashchange: ((this: Window, ev: HashChangeEvent) => any)[];\n popstate: ((this: Window, ev: PopStateEvent) => any)[];\n}\n\nexport const routingEventsListeningTo = ['hashchange', 'popstate'];\n\ntype NavigateArg = string | HTMLAnchorElement | MouseEvent;\n\nexport function navigateToUrl(obj: NavigateArg): void {\n let url;\n if (typeof obj === 'string') {\n url = obj;\n } else if (this && this.href) {\n url = this.href;\n } else if (obj && 'currentTarget' in obj && 'href' in obj.currentTarget && 'preventDefault' in obj) {\n url = ((obj as MouseEvent).currentTarget as HTMLAnchorElement).href;\n (obj as MouseEvent).preventDefault();\n } else {\n throw Error(\n formatErrorMessage(\n 14,\n __DEV__ &&\n `singleSpaNavigate/navigateToUrl must be either called with a string url, with an <a> tag as its context, or with an event whose currentTarget is an <a> tag`,\n ),\n );\n }\n\n const current = new URL(window.location.href);\n const destination = new URL(url, window.location.href);\n\n if (url.indexOf('#') === 0) {\n window.location.hash = destination.hash;\n } else if (current.host !== destination.host && destination.host) {\n if (process.env.BABEL_ENV === 'test') {\n // @ts-expect-error test-only return value\n return { wouldHaveReloadedThePage: true };\n } else {\n window.location.href = url;\n }\n } else if (destination.pathname === current.pathname && destination.search === current.search) {\n window.location.hash = destination.hash;\n } else {\n // different path, host, or query params\n window.history.pushState(null, null, url);\n }\n}\n\nexport function callCapturedEventListeners(eventArguments: [HashChangeEvent | PopStateEvent]): void {\n if (eventArguments) {\n const eventType = eventArguments[0].type;\n if (routingEventsListeningTo.indexOf(eventType) >= 0) {\n capturedEventListeners[eventType].forEach((listener) => {\n try {\n // The error thrown by application event listener should not break single-spa down.\n // Just like https://github.com/single-spa/single-spa/blob/85f5042dff960e40936f3a5069d56fc9477fac04/src/navigation/reroute.js#L140-L146 did\n listener.apply(this, eventArguments);\n } catch (e) {\n setTimeout(() => {\n throw e;\n });\n }\n });\n }\n }\n}\n\nlet urlRerouteOnly: boolean;\n\nfunction urlReroute(evt: HashChangeEvent | PopStateEvent) {\n reroute([], [evt]);\n}\n\ntype UpdateState = (data: any, unused: string, url?: string | URL) => void;\n\nfunction patchedUpdateState(updateState: UpdateState, methodName: 'pushState' | 'replaceState') {\n return function () {\n const urlBefore = window.location.href;\n const result = updateState.apply(this, arguments);\n const urlAfter = window.location.href;\n\n if (!urlRerouteOnly || urlBefore !== urlAfter) {\n // fire an artificial popstate event so that\n // single-spa applications know about routing that\n // occurs in a different application\n window.dispatchEvent(createPopStateEvent(window.history.state, methodName));\n }\n\n return result;\n };\n}\n\ninterface SingleSpaPopStateEvent extends PopStateEvent {\n singleSpa: boolean;\n singleSpaTrigger: string;\n}\n\nfunction createPopStateEvent(state, originalMethodName): SingleSpaPopStateEvent {\n // https://github.com/single-spa/single-spa/issues/224 and https://github.com/single-spa/single-spa-angular/issues/49\n // We need a popstate event even though the browser doesn't fire one by default when you call replaceState, so that\n // all the applications can reroute. We explicitly identify this extraneous event by setting singleSpa=true and\n // singleSpaTrigger=<pushState|replaceState> on the event instance.\n let evt = new PopStateEvent('popstate', { state });\n (evt as SingleSpaPopStateEvent).singleSpa = true;\n (evt as SingleSpaPopStateEvent).singleSpaTrigger = originalMethodName;\n return evt as SingleSpaPopStateEvent;\n}\n\nexport let originalReplaceState: (data: any, unused: string, url?: string | URL) => void = null;\n\nlet historyApiIsPatched: boolean = false;\n\n// We patch the history API so single-spa is notified of all calls to pushState/replaceState.\n// We patch addEventListener/removeEventListener so we can capture all popstate/hashchange event listeners,\n// and delay calling them until single-spa has finished mounting/unmounting applications\nexport function patchHistoryApi(opts?: StartOpts) {\n if (historyApiIsPatched) {\n throw Error(\n formatErrorMessage(\n 43,\n __DEV__ && `single-spa: patchHistoryApi() was called after the history api was already patched.`,\n ),\n );\n }\n\n // True by default, as a performance optimization that reduces\n // the number of extraneous popstate events\n urlRerouteOnly = opts?.hasOwnProperty('urlRerouteOnly') ? opts.urlRerouteOnly : true;\n\n historyApiIsPatched = true;\n\n originalReplaceState = window.history.replaceState;\n\n // We will trigger an app change for any routing events.\n window.addEventListener('hashchange', urlReroute);\n window.addEventListener('popstate', urlReroute);\n\n // Patch addEventListener so that we can ensure correct timing\n const originalAddEventListener = window.addEventListener;\n const originalRemoveEventListener = window.removeEventListener;\n window.addEventListener = function (eventName, fn) {\n if (typeof fn === 'function') {\n if (\n routingEventsListeningTo.indexOf(eventName) >= 0 &&\n !capturedEventListeners[eventName].find((listener) => listener === fn)\n ) {\n capturedEventListeners[eventName].push(fn);\n return;\n }\n }\n\n return originalAddEventListener.apply(this, arguments);\n };\n\n window.removeEventListener = function (eventName, listenerFn) {\n if (typeof listenerFn === 'function') {\n if (routingEventsListeningTo.includes(eventName)) {\n capturedEventListeners[eventName] = capturedEventListeners[eventName].filter((fn) => fn !== listenerFn);\n }\n }\n\n return originalRemoveEventListener.apply(this, arguments);\n };\n\n window.history.pushState = patchedUpdateState(window.history.pushState, 'pushState');\n window.history.replaceState = patchedUpdateState(originalReplaceState, 'replaceState');\n}\n\n// Detect if single-spa has already been loaded on the page.\n// If so, warn because this can result in lots of problems, including\n// lots of extraneous popstate events and unexpected results for\n// apis like getAppNames().\nif (isInBrowser) {\n if (window.singleSpaNavigate) {\n console.warn(\n formatErrorMessage(\n 41,\n __DEV__ && 'single-spa has been loaded twice on the page. This can result in unexpected behavior.',\n ),\n );\n } else {\n /* For convenience in `onclick` attributes, we expose a global function for navigating to\n * whatever an <a> tag's href is.\n */\n window.singleSpaNavigate = navigateToUrl;\n }\n}\n"],"mappings":";;;;AAUA,IAAM,yBAAiD;CACrD,YAAY,CAAC;CACb,UAAU,CAAC;AACb;AAOA,IAAa,2BAA2B,CAAC,cAAc,UAAU;AAIjE,SAAgB,cAAc,KAAwB;CACpD,IAAI;CACJ,IAAI,OAAO,QAAQ,UACjB,MAAM;MACD,IAAI,QAAQ,KAAK,MACtB,MAAM,KAAK;MACN,IAAI,OAAO,mBAAmB,OAAO,UAAU,IAAI,iBAAiB,oBAAoB,KAAK;EAClG,MAAQ,IAAmB,cAAoC;EAC/D,IAAoB,eAAe;CACrC,OACE,MAAM,MACJ,mBACE,IAAA,QAAA,IAAA,aAAA,gBAEE,6JACJ,CACF;CAGF,MAAM,UAAU,IAAI,IAAI,OAAO,SAAS,IAAI;CAC5C,MAAM,cAAc,IAAI,IAAI,KAAK,OAAO,SAAS,IAAI;CAErD,IAAI,IAAI,QAAQ,GAAG,MAAM,GACvB,OAAO,SAAS,OAAO,YAAY;MAC9B,IAAI,QAAQ,SAAS,YAAY,QAAQ,YAAY,MAKxD,OAAO,SAAS,OAAO;MAEpB,IAAI,YAAY,aAAa,QAAQ,YAAY,YAAY,WAAW,QAAQ,QACrF,OAAO,SAAS,OAAO,YAAY;MAGnC,OAAO,QAAQ,UAAU,MAAM,MAAM,GAAG;AAE5C;AAEA,SAAgB,2BAA2B,gBAAyD;CAClG,IAAI,gBAAgB;EAClB,MAAM,YAAY,eAAe,EAAE,CAAC;EACpC,IAAI,yBAAyB,QAAQ,SAAS,KAAK,GACjD,uBAAuB,UAAU,CAAC,SAAS,aAAa;GACtD,IAAI;IAGF,SAAS,MAAM,MAAM,cAAc;GACrC,SAAS,GAAG;IACV,iBAAiB;KACf,MAAM;IACR,CAAC;GACH;EACF,CAAC;CAEL;AACF;AAEA,IAAI;AAEJ,SAAS,WAAW,KAAsC;CACxD,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;AACnB;AAIA,SAAS,mBAAmB,aAA0B,YAA0C;CAC9F,OAAO,WAAY;EACjB,MAAM,YAAY,OAAO,SAAS;EAClC,MAAM,SAAS,YAAY,MAAM,MAAM,SAAS;EAChD,MAAM,WAAW,OAAO,SAAS;EAEjC,IAAI,CAAC,kBAAkB,cAAc,UAInC,OAAO,cAAc,oBAAoB,OAAO,QAAQ,OAAO,UAAU,CAAC;EAG5E,OAAO;CACT;AACF;AAOA,SAAS,oBAAoB,OAAO,oBAA4C;CAK9E,IAAI,MAAM,IAAI,cAAc,YAAY,EAAE,MAAM,CAAC;CACjD,IAAgC,YAAY;CAC5C,IAAgC,mBAAmB;CACnD,OAAO;AACT;AAEA,IAAW,uBAAgF;AAE3F,IAAI,sBAA+B;AAKnC,SAAgB,gBAAgB,MAAkB;CAChD,IAAI,qBACF,MAAM,MACJ,mBACE,IAAA,QAAA,IAAA,aAAA,gBACW,qFACb,CACF;CAKF,kBAAA,SAAA,QAAA,SAAA,KAAA,IAAA,KAAA,IAAiB,KAAM,eAAe,gBAAgB,KAAI,KAAK,iBAAiB;CAEhF,sBAAsB;CAEtB,uBAAuB,OAAO,QAAQ;CAGtC,OAAO,iBAAiB,cAAc,UAAU;CAChD,OAAO,iBAAiB,YAAY,UAAU;CAG9C,MAAM,2BAA2B,OAAO;CACxC,MAAM,8BAA8B,OAAO;CAC3C,OAAO,mBAAmB,SAAU,WAAW,IAAI;EACjD,IAAI,OAAO,OAAO,YAChB;OACE,yBAAyB,QAAQ,SAAS,KAAK,KAC/C,CAAC,uBAAuB,UAAU,CAAC,MAAM,aAAa,aAAa,EAAE,GACrE;IACA,uBAAuB,UAAU,CAAC,KAAK,EAAE;IACzC;GACF;;EAGF,OAAO,yBAAyB,MAAM,MAAM,SAAS;CACvD;CAEA,OAAO,sBAAsB,SAAU,WAAW,YAAY;EAC5D,IAAI,OAAO,eAAe,YACxB;OAAI,yBAAyB,SAAS,SAAS,GAC7C,uBAAuB,aAAa,uBAAuB,UAAU,CAAC,QAAQ,OAAO,OAAO,UAAU;EACxG;EAGF,OAAO,4BAA4B,MAAM,MAAM,SAAS;CAC1D;CAEA,OAAO,QAAQ,YAAY,mBAAmB,OAAO,QAAQ,WAAW,WAAW;CACnF,OAAO,QAAQ,eAAe,mBAAmB,sBAAsB,cAAc;AACvF;AAMA,IAAI,aACF,IAAI,OAAO,mBACT,QAAQ,KACN,mBACE,IAAA,QAAA,IAAA,aAAA,gBACW,uFACb,CACF;KAKA,OAAO,oBAAoB"}
|