xpe 0.0.0-alpha.1 → 1.0.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.
Files changed (214) hide show
  1. package/README.md +627 -71
  2. package/dist/child/app-client.d.ts +44 -0
  3. package/dist/child/app-client.js +151 -0
  4. package/dist/child/index.d.ts +3 -0
  5. package/dist/child/index.js +3 -0
  6. package/dist/child/lifecycle.d.ts +12 -0
  7. package/dist/child/lifecycle.js +47 -0
  8. package/dist/child/mock-host.d.ts +8 -0
  9. package/dist/child/mock-host.js +41 -0
  10. package/dist/core/bridge.d.ts +28 -0
  11. package/dist/core/bridge.js +19 -0
  12. package/dist/core/events.d.ts +13 -0
  13. package/dist/core/events.js +56 -0
  14. package/dist/core/index.d.ts +3 -0
  15. package/dist/core/index.js +3 -0
  16. package/dist/core/types.d.ts +102 -0
  17. package/dist/core/types.js +20 -0
  18. package/dist/dev-shell/index.d.ts +26 -0
  19. package/dist/dev-shell/index.js +56 -0
  20. package/dist/host/app-path-router.d.ts +33 -0
  21. package/dist/host/app-path-router.js +183 -0
  22. package/dist/host/host-runtime.d.ts +29 -0
  23. package/dist/host/host-runtime.js +176 -0
  24. package/dist/host/index.d.ts +1 -0
  25. package/dist/host/index.js +1 -0
  26. package/dist/host/xpe-host.d.ts +41 -0
  27. package/dist/host/xpe-host.js +61 -0
  28. package/dist/index.d.ts +4 -0
  29. package/dist/index.js +4 -0
  30. package/dist/kernel/common.d.ts +62 -0
  31. package/dist/kernel/common.js +207 -0
  32. package/dist/kernel/constant.d.ts +26 -0
  33. package/dist/kernel/constant.js +42 -0
  34. package/dist/kernel/effect.d.ts +32 -0
  35. package/dist/kernel/effect.js +529 -0
  36. package/dist/kernel/entry.d.ts +43 -0
  37. package/dist/kernel/entry.js +224 -0
  38. package/dist/kernel/event.d.ts +22 -0
  39. package/dist/kernel/event.js +120 -0
  40. package/dist/kernel/iframe.d.ts +141 -0
  41. package/dist/kernel/iframe.js +1104 -0
  42. package/dist/kernel/index.d.ts +25 -0
  43. package/dist/kernel/index.js +86 -0
  44. package/dist/kernel/plugin.d.ts +36 -0
  45. package/dist/kernel/plugin.js +68 -0
  46. package/dist/kernel/proxy.d.ts +17 -0
  47. package/dist/kernel/proxy.js +440 -0
  48. package/dist/kernel/runtime-engine.d.ts +154 -0
  49. package/dist/kernel/runtime-engine.js +209 -0
  50. package/dist/kernel/sandbox.d.ts +235 -0
  51. package/dist/kernel/sandbox.js +879 -0
  52. package/dist/kernel/shadow.d.ts +64 -0
  53. package/dist/kernel/shadow.js +385 -0
  54. package/dist/kernel/sync.d.ts +21 -0
  55. package/dist/kernel/sync.js +185 -0
  56. package/dist/kernel/template.d.ts +67 -0
  57. package/dist/kernel/template.js +226 -0
  58. package/dist/kernel/tracker.d.ts +44 -0
  59. package/dist/kernel/tracker.js +92 -0
  60. package/dist/kernel/utils.d.ts +100 -0
  61. package/dist/kernel/utils.js +325 -0
  62. package/dist/kernel/xpe-bridge.d.ts +27 -0
  63. package/dist/kernel/xpe-bridge.js +205 -0
  64. package/dist/shared/index.d.ts +1 -0
  65. package/dist/shared/index.js +3 -0
  66. package/package.json +79 -57
  67. package/LICENSE +0 -21
  68. package/framework/es/core/Application.d.ts +0 -126
  69. package/framework/es/core/Command/Command.d.ts +0 -7
  70. package/framework/es/core/Container/Container.d.ts +0 -80
  71. package/framework/es/core/Contracts/AxiosAdapter.d.ts +0 -12
  72. package/framework/es/core/Helper/Helper.d.ts +0 -43
  73. package/framework/es/core/Helper/Storage/WebStorage.d.ts +0 -71
  74. package/framework/es/core/Libs/Exception.d.ts +0 -24
  75. package/framework/es/core/Libs/Lib.d.ts +0 -72
  76. package/framework/es/core/Provider/CommandProvider.d.ts +0 -4
  77. package/framework/es/core/Provider/HelperProvider.d.ts +0 -4
  78. package/framework/es/core/Provider/HttpProvider.d.ts +0 -13
  79. package/framework/es/core/Provider/ServiceProvider.d.ts +0 -15
  80. package/framework/es/core/Service/HttpService.d.ts +0 -133
  81. package/framework/es/core/Service/Service.d.ts +0 -6
  82. package/framework/es/core/Spanner/RESTful.d.ts +0 -30
  83. package/framework/es/core/Transformer/Transformer.d.ts +0 -46
  84. package/framework/es/core/Type/adapters.d.ts +0 -25
  85. package/framework/es/core/Type/types.d.ts +0 -161
  86. package/framework/es/core/TypeFunc/index.d.ts +0 -6
  87. package/framework/es/core/Wrenches/EventBus.d.ts +0 -56
  88. package/framework/es/core/Wrenches/is.d.ts +0 -19
  89. package/framework/es/ege.js +0 -4
  90. package/framework/es/ege.js.map +0 -1
  91. package/framework/es/index.d.ts +0 -13
  92. package/framework/es/pdd.js +0 -4
  93. package/framework/es/pdd.js.map +0 -1
  94. package/framework/es/src/core/Application.d.ts +0 -127
  95. package/framework/es/src/core/Application.d.ts.map +0 -1
  96. package/framework/es/src/core/Command/Command.d.ts +0 -8
  97. package/framework/es/src/core/Command/Command.d.ts.map +0 -1
  98. package/framework/es/src/core/Container/Container.d.ts +0 -81
  99. package/framework/es/src/core/Container/Container.d.ts.map +0 -1
  100. package/framework/es/src/core/Contracts/AxiosAdapter.d.ts +0 -13
  101. package/framework/es/src/core/Contracts/AxiosAdapter.d.ts.map +0 -1
  102. package/framework/es/src/core/Helper/Helper.d.ts +0 -45
  103. package/framework/es/src/core/Helper/Helper.d.ts.map +0 -1
  104. package/framework/es/src/core/Helper/Storage/WebStorage.d.ts +0 -72
  105. package/framework/es/src/core/Helper/Storage/WebStorage.d.ts.map +0 -1
  106. package/framework/es/src/core/Libs/Exception.d.ts +0 -25
  107. package/framework/es/src/core/Libs/Exception.d.ts.map +0 -1
  108. package/framework/es/src/core/Libs/Lib.d.ts +0 -73
  109. package/framework/es/src/core/Libs/Lib.d.ts.map +0 -1
  110. package/framework/es/src/core/Provider/CommandProvider.d.ts +0 -5
  111. package/framework/es/src/core/Provider/CommandProvider.d.ts.map +0 -1
  112. package/framework/es/src/core/Provider/HelperProvider.d.ts +0 -5
  113. package/framework/es/src/core/Provider/HelperProvider.d.ts.map +0 -1
  114. package/framework/es/src/core/Provider/HttpProvider.d.ts +0 -14
  115. package/framework/es/src/core/Provider/HttpProvider.d.ts.map +0 -1
  116. package/framework/es/src/core/Provider/ServiceProvider.d.ts +0 -16
  117. package/framework/es/src/core/Provider/ServiceProvider.d.ts.map +0 -1
  118. package/framework/es/src/core/Service/HttpService.d.ts +0 -128
  119. package/framework/es/src/core/Service/HttpService.d.ts.map +0 -1
  120. package/framework/es/src/core/Service/Service.d.ts +0 -7
  121. package/framework/es/src/core/Service/Service.d.ts.map +0 -1
  122. package/framework/es/src/core/Spanner/RESTful.d.ts +0 -32
  123. package/framework/es/src/core/Spanner/RESTful.d.ts.map +0 -1
  124. package/framework/es/src/core/Transformer/Transformer.d.ts +0 -47
  125. package/framework/es/src/core/Transformer/Transformer.d.ts.map +0 -1
  126. package/framework/es/src/core/Type/adapters.d.ts +0 -26
  127. package/framework/es/src/core/Type/adapters.d.ts.map +0 -1
  128. package/framework/es/src/core/Type/types.d.ts +0 -186
  129. package/framework/es/src/core/Type/types.d.ts.map +0 -1
  130. package/framework/es/src/core/TypeFunc/index.d.ts +0 -8
  131. package/framework/es/src/core/TypeFunc/index.d.ts.map +0 -1
  132. package/framework/es/src/core/Wrenches/EventBus.d.ts +0 -57
  133. package/framework/es/src/core/Wrenches/EventBus.d.ts.map +0 -1
  134. package/framework/es/src/core/Wrenches/is.d.ts +0 -20
  135. package/framework/es/src/core/Wrenches/is.d.ts.map +0 -1
  136. package/framework/es/src/index.d.ts +0 -14
  137. package/framework/es/src/index.d.ts.map +0 -1
  138. package/framework/es/src/utils.d.ts +0 -17
  139. package/framework/es/src/utils.d.ts.map +0 -1
  140. package/framework/es/utils.d.ts +0 -16
  141. package/framework/umd/core/Application.d.ts +0 -126
  142. package/framework/umd/core/Command/Command.d.ts +0 -7
  143. package/framework/umd/core/Container/Container.d.ts +0 -80
  144. package/framework/umd/core/Contracts/AxiosAdapter.d.ts +0 -12
  145. package/framework/umd/core/Helper/Helper.d.ts +0 -43
  146. package/framework/umd/core/Helper/Storage/WebStorage.d.ts +0 -71
  147. package/framework/umd/core/Libs/Exception.d.ts +0 -24
  148. package/framework/umd/core/Libs/Lib.d.ts +0 -72
  149. package/framework/umd/core/Provider/CommandProvider.d.ts +0 -4
  150. package/framework/umd/core/Provider/HelperProvider.d.ts +0 -4
  151. package/framework/umd/core/Provider/HttpProvider.d.ts +0 -13
  152. package/framework/umd/core/Provider/ServiceProvider.d.ts +0 -15
  153. package/framework/umd/core/Service/HttpService.d.ts +0 -133
  154. package/framework/umd/core/Service/Service.d.ts +0 -6
  155. package/framework/umd/core/Spanner/RESTful.d.ts +0 -30
  156. package/framework/umd/core/Transformer/Transformer.d.ts +0 -46
  157. package/framework/umd/core/Type/adapters.d.ts +0 -25
  158. package/framework/umd/core/Type/types.d.ts +0 -161
  159. package/framework/umd/core/TypeFunc/index.d.ts +0 -6
  160. package/framework/umd/core/Wrenches/EventBus.d.ts +0 -56
  161. package/framework/umd/core/Wrenches/is.d.ts +0 -19
  162. package/framework/umd/ege.js +0 -4
  163. package/framework/umd/ege.js.map +0 -1
  164. package/framework/umd/index.d.ts +0 -13
  165. package/framework/umd/pdd.js +0 -4
  166. package/framework/umd/pdd.js.map +0 -1
  167. package/framework/umd/src/core/Application.d.ts +0 -127
  168. package/framework/umd/src/core/Application.d.ts.map +0 -1
  169. package/framework/umd/src/core/Command/Command.d.ts +0 -8
  170. package/framework/umd/src/core/Command/Command.d.ts.map +0 -1
  171. package/framework/umd/src/core/Container/Container.d.ts +0 -81
  172. package/framework/umd/src/core/Container/Container.d.ts.map +0 -1
  173. package/framework/umd/src/core/Contracts/AxiosAdapter.d.ts +0 -13
  174. package/framework/umd/src/core/Contracts/AxiosAdapter.d.ts.map +0 -1
  175. package/framework/umd/src/core/Helper/Helper.d.ts +0 -45
  176. package/framework/umd/src/core/Helper/Helper.d.ts.map +0 -1
  177. package/framework/umd/src/core/Helper/Storage/WebStorage.d.ts +0 -72
  178. package/framework/umd/src/core/Helper/Storage/WebStorage.d.ts.map +0 -1
  179. package/framework/umd/src/core/Libs/Exception.d.ts +0 -25
  180. package/framework/umd/src/core/Libs/Exception.d.ts.map +0 -1
  181. package/framework/umd/src/core/Libs/Lib.d.ts +0 -73
  182. package/framework/umd/src/core/Libs/Lib.d.ts.map +0 -1
  183. package/framework/umd/src/core/Provider/CommandProvider.d.ts +0 -5
  184. package/framework/umd/src/core/Provider/CommandProvider.d.ts.map +0 -1
  185. package/framework/umd/src/core/Provider/HelperProvider.d.ts +0 -5
  186. package/framework/umd/src/core/Provider/HelperProvider.d.ts.map +0 -1
  187. package/framework/umd/src/core/Provider/HttpProvider.d.ts +0 -14
  188. package/framework/umd/src/core/Provider/HttpProvider.d.ts.map +0 -1
  189. package/framework/umd/src/core/Provider/ServiceProvider.d.ts +0 -16
  190. package/framework/umd/src/core/Provider/ServiceProvider.d.ts.map +0 -1
  191. package/framework/umd/src/core/Service/HttpService.d.ts +0 -128
  192. package/framework/umd/src/core/Service/HttpService.d.ts.map +0 -1
  193. package/framework/umd/src/core/Service/Service.d.ts +0 -7
  194. package/framework/umd/src/core/Service/Service.d.ts.map +0 -1
  195. package/framework/umd/src/core/Spanner/RESTful.d.ts +0 -32
  196. package/framework/umd/src/core/Spanner/RESTful.d.ts.map +0 -1
  197. package/framework/umd/src/core/Transformer/Transformer.d.ts +0 -47
  198. package/framework/umd/src/core/Transformer/Transformer.d.ts.map +0 -1
  199. package/framework/umd/src/core/Type/adapters.d.ts +0 -26
  200. package/framework/umd/src/core/Type/adapters.d.ts.map +0 -1
  201. package/framework/umd/src/core/Type/types.d.ts +0 -186
  202. package/framework/umd/src/core/Type/types.d.ts.map +0 -1
  203. package/framework/umd/src/core/TypeFunc/index.d.ts +0 -8
  204. package/framework/umd/src/core/TypeFunc/index.d.ts.map +0 -1
  205. package/framework/umd/src/core/Wrenches/EventBus.d.ts +0 -57
  206. package/framework/umd/src/core/Wrenches/EventBus.d.ts.map +0 -1
  207. package/framework/umd/src/core/Wrenches/is.d.ts +0 -20
  208. package/framework/umd/src/core/Wrenches/is.d.ts.map +0 -1
  209. package/framework/umd/src/index.d.ts +0 -14
  210. package/framework/umd/src/index.d.ts.map +0 -1
  211. package/framework/umd/src/utils.d.ts +0 -17
  212. package/framework/umd/src/utils.d.ts.map +0 -1
  213. package/framework/umd/utils.d.ts +0 -16
  214. package/index.d.ts +0 -724
@@ -0,0 +1,33 @@
1
+ import type { AppManifest, AppNavigationTarget, Unsubscribe } from "../core/index.js";
2
+ import type { RuntimeContainer } from "../kernel/index.js";
3
+ import type { HostRuntime } from "./host-runtime.js";
4
+ export type AppPathRouteMode = "push" | "replace";
5
+ export type AppPathRoute = {
6
+ manifest: AppManifest;
7
+ routePath: string;
8
+ };
9
+ export type AppPathRouterApp = {
10
+ manifest: AppManifest;
11
+ appPath?: string;
12
+ defaultPath?: string;
13
+ };
14
+ export type CreateAppPathRouterOptions = {
15
+ host: HostRuntime;
16
+ apps: AppPathRouterApp[];
17
+ container: RuntimeContainer;
18
+ getCurrentUrl?: () => URL;
19
+ writeUrl?: (url: URL, mode: AppPathRouteMode) => void;
20
+ onRouteChange?: (route: AppPathRoute) => void;
21
+ defaultAppCode?: string;
22
+ };
23
+ export type AppPathRouter = {
24
+ current(): AppPathRoute;
25
+ start(options?: {
26
+ replaceInvalidUrl?: boolean;
27
+ }): Promise<void>;
28
+ navigate(appCode: string, routePath?: string | AppNavigationTarget, mode?: AppPathRouteMode): Promise<void>;
29
+ reload(): Promise<void>;
30
+ handleBrowserNavigation(): Promise<void>;
31
+ attach(): Unsubscribe;
32
+ };
33
+ export declare function createAppPathRouter(options: CreateAppPathRouterOptions): AppPathRouter;
@@ -0,0 +1,183 @@
1
+ import { XpeRuntimeError } from "../core/index.js";
2
+ export function createAppPathRouter(options) {
3
+ if (!options.apps.length) {
4
+ throw new XpeRuntimeError("XPE_APP_NOT_REGISTERED", "XPE app path router 至少需要注册一个应用", {});
5
+ }
6
+ let activeAppCode = null;
7
+ let activeRouteKey = null;
8
+ let routeTask = Promise.resolve();
9
+ const getCurrentUrl = options.getCurrentUrl ?? (() => new URL(window.location.href));
10
+ const writeUrl = options.writeUrl ??
11
+ ((url, mode) => {
12
+ window.history[mode === "push" ? "pushState" : "replaceState"](null, "", url.href);
13
+ });
14
+ async function start(startOptions = {}) {
15
+ await enqueueRoute(async () => {
16
+ const route = current();
17
+ if (startOptions.replaceInvalidUrl && !findAppByPath(getCurrentUrl().pathname)) {
18
+ writeAppUrl(route.manifest, route.routePath, "replace");
19
+ }
20
+ await applyRoute(route);
21
+ });
22
+ }
23
+ async function navigate(appCode, routePath, mode = "push") {
24
+ const navigation = resolveNavigationTarget(appCode, routePath, mode);
25
+ const app = findAppByCode(navigation.appCode);
26
+ if (!app) {
27
+ throw new XpeRuntimeError("XPE_APP_NOT_REGISTERED", `XPE app path router 找不到应用:${navigation.appCode}`, {
28
+ appCode: navigation.appCode,
29
+ });
30
+ }
31
+ const normalizedRoute = normalizeRoutePath(navigation.path ?? getDefaultPath(app));
32
+ writeAppUrl(app.manifest, normalizedRoute, navigation.mode);
33
+ await enqueueRoute(() => applyRoute({ manifest: app.manifest, routePath: normalizedRoute }));
34
+ }
35
+ async function reload() {
36
+ await enqueueRoute(() => applyRoute(current(), { forceReload: true }));
37
+ }
38
+ async function handleBrowserNavigation() {
39
+ await enqueueRoute(() => applyRoute(current()));
40
+ }
41
+ async function applyRoute(route, applyOptions = {}) {
42
+ const nextRouteKey = toRouteKey(route);
43
+ if (!applyOptions.forceReload && activeRouteKey === nextRouteKey)
44
+ return;
45
+ const manifest = withRuntimeRoute(route.manifest, route.routePath, getCurrentUrl());
46
+ options.onRouteChange?.({ manifest, routePath: route.routePath });
47
+ if (!applyOptions.forceReload && activeAppCode === manifest.appCode) {
48
+ options.host.navigate(manifest.appCode, route.routePath);
49
+ activeRouteKey = nextRouteKey;
50
+ return;
51
+ }
52
+ if (applyOptions.forceReload && activeAppCode)
53
+ await options.host.destroy(activeAppCode);
54
+ await options.host.start({ manifest, container: options.container });
55
+ activeAppCode = manifest.appCode;
56
+ activeRouteKey = nextRouteKey;
57
+ }
58
+ function attach() {
59
+ const targetWindow = window;
60
+ const handleNavigation = () => {
61
+ void handleBrowserNavigation();
62
+ };
63
+ targetWindow.addEventListener("hashchange", handleNavigation);
64
+ targetWindow.addEventListener("popstate", handleNavigation);
65
+ return () => {
66
+ targetWindow.removeEventListener("hashchange", handleNavigation);
67
+ targetWindow.removeEventListener("popstate", handleNavigation);
68
+ };
69
+ }
70
+ function current() {
71
+ const url = getCurrentUrl();
72
+ const app = findAppByPath(url.pathname) ?? getDefaultApp();
73
+ return {
74
+ manifest: app.manifest,
75
+ routePath: normalizeRoutePath(url.hash.replace(/^#/, "") || getDefaultPath(app)),
76
+ };
77
+ }
78
+ function writeAppUrl(manifest, routePath, mode) {
79
+ const url = getCurrentUrl();
80
+ url.pathname = withTrailingSlash(getAppPath(manifest));
81
+ url.search = "";
82
+ url.hash = normalizeRoutePath(routePath);
83
+ if (url.href !== getCurrentUrl().href)
84
+ writeUrl(url, mode);
85
+ }
86
+ function findAppByPath(pathname) {
87
+ const normalizedPathname = normalizePathname(pathname);
88
+ return options.apps.find((app) => normalizePathname(getAppPath(app.manifest, app.appPath)) === normalizedPathname);
89
+ }
90
+ function findAppByCode(appCode) {
91
+ return options.apps.find((app) => app.manifest.appCode === appCode);
92
+ }
93
+ function getDefaultApp() {
94
+ return (options.defaultAppCode ? findAppByCode(options.defaultAppCode) : undefined) ?? options.apps[0];
95
+ }
96
+ return {
97
+ current,
98
+ start,
99
+ navigate,
100
+ reload,
101
+ handleBrowserNavigation,
102
+ attach,
103
+ };
104
+ function enqueueRoute(task) {
105
+ const nextTask = routeTask.then(task, task);
106
+ routeTask = nextTask.catch(() => undefined);
107
+ return nextTask;
108
+ }
109
+ function resolveNavigationTarget(appCode, routePath, mode) {
110
+ if (typeof routePath === "object" && routePath) {
111
+ return {
112
+ appCode: routePath.appCode ?? appCode,
113
+ path: formatRoutePath(routePath.path, routePath.query),
114
+ mode: routePath.replace ? "replace" : mode,
115
+ };
116
+ }
117
+ return {
118
+ appCode,
119
+ path: typeof routePath === "string" ? routePath : undefined,
120
+ mode,
121
+ };
122
+ }
123
+ }
124
+ function getAppPath(manifest, appPath) {
125
+ return appPath ?? manifest.basePath;
126
+ }
127
+ function getDefaultPath(app) {
128
+ return app.defaultPath ?? "/";
129
+ }
130
+ function normalizeRoutePath(path) {
131
+ return path.startsWith("/") ? path : `/${path}`;
132
+ }
133
+ function formatRoutePath(path, query) {
134
+ const normalizedPath = normalizeRoutePath(path);
135
+ const search = formatQuery(query);
136
+ if (!search)
137
+ return normalizedPath;
138
+ return normalizedPath.includes("?") ? `${normalizedPath}&${search.slice(1)}` : `${normalizedPath}${search}`;
139
+ }
140
+ function formatQuery(query) {
141
+ if (!query)
142
+ return "";
143
+ const params = new URLSearchParams();
144
+ Object.entries(query).forEach(([key, value]) => {
145
+ const values = Array.isArray(value) ? value : [value];
146
+ values.forEach((item) => {
147
+ if (item === null || item === undefined)
148
+ return;
149
+ params.append(key, String(item));
150
+ });
151
+ });
152
+ const queryString = params.toString();
153
+ return queryString ? `?${queryString}` : "";
154
+ }
155
+ function normalizePathname(pathname) {
156
+ return pathname.length > 1 ? pathname.replace(/\/$/, "") : pathname;
157
+ }
158
+ function withTrailingSlash(pathname) {
159
+ return pathname.endsWith("/") ? pathname : `${pathname}/`;
160
+ }
161
+ function toRouteKey(route) {
162
+ return `${route.manifest.appCode}:${normalizeRoutePath(route.routePath)}`;
163
+ }
164
+ function withRuntimeRoute(manifest, routePath, baseUrl) {
165
+ const runtimeUrl = new URL(manifest.runtime.url, baseUrl.href);
166
+ const normalizedRoute = normalizeRoutePath(routePath);
167
+ if ((manifest.runtime.routeMode ?? "hash") === "hash") {
168
+ runtimeUrl.hash = normalizedRoute;
169
+ }
170
+ else {
171
+ runtimeUrl.pathname = joinPath(manifest.runtime.basename ?? manifest.basePath, normalizedRoute);
172
+ }
173
+ return {
174
+ ...manifest,
175
+ runtime: {
176
+ ...manifest.runtime,
177
+ url: runtimeUrl.href,
178
+ },
179
+ };
180
+ }
181
+ function joinPath(basePath, routePath) {
182
+ return `${basePath.replace(/\/$/, "")}/${routePath.replace(/^\//, "")}`;
183
+ }
@@ -0,0 +1,29 @@
1
+ import { type AppBridge, type AppContext, type AppEventHandler, type HostNavigationTarget, type AppNavigationTarget, type AppManifest, type Unsubscribe } from "../core/index.js";
2
+ import { type RuntimeContainer, type RuntimeKernel } from "../kernel/index.js";
3
+ export type HostRuntimeOptions = {
4
+ getEntryContext: (appCode: string) => AppContext | Promise<AppContext>;
5
+ runtimeKernel?: RuntimeKernel;
6
+ onUnauthorized?: (context: AppContext) => void;
7
+ onRouteChange?: (event: {
8
+ appCode: string;
9
+ target: string | AppNavigationTarget;
10
+ }) => void;
11
+ onHostNavigate?: (target: string | HostNavigationTarget) => void;
12
+ onError?: (error: unknown) => void;
13
+ };
14
+ export type StartAppOptions = {
15
+ manifest: AppManifest;
16
+ container: RuntimeContainer;
17
+ };
18
+ export type HostRuntime = {
19
+ register(manifest: AppManifest): void;
20
+ getManifest(appCode: string): AppManifest | undefined;
21
+ preload(manifest: AppManifest): void;
22
+ start(options: StartAppOptions): Promise<AppBridge>;
23
+ navigate(appCode: string, path: string): void;
24
+ emit<TPayload = unknown>(appCode: string, eventName: string, payload: TPayload): void;
25
+ on<TPayload = unknown>(appCode: string, eventName: string, handler: AppEventHandler<TPayload>): Unsubscribe;
26
+ off<TPayload = unknown>(appCode: string, eventName: string, handler: AppEventHandler<TPayload>): void;
27
+ destroy(appCode: string): Promise<void>;
28
+ };
29
+ export declare function createHostRuntime(options: HostRuntimeOptions): HostRuntime;
@@ -0,0 +1,176 @@
1
+ import { createEventHub, XPE_ROUTE_CHANGE_EVENT, XpeRuntimeError, } from "../core/index.js";
2
+ import { createRuntimeKernel } from "../kernel/index.js";
3
+ export function createHostRuntime(options) {
4
+ const manifests = new Map();
5
+ const bridges = new Map();
6
+ const appEvents = new Map();
7
+ const runtimeKernel = options.runtimeKernel ?? createRuntimeKernel();
8
+ function getAppEvents(appCode) {
9
+ let eventHub = appEvents.get(appCode);
10
+ if (!eventHub) {
11
+ eventHub = createEventHub();
12
+ appEvents.set(appCode, eventHub);
13
+ }
14
+ return eventHub;
15
+ }
16
+ return {
17
+ register(manifest) {
18
+ manifests.set(manifest.appCode, normalizeManifest(manifest));
19
+ },
20
+ getManifest(appCode) {
21
+ return manifests.get(appCode);
22
+ },
23
+ preload(manifest) {
24
+ const normalizedManifest = normalizeManifest(manifest);
25
+ manifests.set(normalizedManifest.appCode, normalizedManifest);
26
+ runtimeKernel.preload({ manifest: normalizedManifest });
27
+ },
28
+ async start(startOptions) {
29
+ const manifest = normalizeManifest(startOptions.manifest);
30
+ manifests.set(manifest.appCode, manifest);
31
+ try {
32
+ const context = await options.getEntryContext(manifest.appCode);
33
+ // 未授权是一条独立的业务分支,只走 onUnauthorized,不再经 onError,
34
+ // 避免「一次未授权同时触发 onUnauthorized + onError」的重复派发。
35
+ // 仍然 reject,让 await start() 的调用方能感知进入被拒绝。
36
+ if (context.accessStatus !== "enterable") {
37
+ options.onUnauthorized?.(context);
38
+ throw new XpeRuntimeError("XPE_APP_NOT_ENTERABLE", "XPE 应用当前不可进入", {
39
+ appCode: manifest.appCode,
40
+ accessStatus: context.accessStatus,
41
+ reason: context.reason,
42
+ });
43
+ }
44
+ const bridge = createHostBridge({
45
+ manifest,
46
+ context,
47
+ appEvents: getAppEvents(manifest.appCode),
48
+ onRouteChange: options.onRouteChange,
49
+ onHostNavigate: options.onHostNavigate,
50
+ });
51
+ bridges.set(manifest.appCode, bridge);
52
+ await runtimeKernel.start({
53
+ manifest,
54
+ context,
55
+ container: startOptions.container,
56
+ bridge,
57
+ });
58
+ return bridge;
59
+ }
60
+ catch (error) {
61
+ // 未授权已由 onUnauthorized 派发,不再重复走 onError;其余错误(getEntryContext
62
+ // 失败、kernel 启动失败等)才交给 onError。
63
+ if (!(error instanceof XpeRuntimeError && error.code === "XPE_APP_NOT_ENTERABLE")) {
64
+ options.onError?.(error);
65
+ }
66
+ throw error;
67
+ }
68
+ },
69
+ navigate(appCode, path) {
70
+ const bridge = bridges.get(appCode);
71
+ bridge?.syncRoute?.(path);
72
+ },
73
+ emit(appCode, eventName, payload) {
74
+ getAppEvents(appCode).emit(eventName, payload);
75
+ },
76
+ on(appCode, eventName, handler) {
77
+ return getAppEvents(appCode).on(eventName, handler);
78
+ },
79
+ off(appCode, eventName, handler) {
80
+ getAppEvents(appCode).off(eventName, handler);
81
+ },
82
+ async destroy(appCode) {
83
+ const manifest = manifests.get(appCode);
84
+ if (manifest) {
85
+ await runtimeKernel.destroy({
86
+ appCode,
87
+ runtime: normalizeRuntimeConfig(manifest.appCode, manifest.basePath, manifest.runtime),
88
+ });
89
+ }
90
+ bridges.delete(appCode);
91
+ // 清理 per-app 事件 hub,否则反复 register/start/destroy 会累积 hub 及其上注册的
92
+ // host.on 处理器,活到整个 runtime 生命周期结束,形成真实泄漏。
93
+ const eventHub = appEvents.get(appCode);
94
+ if (eventHub) {
95
+ eventHub.clear();
96
+ appEvents.delete(appCode);
97
+ }
98
+ },
99
+ };
100
+ }
101
+ function createHostBridge(options) {
102
+ let currentContext = options.context;
103
+ const contextEvents = createEventHub();
104
+ const runtime = {
105
+ poweredByXpe: true,
106
+ appCode: options.manifest.appCode,
107
+ name: getRuntimeName(options.manifest.appCode, options.manifest.runtime),
108
+ basename: getRuntimeBasename(options.manifest.basePath, options.manifest.runtime),
109
+ routeMode: options.manifest.runtime.routeMode ?? "hash",
110
+ };
111
+ const bridge = {
112
+ runtime,
113
+ get context() {
114
+ return currentContext;
115
+ },
116
+ getContext() {
117
+ return currentContext;
118
+ },
119
+ setContext(nextContext) {
120
+ currentContext = nextContext;
121
+ contextEvents.emit("context-change", nextContext);
122
+ },
123
+ onContextChange(handler) {
124
+ return contextEvents.on("context-change", handler);
125
+ },
126
+ emit(eventName, payload) {
127
+ options.appEvents.emit(eventName, payload);
128
+ },
129
+ on(eventName, handler) {
130
+ return options.appEvents.on(eventName, handler);
131
+ },
132
+ off(eventName, handler) {
133
+ options.appEvents.off(eventName, handler);
134
+ },
135
+ navigate(target) {
136
+ options.onRouteChange?.({ appCode: options.manifest.appCode, target });
137
+ },
138
+ navigateHost(target) {
139
+ options.onHostNavigate?.(target);
140
+ },
141
+ reportRouteChange(path) {
142
+ options.onRouteChange?.({ appCode: options.manifest.appCode, target: path });
143
+ },
144
+ syncRoute(path) {
145
+ options.appEvents.emit(XPE_ROUTE_CHANGE_EVENT, path);
146
+ },
147
+ };
148
+ return bridge;
149
+ }
150
+ function normalizeManifest(manifest) {
151
+ return {
152
+ ...manifest,
153
+ entryPath: manifest.entryPath ?? toEntryPath(manifest.basePath),
154
+ runtimeMode: manifest.runtimeMode ?? "xpe",
155
+ runtime: normalizeRuntimeConfig(manifest.appCode, manifest.basePath, manifest.runtime),
156
+ menus: manifest.menus ?? [],
157
+ permissions: manifest.permissions ?? [],
158
+ };
159
+ }
160
+ function normalizeRuntimeConfig(appCode, basePath, runtime) {
161
+ return {
162
+ ...runtime,
163
+ mode: runtime.mode ?? "xpe",
164
+ name: getRuntimeName(appCode, runtime),
165
+ basename: getRuntimeBasename(basePath, runtime),
166
+ };
167
+ }
168
+ function getRuntimeName(appCode, runtime) {
169
+ return runtime.name ?? appCode;
170
+ }
171
+ function getRuntimeBasename(basePath, runtime) {
172
+ return runtime.basename ?? basePath;
173
+ }
174
+ function toEntryPath(basePath) {
175
+ return `${basePath.replace(/\/$/, "")}/#/`;
176
+ }
@@ -0,0 +1 @@
1
+ export * from "./xpe-host.js";
@@ -0,0 +1 @@
1
+ export * from "./xpe-host.js";
@@ -0,0 +1,41 @@
1
+ import type { AppContext, AppEventHandler, AppManifest, AppNavigationTarget, HostNavigationTarget, Unsubscribe } from "../core/index.js";
2
+ import type { RuntimeContainer, RuntimeKernel } from "../kernel/index.js";
3
+ import { type AppPathRoute, type AppPathRouter, type AppPathRouterApp, type AppPathRouteMode } from "./app-path-router.js";
4
+ import { type HostRuntime } from "./host-runtime.js";
5
+ export type HostOptions = {
6
+ container: RuntimeContainer;
7
+ apps: AppPathRouterApp[];
8
+ getEntryContext: (appCode: string) => AppContext | Promise<AppContext>;
9
+ defaultAppCode?: string;
10
+ runtimeKernel?: RuntimeKernel;
11
+ onUnauthorized?: (context: AppContext) => void;
12
+ onRouteChange?: (route: AppPathRoute) => void;
13
+ onNavigate?: (event: {
14
+ appCode: string;
15
+ target: string | AppNavigationTarget;
16
+ }) => void;
17
+ onHostNavigate?: (target: string | HostNavigationTarget) => void;
18
+ getCurrentUrl?: () => URL;
19
+ writeUrl?: (url: URL, mode: AppPathRouteMode) => void;
20
+ autoAttach?: boolean;
21
+ onError?: (error: unknown) => void;
22
+ };
23
+ export type Host = {
24
+ runtime: HostRuntime;
25
+ router: AppPathRouter;
26
+ start(options?: {
27
+ replaceInvalidUrl?: boolean;
28
+ }): Promise<void>;
29
+ navigate(appCode: string, routePath?: string | AppNavigationTarget): Promise<void>;
30
+ emit<TPayload = unknown>(appCode: string, eventName: string, payload: TPayload): void;
31
+ on<TPayload = unknown>(appCode: string, eventName: string, handler: AppEventHandler<TPayload>): Unsubscribe;
32
+ off<TPayload = unknown>(appCode: string, eventName: string, handler: AppEventHandler<TPayload>): void;
33
+ reload(): Promise<void>;
34
+ preload(manifest: AppManifest): void;
35
+ destroy(appCode: string): Promise<void>;
36
+ dispose(): void;
37
+ };
38
+ export type XpeHostOptions = HostOptions;
39
+ export type XpeHost = Host;
40
+ export declare function createHost(options: HostOptions): Host;
41
+ export declare const createXpeHost: typeof createHost;
@@ -0,0 +1,61 @@
1
+ import { createAppPathRouter, } from "./app-path-router.js";
2
+ import { createHostRuntime } from "./host-runtime.js";
3
+ export function createHost(options) {
4
+ let detachRouter;
5
+ const runtime = createHostRuntime({
6
+ getEntryContext: options.getEntryContext,
7
+ runtimeKernel: options.runtimeKernel,
8
+ onUnauthorized: options.onUnauthorized,
9
+ onError: options.onError,
10
+ onHostNavigate: options.onHostNavigate,
11
+ onRouteChange(event) {
12
+ options.onNavigate?.(event);
13
+ void router.navigate(event.appCode, event.target);
14
+ },
15
+ });
16
+ const router = createAppPathRouter({
17
+ host: runtime,
18
+ container: options.container,
19
+ apps: options.apps,
20
+ defaultAppCode: options.defaultAppCode,
21
+ onRouteChange: options.onRouteChange,
22
+ getCurrentUrl: options.getCurrentUrl,
23
+ writeUrl: options.writeUrl,
24
+ });
25
+ return {
26
+ runtime,
27
+ router,
28
+ async start(startOptions = { replaceInvalidUrl: true }) {
29
+ if (options.autoAttach !== false) {
30
+ detachRouter ?? (detachRouter = router.attach());
31
+ }
32
+ await router.start(startOptions);
33
+ },
34
+ navigate(appCode, routePath) {
35
+ return router.navigate(appCode, routePath);
36
+ },
37
+ emit(appCode, eventName, payload) {
38
+ runtime.emit(appCode, eventName, payload);
39
+ },
40
+ on(appCode, eventName, handler) {
41
+ return runtime.on(appCode, eventName, handler);
42
+ },
43
+ off(appCode, eventName, handler) {
44
+ runtime.off(appCode, eventName, handler);
45
+ },
46
+ reload() {
47
+ return router.reload();
48
+ },
49
+ preload(manifest) {
50
+ runtime.preload(manifest);
51
+ },
52
+ destroy(appCode) {
53
+ return runtime.destroy(appCode);
54
+ },
55
+ dispose() {
56
+ detachRouter?.();
57
+ detachRouter = undefined;
58
+ },
59
+ };
60
+ }
61
+ export const createXpeHost = createHost;
@@ -0,0 +1,4 @@
1
+ export * from "./core/index.js";
2
+ export * from "./host/index.js";
3
+ export * from "./child/index.js";
4
+ export * from "./dev-shell/index.js";
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./core/index.js";
2
+ export * from "./host/index.js";
3
+ export * from "./child/index.js";
4
+ export * from "./dev-shell/index.js";
@@ -0,0 +1,62 @@
1
+ import RuntimeSandbox from "./sandbox.js";
2
+ import { cacheOptions } from "./runtime-engine.js";
3
+ export interface SandboxCache {
4
+ sandbox?: RuntimeSandbox;
5
+ options?: cacheOptions;
6
+ }
7
+ export type appAddEventListenerOptions = AddEventListenerOptions & {
8
+ targetWindow?: Window;
9
+ };
10
+ export declare const idToSandboxCacheMap: Map<String, SandboxCache>;
11
+ export declare function getSandboxById(id: String): RuntimeSandbox | null;
12
+ export declare function getOptionsById(id: String): cacheOptions | null;
13
+ export declare function addSandboxCacheWithSandbox(id: string, sandbox: RuntimeSandbox): void;
14
+ export declare function deleteSandboxById(id: string): void;
15
+ export declare function addSandboxCacheWithOptions(id: string, options: cacheOptions): void;
16
+ export declare const documentProxyProperties: {
17
+ modifyLocalProperties: string[];
18
+ modifyProperties: string[];
19
+ shadowProperties: string[];
20
+ shadowMethods: string[];
21
+ documentProperties: string[];
22
+ documentMethods: string[];
23
+ documentEvents: string[];
24
+ ownerProperties: string[];
25
+ };
26
+ export declare const appDocumentAddEventListenerEvents: string[];
27
+ export declare const appDocumentOnEvents: string[];
28
+ export declare const mainDocumentAddEventListenerEvents: string[];
29
+ export declare const mainAndAppAddEventListenerEvents: string[];
30
+ export declare const appWindowAddEventListenerEvents: string[];
31
+ export declare const appWindowOnEvent: string[];
32
+ export declare const relativeElementTagAttrMap: {
33
+ IMG: string;
34
+ A: string;
35
+ SOURCE: string;
36
+ };
37
+ export declare const windowProxyProperties: string[];
38
+ export declare const windowRegWhiteList: RegExp[];
39
+ export declare const rawElementAppendChild: <T extends Node>(node: T) => T;
40
+ export declare const rawElementRemoveChild: <T extends Node>(child: T) => T;
41
+ export declare const rawElementContains: (other: Node | null) => boolean;
42
+ export declare const rawHeadInsertBefore: <T extends Node>(node: T, child: Node | null) => T;
43
+ export declare const rawBodyInsertBefore: <T extends Node>(node: T, child: Node | null) => T;
44
+ export declare const rawInsertAdjacentElement: (where: InsertPosition, element: Element) => Element | null;
45
+ export declare const rawAddEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: AddEventListenerOptions | boolean) => void;
46
+ export declare const rawRemoveEventListener: (type: string, callback: EventListenerOrEventListenerObject | null, options?: EventListenerOptions | boolean) => void;
47
+ export declare const rawWindowAddEventListener: {
48
+ <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
49
+ (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
50
+ } & typeof addEventListener;
51
+ export declare const rawWindowRemoveEventListener: {
52
+ <K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
53
+ (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
54
+ } & typeof removeEventListener;
55
+ export declare const rawAppendChild: <T extends Node>(node: T) => T;
56
+ export declare const rawDocumentQuerySelector: {
57
+ <K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
58
+ <K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
59
+ <K extends keyof MathMLElementTagNameMap>(selectors: K): MathMLElementTagNameMap[K] | null;
60
+ <K extends keyof HTMLElementDeprecatedTagNameMap>(selectors: K): HTMLElementDeprecatedTagNameMap[K] | null;
61
+ <E extends Element = Element>(selectors: string): E | null;
62
+ };