@zero-bits/kernel 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.
- package/README.md +119 -0
- package/dist/chunk-D4E5XKWD.js +482 -0
- package/dist/chunk-ETCJDJTI.cjs +482 -0
- package/dist/core/index.cjs +28 -0
- package/dist/core/index.d.cts +58 -0
- package/dist/core/index.d.ts +58 -0
- package/dist/core/index.js +28 -0
- package/dist/react/index.cjs +147 -0
- package/dist/react/index.d.cts +42 -0
- package/dist/react/index.d.ts +42 -0
- package/dist/react/index.js +147 -0
- package/dist/types-JlxTjSfC.d.cts +120 -0
- package/dist/types-JlxTjSfC.d.ts +120 -0
- package/package.json +38 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/core/types.ts
|
|
2
|
+
var PluginError = class extends Error {
|
|
3
|
+
constructor(pluginName, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "PluginError";
|
|
6
|
+
this.pluginName = pluginName;
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
var PluginNetworkError = class extends PluginError {
|
|
10
|
+
constructor(pluginName, url, cause) {
|
|
11
|
+
super(pluginName, `[Kernel] \u63D2\u4EF6 [${pluginName}] \u7F51\u7EDC\u52A0\u8F7D\u5931\u8D25\uFF0CURL: ${url}`);
|
|
12
|
+
this.name = "PluginNetworkError";
|
|
13
|
+
if (cause) this.cause = cause;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
var PluginTimeoutError = class extends PluginError {
|
|
17
|
+
constructor(pluginName, timeout) {
|
|
18
|
+
super(pluginName, `[Kernel] \u63D2\u4EF6 [${pluginName}] \u52A0\u8F7D\u8D85\u65F6\uFF08>${timeout}ms\uFF09`);
|
|
19
|
+
this.name = "PluginTimeoutError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
var PluginDependencyError = class extends PluginError {
|
|
23
|
+
constructor(pluginName, dependency) {
|
|
24
|
+
super(pluginName, `[Kernel] \u63D2\u4EF6 [${pluginName}] \u7F3A\u5C11\u4F9D\u8D56: [${dependency}]\uFF0C\u8BF7\u786E\u4FDD\u5DF2\u8C03\u7528 regSharedModule \u6CE8\u5165`);
|
|
25
|
+
this.name = "PluginDependencyError";
|
|
26
|
+
this.dependency = dependency;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var PluginExecutionError = class extends PluginError {
|
|
30
|
+
constructor(pluginName, cause) {
|
|
31
|
+
super(pluginName, `[Kernel] \u63D2\u4EF6 [${pluginName}] \u6267\u884C\u521D\u59CB\u5316\u5931\u8D25`);
|
|
32
|
+
this.name = "PluginExecutionError";
|
|
33
|
+
if (cause) this.cause = cause;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var KernelNotInitializedError = class extends Error {
|
|
37
|
+
constructor() {
|
|
38
|
+
super("[Kernel] \u5185\u6838\u5F15\u64CE\u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 initKernel() \u6216 createKernel()");
|
|
39
|
+
this.name = "KernelNotInitializedError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// src/core/core.ts
|
|
44
|
+
function toPluginError(pluginName, err) {
|
|
45
|
+
if (err instanceof PluginError) return err;
|
|
46
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
47
|
+
return new PluginError(pluginName, message);
|
|
48
|
+
}
|
|
49
|
+
function withTimeout(promise, ms, error) {
|
|
50
|
+
let timer;
|
|
51
|
+
const timeout = new Promise((_, reject) => {
|
|
52
|
+
timer = setTimeout(() => reject(error), ms);
|
|
53
|
+
});
|
|
54
|
+
promise.catch(() => {
|
|
55
|
+
});
|
|
56
|
+
return Promise.race([promise, timeout]).finally(() => clearTimeout(timer));
|
|
57
|
+
}
|
|
58
|
+
function createDeferred() {
|
|
59
|
+
let resolve;
|
|
60
|
+
let reject;
|
|
61
|
+
const promise = new Promise((res, rej) => {
|
|
62
|
+
resolve = res;
|
|
63
|
+
reject = rej;
|
|
64
|
+
});
|
|
65
|
+
return { promise, resolve, reject };
|
|
66
|
+
}
|
|
67
|
+
var Kernel = class {
|
|
68
|
+
/**
|
|
69
|
+
* 构造函数
|
|
70
|
+
* @param options 内核配置
|
|
71
|
+
* @default timeout: 10000
|
|
72
|
+
* @default retryCount: 2
|
|
73
|
+
* @default nonce: ''
|
|
74
|
+
* @default debug: true
|
|
75
|
+
* @default namespace: ''
|
|
76
|
+
* @default logger: console
|
|
77
|
+
* @default onLoadStart: () => {}
|
|
78
|
+
* @default onLoadSuccess: () => {}
|
|
79
|
+
* @default onLoadError: () => {}
|
|
80
|
+
*/
|
|
81
|
+
constructor(options) {
|
|
82
|
+
this.modules = /* @__PURE__ */ new Map();
|
|
83
|
+
this.ownHandlers = /* @__PURE__ */ new Map();
|
|
84
|
+
this.initialized = false;
|
|
85
|
+
if (!_optionalChain([options, 'optionalAccess', _2 => _2.namespace])) {
|
|
86
|
+
throw new Error("[SmartHub] \u5FC5\u987B\u914D\u7F6E namespace \u5168\u79F0 (\u4F8B\u5982: __SMART_HUB___DEFINE)");
|
|
87
|
+
}
|
|
88
|
+
this.logger = _optionalChain([options, 'optionalAccess', _3 => _3.logger]) || console;
|
|
89
|
+
this.config = {
|
|
90
|
+
timeout: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _4 => _4.timeout]), () => ( 1e4)),
|
|
91
|
+
retryCount: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _5 => _5.retryCount]), () => ( 2)),
|
|
92
|
+
nonce: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _6 => _6.nonce]), () => ( "")),
|
|
93
|
+
debug: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.debug]), () => ( true)),
|
|
94
|
+
namespace: options.namespace,
|
|
95
|
+
logger: this.logger,
|
|
96
|
+
onLoadStart: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.onLoadStart]), () => ( (() => {
|
|
97
|
+
}))),
|
|
98
|
+
onLoadSuccess: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _9 => _9.onLoadSuccess]), () => ( (() => {
|
|
99
|
+
}))),
|
|
100
|
+
onLoadError: _nullishCoalesce(_optionalChain([options, 'optionalAccess', _10 => _10.onLoadError]), () => ( (() => {
|
|
101
|
+
})))
|
|
102
|
+
};
|
|
103
|
+
this.initGlobalInterceptor();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* 获取全局Pending Map
|
|
107
|
+
* @returns 全局Pending Map
|
|
108
|
+
*/
|
|
109
|
+
get globalPendingMap() {
|
|
110
|
+
if (typeof window === "undefined") return void 0;
|
|
111
|
+
const defineFn = window[this.config.namespace];
|
|
112
|
+
return defineFn ? defineFn._pendingMap : void 0;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 获取全局资源并发锁
|
|
116
|
+
*/
|
|
117
|
+
get globalLocks() {
|
|
118
|
+
if (typeof window === "undefined") return /* @__PURE__ */ new Map();
|
|
119
|
+
const nsLocks = `${this.config.namespace}_LOCKS`;
|
|
120
|
+
if (!window[nsLocks]) {
|
|
121
|
+
window[nsLocks] = /* @__PURE__ */ new Map();
|
|
122
|
+
}
|
|
123
|
+
return window[nsLocks];
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* 初始化全局拦截器
|
|
127
|
+
*/
|
|
128
|
+
initGlobalInterceptor() {
|
|
129
|
+
if (typeof window === "undefined") return;
|
|
130
|
+
const ns = this.config.namespace;
|
|
131
|
+
if (!window[ns]) {
|
|
132
|
+
const defineFn = (pluginName, deps, factory) => {
|
|
133
|
+
const handlers = _optionalChain([defineFn, 'access', _11 => _11._pendingMap, 'optionalAccess', _12 => _12.get, 'call', _13 => _13(pluginName)]);
|
|
134
|
+
if (handlers && handlers.size > 0) {
|
|
135
|
+
handlers.forEach((handler) => handler(deps, factory));
|
|
136
|
+
handlers.clear();
|
|
137
|
+
} else {
|
|
138
|
+
console.warn(`[SmartHub] \u6536\u5230\u672A\u77E5\u7684\u63D2\u4EF6 [${pluginName}] define \u8C03\u7528`);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
defineFn._pendingMap = /* @__PURE__ */ new Map();
|
|
142
|
+
window[ns] = defineFn;
|
|
143
|
+
}
|
|
144
|
+
this.initialized = true;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* 判断内核是否已初始化
|
|
148
|
+
* @returns true 如果内核已初始化,否则 false
|
|
149
|
+
*/
|
|
150
|
+
isInitialized() {
|
|
151
|
+
return this.initialized;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* 注册共享模块
|
|
155
|
+
* @param name 模块名称
|
|
156
|
+
* @param instance 模块实例
|
|
157
|
+
* @param options 模块配置
|
|
158
|
+
* @default force: false
|
|
159
|
+
*/
|
|
160
|
+
regSharedModule(name, instance, options) {
|
|
161
|
+
if (this.modules.has(name) && !_optionalChain([options, 'optionalAccess', _14 => _14.force])) {
|
|
162
|
+
if (this.config.debug) {
|
|
163
|
+
this.logger.warn(`[SmartHub] \u5171\u4EAB\u6A21\u5757 [${name}] \u5DF2\u6CE8\u518C\uFF0C\u5982\u9700\u8986\u76D6\u8BF7\u4F20\u5165 { force: true }`);
|
|
164
|
+
}
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
this.modules.set(name, {
|
|
168
|
+
module: instance,
|
|
169
|
+
_promise: Promise.resolve(instance),
|
|
170
|
+
status: "resolved"
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* 注入脚本(带自毁机制与并发锁)
|
|
175
|
+
* @param url 脚本地址
|
|
176
|
+
* @param pluginName 插件名称
|
|
177
|
+
* @returns Promise对象
|
|
178
|
+
*/
|
|
179
|
+
injectScript(url, pluginName) {
|
|
180
|
+
const locks = this.globalLocks;
|
|
181
|
+
if (locks.has(url)) return locks.get(url);
|
|
182
|
+
const promise = new Promise((resolve, reject) => {
|
|
183
|
+
const script = document.createElement("script");
|
|
184
|
+
script.src = url;
|
|
185
|
+
script.async = true;
|
|
186
|
+
if (this.config.nonce) script.nonce = this.config.nonce;
|
|
187
|
+
const cleanup = () => {
|
|
188
|
+
script.onload = null;
|
|
189
|
+
script.onerror = null;
|
|
190
|
+
locks.delete(url);
|
|
191
|
+
if (script.parentNode) script.parentNode.removeChild(script);
|
|
192
|
+
};
|
|
193
|
+
script.onload = () => {
|
|
194
|
+
cleanup();
|
|
195
|
+
resolve();
|
|
196
|
+
};
|
|
197
|
+
script.onerror = (event) => {
|
|
198
|
+
cleanup();
|
|
199
|
+
reject(new PluginNetworkError(pluginName, url, event));
|
|
200
|
+
};
|
|
201
|
+
document.head.appendChild(script);
|
|
202
|
+
});
|
|
203
|
+
locks.set(url, promise);
|
|
204
|
+
return promise;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 注入样式(带并发锁,防止 FOUC)
|
|
208
|
+
* @param url 样式地址
|
|
209
|
+
* @param pluginName 插件名称
|
|
210
|
+
* @returns Promise对象
|
|
211
|
+
*/
|
|
212
|
+
injectStyle(url, pluginName) {
|
|
213
|
+
const locks = this.globalLocks;
|
|
214
|
+
if (locks.has(url)) return locks.get(url);
|
|
215
|
+
const existing = document.querySelector(`link[href="${url}"][rel="stylesheet"]`);
|
|
216
|
+
if (existing) return Promise.resolve();
|
|
217
|
+
const promise = new Promise((resolve, reject) => {
|
|
218
|
+
const link = document.createElement("link");
|
|
219
|
+
link.rel = "stylesheet";
|
|
220
|
+
link.href = url;
|
|
221
|
+
if (this.config.nonce) link.nonce = this.config.nonce;
|
|
222
|
+
const cleanup = () => {
|
|
223
|
+
link.onload = null;
|
|
224
|
+
link.onerror = null;
|
|
225
|
+
locks.delete(url);
|
|
226
|
+
};
|
|
227
|
+
link.onload = () => {
|
|
228
|
+
cleanup();
|
|
229
|
+
resolve();
|
|
230
|
+
};
|
|
231
|
+
link.onerror = (event) => {
|
|
232
|
+
cleanup();
|
|
233
|
+
if (link.parentNode) link.parentNode.removeChild(link);
|
|
234
|
+
reject(new PluginNetworkError(pluginName, url, event));
|
|
235
|
+
};
|
|
236
|
+
document.head.appendChild(link);
|
|
237
|
+
});
|
|
238
|
+
locks.set(url, promise);
|
|
239
|
+
return promise;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* 带重试的函数执行器
|
|
243
|
+
* @param fn 需要执行的函数
|
|
244
|
+
* @param pluginName 插件名称
|
|
245
|
+
* @returns Promise对象
|
|
246
|
+
*/
|
|
247
|
+
async withRetry(fn, pluginName) {
|
|
248
|
+
let lastError;
|
|
249
|
+
for (let attempt = 0; attempt <= this.config.retryCount; attempt++) {
|
|
250
|
+
try {
|
|
251
|
+
return await fn();
|
|
252
|
+
} catch (err) {
|
|
253
|
+
lastError = err;
|
|
254
|
+
if (attempt < this.config.retryCount) {
|
|
255
|
+
await new Promise((r) => setTimeout(r, 100 * Math.pow(2, attempt)));
|
|
256
|
+
if (this.config.debug) {
|
|
257
|
+
this.logger.warn(`[SmartHub] \u63D2\u4EF6 [${pluginName}] \u7B2C ${attempt + 1} \u6B21\u91CD\u8BD5\u52A0\u8F7D...`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
throw lastError;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 解析工厂函数(支持异步依赖树)
|
|
266
|
+
* @param pluginName 插件名称
|
|
267
|
+
* @param deps 依赖项
|
|
268
|
+
* @param factory 工厂函数
|
|
269
|
+
* @returns Promise对象
|
|
270
|
+
*/
|
|
271
|
+
async resolveFactory(pluginName, deps, factory) {
|
|
272
|
+
let resolvedDeps;
|
|
273
|
+
try {
|
|
274
|
+
resolvedDeps = await Promise.all(deps.map((dep) => {
|
|
275
|
+
const entry = this.modules.get(dep);
|
|
276
|
+
if (!entry) throw new PluginDependencyError(pluginName, dep);
|
|
277
|
+
return entry._promise;
|
|
278
|
+
}));
|
|
279
|
+
} catch (err) {
|
|
280
|
+
throw err;
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
return factory(...resolvedDeps);
|
|
284
|
+
} catch (err) {
|
|
285
|
+
throw new PluginExecutionError(pluginName, err);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* 注册待处理函数
|
|
290
|
+
* @param pluginName 插件名称
|
|
291
|
+
* @returns Promise对象
|
|
292
|
+
*/
|
|
293
|
+
registerPendingHandler(pluginName) {
|
|
294
|
+
const handler = (deps, factory) => {
|
|
295
|
+
const entry = this.modules.get(pluginName);
|
|
296
|
+
if (entry) entry._defineCalled = true;
|
|
297
|
+
this.resolveFactory(pluginName, deps, factory).then((mod) => {
|
|
298
|
+
const entry2 = this.modules.get(pluginName);
|
|
299
|
+
if (entry2) {
|
|
300
|
+
entry2.module = mod;
|
|
301
|
+
entry2.status = "resolved";
|
|
302
|
+
_optionalChain([entry2, 'access', _15 => _15._resolve, 'optionalCall', _16 => _16(mod)]);
|
|
303
|
+
}
|
|
304
|
+
}).catch((err) => {
|
|
305
|
+
const entry2 = this.modules.get(pluginName);
|
|
306
|
+
if (entry2) {
|
|
307
|
+
entry2.status = "rejected";
|
|
308
|
+
_optionalChain([entry2, 'access', _17 => _17._reject, 'optionalCall', _18 => _18(err)]);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
this.ownHandlers.delete(pluginName);
|
|
312
|
+
};
|
|
313
|
+
const ns = this.config.namespace;
|
|
314
|
+
const defineFn = window[ns];
|
|
315
|
+
if (!defineFn) throw new Error(`[SmartHub] \u5168\u5C40\u62E6\u622A\u5668 ${ns} \u672A\u521D\u59CB\u5316`);
|
|
316
|
+
if (!defineFn._pendingMap) {
|
|
317
|
+
defineFn._pendingMap = /* @__PURE__ */ new Map();
|
|
318
|
+
}
|
|
319
|
+
const globalMap = defineFn._pendingMap;
|
|
320
|
+
if (!globalMap.has(pluginName)) {
|
|
321
|
+
globalMap.set(pluginName, /* @__PURE__ */ new Set());
|
|
322
|
+
}
|
|
323
|
+
globalMap.get(pluginName).add(handler);
|
|
324
|
+
this.ownHandlers.set(pluginName, handler);
|
|
325
|
+
return handler;
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* 加载插件
|
|
329
|
+
* @param pluginName 插件名称
|
|
330
|
+
* @param options 插件配置
|
|
331
|
+
* @returns Promise对象
|
|
332
|
+
*/
|
|
333
|
+
async loadPlugin(pluginName, options) {
|
|
334
|
+
if (!this.initialized) throw new KernelNotInitializedError();
|
|
335
|
+
const url = typeof options === "string" ? options : options.url;
|
|
336
|
+
const styleUrls = typeof options === "string" ? [] : options.styleUrls || [];
|
|
337
|
+
const cached = this.modules.get(pluginName);
|
|
338
|
+
if (cached && (cached.status === "resolved" || cached.status === "pending") && cached.url === url) {
|
|
339
|
+
return cached._promise;
|
|
340
|
+
}
|
|
341
|
+
if (cached && cached.url !== url) this.unloadPlugin(pluginName);
|
|
342
|
+
this.config.onLoadStart(pluginName);
|
|
343
|
+
const deferred = createDeferred();
|
|
344
|
+
this.modules.set(pluginName, {
|
|
345
|
+
module: null,
|
|
346
|
+
_promise: deferred.promise,
|
|
347
|
+
_resolve: deferred.resolve,
|
|
348
|
+
_reject: deferred.reject,
|
|
349
|
+
status: "pending",
|
|
350
|
+
_defineCalled: false,
|
|
351
|
+
url
|
|
352
|
+
});
|
|
353
|
+
let handler;
|
|
354
|
+
try {
|
|
355
|
+
handler = this.registerPendingHandler(pluginName);
|
|
356
|
+
await this.withRetry(
|
|
357
|
+
() => withTimeout(
|
|
358
|
+
Promise.all([
|
|
359
|
+
this.injectScript(url, pluginName),
|
|
360
|
+
...styleUrls.map((styleUrl) => this.injectStyle(styleUrl, pluginName))
|
|
361
|
+
]),
|
|
362
|
+
this.config.timeout,
|
|
363
|
+
new PluginTimeoutError(pluginName, this.config.timeout)
|
|
364
|
+
),
|
|
365
|
+
pluginName
|
|
366
|
+
);
|
|
367
|
+
const entry = this.modules.get(pluginName);
|
|
368
|
+
if (!entry._defineCalled) {
|
|
369
|
+
throw new PluginExecutionError(pluginName, `Plugin script loaded but ${this.config.namespace} was not called.`);
|
|
370
|
+
}
|
|
371
|
+
const mod = await withTimeout(
|
|
372
|
+
entry._promise,
|
|
373
|
+
this.config.timeout,
|
|
374
|
+
new PluginTimeoutError(pluginName, this.config.timeout)
|
|
375
|
+
);
|
|
376
|
+
this.config.onLoadSuccess(pluginName);
|
|
377
|
+
return mod;
|
|
378
|
+
} catch (err) {
|
|
379
|
+
_optionalChain([this, 'access', _19 => _19.globalPendingMap, 'optionalAccess', _20 => _20.get, 'call', _21 => _21(pluginName), 'optionalAccess', _22 => _22.delete, 'call', _23 => _23(handler)]);
|
|
380
|
+
this.ownHandlers.delete(pluginName);
|
|
381
|
+
const entry = this.modules.get(pluginName);
|
|
382
|
+
if (entry) {
|
|
383
|
+
entry.status = "rejected";
|
|
384
|
+
_optionalChain([entry, 'access', _24 => _24._reject, 'optionalCall', _25 => _25(err)]);
|
|
385
|
+
}
|
|
386
|
+
const pluginErr = toPluginError(pluginName, err);
|
|
387
|
+
this.config.onLoadError(pluginName, pluginErr);
|
|
388
|
+
throw pluginErr;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* 卸载插件
|
|
393
|
+
* @param pluginName 插件名称
|
|
394
|
+
*/
|
|
395
|
+
unloadPlugin(pluginName) {
|
|
396
|
+
this.modules.delete(pluginName);
|
|
397
|
+
const handler = this.ownHandlers.get(pluginName);
|
|
398
|
+
if (handler) {
|
|
399
|
+
_optionalChain([this, 'access', _26 => _26.globalPendingMap, 'optionalAccess', _27 => _27.get, 'call', _28 => _28(pluginName), 'optionalAccess', _29 => _29.delete, 'call', _30 => _30(handler)]);
|
|
400
|
+
this.ownHandlers.delete(pluginName);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* 预加载远端插件资源到浏览器缓存(不执行)
|
|
405
|
+
* @param options 插件地址或配置
|
|
406
|
+
*/
|
|
407
|
+
preloadPlugin(options) {
|
|
408
|
+
if (typeof document === "undefined") return;
|
|
409
|
+
const url = typeof options === "string" ? options : options.url;
|
|
410
|
+
const styleUrls = typeof options === "string" ? [] : options.styleUrls || [];
|
|
411
|
+
const preloadResource = (href, as) => {
|
|
412
|
+
if (document.querySelector(`link[href="${href}"][rel="preload"]`)) return;
|
|
413
|
+
const link = document.createElement("link");
|
|
414
|
+
link.rel = "preload";
|
|
415
|
+
link.href = href;
|
|
416
|
+
link.as = as;
|
|
417
|
+
if (this.config.nonce) link.nonce = this.config.nonce;
|
|
418
|
+
document.head.appendChild(link);
|
|
419
|
+
};
|
|
420
|
+
if (url) preloadResource(url, "script");
|
|
421
|
+
styleUrls.forEach((styleUrl) => preloadResource(styleUrl, "style"));
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* 销毁内核实例
|
|
425
|
+
*/
|
|
426
|
+
destroy() {
|
|
427
|
+
this.ownHandlers.forEach((handler, pluginName) => {
|
|
428
|
+
_optionalChain([this, 'access', _31 => _31.globalPendingMap, 'optionalAccess', _32 => _32.get, 'call', _33 => _33(pluginName), 'optionalAccess', _34 => _34.delete, 'call', _35 => _35(handler)]);
|
|
429
|
+
});
|
|
430
|
+
this.ownHandlers.clear();
|
|
431
|
+
this.modules.clear();
|
|
432
|
+
this.initialized = false;
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
function createKernel(options) {
|
|
436
|
+
return new Kernel(options);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// src/core/index.ts
|
|
440
|
+
var globalKernel = null;
|
|
441
|
+
function initKernel(options) {
|
|
442
|
+
if (globalKernel) return console.warn("[SmartHub] initKernel() \u5DF2\u6267\u884C\u8FC7\uFF0C\u8BF7\u52FF\u91CD\u590D\u8C03\u7528");
|
|
443
|
+
globalKernel = createKernel(options);
|
|
444
|
+
}
|
|
445
|
+
function regSharedModule(name, instance, options) {
|
|
446
|
+
if (!globalKernel) {
|
|
447
|
+
console.warn(`[SmartHub] \u5168\u5C40\u5185\u6838\u672A\u521D\u59CB\u5316\uFF0C\u81EA\u52A8\u4EE5\u9ED8\u8BA4\u914D\u7F6E\u521D\u59CB\u5316...`);
|
|
448
|
+
globalKernel = createKernel();
|
|
449
|
+
}
|
|
450
|
+
globalKernel.regSharedModule(name, instance, options);
|
|
451
|
+
}
|
|
452
|
+
async function loadRemotePlugin(pluginName, options) {
|
|
453
|
+
if (!globalKernel) {
|
|
454
|
+
throw new Error("[SmartHub] \u5185\u6838\u672A\u521D\u59CB\u5316\uFF0C\u8BF7\u5148\u8C03\u7528 initKernel()");
|
|
455
|
+
}
|
|
456
|
+
return globalKernel.loadPlugin(pluginName, options);
|
|
457
|
+
}
|
|
458
|
+
function preloadRemotePlugin(options) {
|
|
459
|
+
if (!globalKernel) {
|
|
460
|
+
console.warn("[SmartHub] \u5168\u5C40\u5185\u6838\u672A\u521D\u59CB\u5316\uFF0C\u81EA\u52A8\u4EE5\u9ED8\u8BA4\u914D\u7F6E\u521D\u59CB\u5316...");
|
|
461
|
+
globalKernel = createKernel();
|
|
462
|
+
}
|
|
463
|
+
globalKernel.preloadPlugin(options);
|
|
464
|
+
}
|
|
465
|
+
function getGlobalKernel() {
|
|
466
|
+
return globalKernel;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
exports.PluginError = PluginError; exports.PluginNetworkError = PluginNetworkError; exports.PluginTimeoutError = PluginTimeoutError; exports.PluginDependencyError = PluginDependencyError; exports.PluginExecutionError = PluginExecutionError; exports.KernelNotInitializedError = KernelNotInitializedError; exports.createKernel = createKernel; exports.initKernel = initKernel; exports.regSharedModule = regSharedModule; exports.loadRemotePlugin = loadRemotePlugin; exports.preloadRemotePlugin = preloadRemotePlugin; exports.getGlobalKernel = getGlobalKernel;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
var _chunkETCJDJTIcjs = require('../chunk-ETCJDJTI.cjs');
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
exports.KernelNotInitializedError = _chunkETCJDJTIcjs.KernelNotInitializedError; exports.PluginDependencyError = _chunkETCJDJTIcjs.PluginDependencyError; exports.PluginError = _chunkETCJDJTIcjs.PluginError; exports.PluginExecutionError = _chunkETCJDJTIcjs.PluginExecutionError; exports.PluginNetworkError = _chunkETCJDJTIcjs.PluginNetworkError; exports.PluginTimeoutError = _chunkETCJDJTIcjs.PluginTimeoutError; exports.createKernel = _chunkETCJDJTIcjs.createKernel; exports.getGlobalKernel = _chunkETCJDJTIcjs.getGlobalKernel; exports.initKernel = _chunkETCJDJTIcjs.initKernel; exports.loadRemotePlugin = _chunkETCJDJTIcjs.loadRemotePlugin; exports.preloadRemotePlugin = _chunkETCJDJTIcjs.preloadRemotePlugin; exports.regSharedModule = _chunkETCJDJTIcjs.regSharedModule;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { K as KernelOptions, a as KernelInstance, P as PluginLoadOptions } from '../types-JlxTjSfC.cjs';
|
|
2
|
+
export { b as KernelLogger, c as KernelNotInitializedError, M as ModuleEntry, d as PluginDependencyError, e as PluginError, f as PluginExecutionError, g as PluginNetworkError, h as PluginTimeoutError } from '../types-JlxTjSfC.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 创建内核实例
|
|
6
|
+
* @param options 内核配置
|
|
7
|
+
* @returns 内核实例
|
|
8
|
+
*/
|
|
9
|
+
declare function createKernel(options?: KernelOptions): KernelInstance;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 初始化全局内核引擎
|
|
13
|
+
* @param options 内核配置项
|
|
14
|
+
* - timeout: 网络请求超时时间(毫秒),默认 10000
|
|
15
|
+
* - retryCount: 网络请求重试次数,默认 2
|
|
16
|
+
* - namespace: 插件命名空间,默认 '__KERNEL__'
|
|
17
|
+
* - debug: 是否开启调试模式,默认 true
|
|
18
|
+
* - logger: 自定义日志处理器
|
|
19
|
+
* - onLoadStart: 插件加载开始时的钩子
|
|
20
|
+
* - onLoadSuccess: 插件加载成功后的钩子
|
|
21
|
+
* - onLoadError: 插件加载失败后的全局错误钩子
|
|
22
|
+
*/
|
|
23
|
+
declare function initKernel(options?: KernelOptions): void;
|
|
24
|
+
/**
|
|
25
|
+
* 注册共享模块到全局内核
|
|
26
|
+
* @param name 模块名
|
|
27
|
+
* @param instance 模块实例
|
|
28
|
+
* @param options 选项
|
|
29
|
+
* - force: 是否强制覆盖已存在的同名模块,默认为 false
|
|
30
|
+
*/
|
|
31
|
+
declare function regSharedModule(name: string, instance: any, options?: {
|
|
32
|
+
force?: boolean;
|
|
33
|
+
}): void;
|
|
34
|
+
/**
|
|
35
|
+
* 通过全局内核加载远端插件
|
|
36
|
+
* @param pluginName 插件名
|
|
37
|
+
* @param options 插件加载选项
|
|
38
|
+
* - url: 插件脚本地址
|
|
39
|
+
* - styleUrls: 插件样式地址列表
|
|
40
|
+
* - type: 插件模块类型,'umd' 使用全局 define,'esm' 使用原生 import,默认 'umd'
|
|
41
|
+
* @returns 插件实例
|
|
42
|
+
*/
|
|
43
|
+
declare function loadRemotePlugin<T = any>(pluginName: string, options: PluginLoadOptions): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* 预加载远端插件(通过 <link rel="preload"> 加载到浏览器缓存,但不执行)
|
|
46
|
+
* @param options 插件加载选项
|
|
47
|
+
* - url: 插件脚本地址
|
|
48
|
+
* - styleUrls: 插件样式地址列表
|
|
49
|
+
* - type: 插件模块类型,'umd' 使用全局 define,'esm' 使用原生 import,默认 'umd'
|
|
50
|
+
*/
|
|
51
|
+
declare function preloadRemotePlugin(options: PluginLoadOptions): void;
|
|
52
|
+
/**
|
|
53
|
+
* 获取全局内核实例(需已调用 initKernel())
|
|
54
|
+
* 可用于直接调用 unloadPlugin() / destroy() 等方法
|
|
55
|
+
*/
|
|
56
|
+
declare function getGlobalKernel(): KernelInstance | null;
|
|
57
|
+
|
|
58
|
+
export { KernelInstance, KernelOptions, PluginLoadOptions, createKernel, getGlobalKernel, initKernel, loadRemotePlugin, preloadRemotePlugin, regSharedModule };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { K as KernelOptions, a as KernelInstance, P as PluginLoadOptions } from '../types-JlxTjSfC.js';
|
|
2
|
+
export { b as KernelLogger, c as KernelNotInitializedError, M as ModuleEntry, d as PluginDependencyError, e as PluginError, f as PluginExecutionError, g as PluginNetworkError, h as PluginTimeoutError } from '../types-JlxTjSfC.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 创建内核实例
|
|
6
|
+
* @param options 内核配置
|
|
7
|
+
* @returns 内核实例
|
|
8
|
+
*/
|
|
9
|
+
declare function createKernel(options?: KernelOptions): KernelInstance;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 初始化全局内核引擎
|
|
13
|
+
* @param options 内核配置项
|
|
14
|
+
* - timeout: 网络请求超时时间(毫秒),默认 10000
|
|
15
|
+
* - retryCount: 网络请求重试次数,默认 2
|
|
16
|
+
* - namespace: 插件命名空间,默认 '__KERNEL__'
|
|
17
|
+
* - debug: 是否开启调试模式,默认 true
|
|
18
|
+
* - logger: 自定义日志处理器
|
|
19
|
+
* - onLoadStart: 插件加载开始时的钩子
|
|
20
|
+
* - onLoadSuccess: 插件加载成功后的钩子
|
|
21
|
+
* - onLoadError: 插件加载失败后的全局错误钩子
|
|
22
|
+
*/
|
|
23
|
+
declare function initKernel(options?: KernelOptions): void;
|
|
24
|
+
/**
|
|
25
|
+
* 注册共享模块到全局内核
|
|
26
|
+
* @param name 模块名
|
|
27
|
+
* @param instance 模块实例
|
|
28
|
+
* @param options 选项
|
|
29
|
+
* - force: 是否强制覆盖已存在的同名模块,默认为 false
|
|
30
|
+
*/
|
|
31
|
+
declare function regSharedModule(name: string, instance: any, options?: {
|
|
32
|
+
force?: boolean;
|
|
33
|
+
}): void;
|
|
34
|
+
/**
|
|
35
|
+
* 通过全局内核加载远端插件
|
|
36
|
+
* @param pluginName 插件名
|
|
37
|
+
* @param options 插件加载选项
|
|
38
|
+
* - url: 插件脚本地址
|
|
39
|
+
* - styleUrls: 插件样式地址列表
|
|
40
|
+
* - type: 插件模块类型,'umd' 使用全局 define,'esm' 使用原生 import,默认 'umd'
|
|
41
|
+
* @returns 插件实例
|
|
42
|
+
*/
|
|
43
|
+
declare function loadRemotePlugin<T = any>(pluginName: string, options: PluginLoadOptions): Promise<T>;
|
|
44
|
+
/**
|
|
45
|
+
* 预加载远端插件(通过 <link rel="preload"> 加载到浏览器缓存,但不执行)
|
|
46
|
+
* @param options 插件加载选项
|
|
47
|
+
* - url: 插件脚本地址
|
|
48
|
+
* - styleUrls: 插件样式地址列表
|
|
49
|
+
* - type: 插件模块类型,'umd' 使用全局 define,'esm' 使用原生 import,默认 'umd'
|
|
50
|
+
*/
|
|
51
|
+
declare function preloadRemotePlugin(options: PluginLoadOptions): void;
|
|
52
|
+
/**
|
|
53
|
+
* 获取全局内核实例(需已调用 initKernel())
|
|
54
|
+
* 可用于直接调用 unloadPlugin() / destroy() 等方法
|
|
55
|
+
*/
|
|
56
|
+
declare function getGlobalKernel(): KernelInstance | null;
|
|
57
|
+
|
|
58
|
+
export { KernelInstance, KernelOptions, PluginLoadOptions, createKernel, getGlobalKernel, initKernel, loadRemotePlugin, preloadRemotePlugin, regSharedModule };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
KernelNotInitializedError,
|
|
3
|
+
PluginDependencyError,
|
|
4
|
+
PluginError,
|
|
5
|
+
PluginExecutionError,
|
|
6
|
+
PluginNetworkError,
|
|
7
|
+
PluginTimeoutError,
|
|
8
|
+
createKernel,
|
|
9
|
+
getGlobalKernel,
|
|
10
|
+
initKernel,
|
|
11
|
+
loadRemotePlugin,
|
|
12
|
+
preloadRemotePlugin,
|
|
13
|
+
regSharedModule
|
|
14
|
+
} from "../chunk-D4E5XKWD.js";
|
|
15
|
+
export {
|
|
16
|
+
KernelNotInitializedError,
|
|
17
|
+
PluginDependencyError,
|
|
18
|
+
PluginError,
|
|
19
|
+
PluginExecutionError,
|
|
20
|
+
PluginNetworkError,
|
|
21
|
+
PluginTimeoutError,
|
|
22
|
+
createKernel,
|
|
23
|
+
getGlobalKernel,
|
|
24
|
+
initKernel,
|
|
25
|
+
loadRemotePlugin,
|
|
26
|
+
preloadRemotePlugin,
|
|
27
|
+
regSharedModule
|
|
28
|
+
};
|