@lytjs/core 5.0.0 → 6.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 (44) hide show
  1. package/README.md +328 -288
  2. package/dist/index.cjs +3482 -1
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/index.d.cts +1473 -0
  5. package/dist/index.d.ts +1473 -0
  6. package/dist/index.mjs +3342 -1
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +43 -57
  9. package/dist/error-entry.cjs +0 -1
  10. package/dist/error-entry.mjs +0 -1
  11. package/dist/plugin-entry.cjs +0 -1
  12. package/dist/plugin-entry.mjs +0 -1
  13. package/dist/shared-entry.cjs +0 -1
  14. package/dist/shared-entry.mjs +0 -1
  15. package/dist/types/create-app.d.ts +0 -161
  16. package/dist/types/create-app.d.ts.map +0 -1
  17. package/dist/types/dev-error.d.ts +0 -32
  18. package/dist/types/dev-error.d.ts.map +0 -1
  19. package/dist/types/error-codes.d.ts +0 -8
  20. package/dist/types/error-codes.d.ts.map +0 -1
  21. package/dist/types/error-entry.d.ts +0 -14
  22. package/dist/types/error-entry.d.ts.map +0 -1
  23. package/dist/types/error-handling.d.ts +0 -264
  24. package/dist/types/error-handling.d.ts.map +0 -1
  25. package/dist/types/h.d.ts +0 -96
  26. package/dist/types/h.d.ts.map +0 -1
  27. package/dist/types/index.d.ts +0 -13
  28. package/dist/types/index.d.ts.map +0 -1
  29. package/dist/types/lyt-error.d.ts +0 -8
  30. package/dist/types/lyt-error.d.ts.map +0 -1
  31. package/dist/types/plugin-entry.d.ts +0 -9
  32. package/dist/types/plugin-entry.d.ts.map +0 -1
  33. package/dist/types/plugin.d.ts +0 -119
  34. package/dist/types/plugin.d.ts.map +0 -1
  35. package/dist/types/shared-entry.d.ts +0 -8
  36. package/dist/types/shared-entry.d.ts.map +0 -1
  37. package/dist/types/warn.d.ts +0 -8
  38. package/dist/types/warn.d.ts.map +0 -1
  39. package/dist/types/web-component-entry.d.ts +0 -9
  40. package/dist/types/web-component-entry.d.ts.map +0 -1
  41. package/dist/types/web-component.d.ts +0 -127
  42. package/dist/types/web-component.d.ts.map +0 -1
  43. package/dist/web-component-entry.cjs +0 -6
  44. package/dist/web-component-entry.mjs +0 -6
package/dist/index.cjs CHANGED
@@ -1 +1,3482 @@
1
- "use strict";var E=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var q=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var Y=(n,e)=>{for(var t in e)E(n,t,{get:e[t],enumerable:!0})},O=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of q(e))!X.call(n,o)&&o!==t&&E(n,o,{get:()=>e[o],enumerable:!(i=$(e,o))||i.enumerable});return n},A=(n,e,t)=>(O(n,e,"default"),t&&O(t,e,"default"));var K=n=>O(E({},"__esModule",{value:!0}),n);var v={};Y(v,{Fragment:()=>x.Fragment,ShapeFlags:()=>L,createApp:()=>S,h:()=>R});module.exports=K(v);var y=require("@lytjs/common"),x=require("@lytjs/vdom");var L=(s=>(s[s.ELEMENT=1]="ELEMENT",s[s.FUNCTIONAL_COMPONENT=2]="FUNCTIONAL_COMPONENT",s[s.STATEFUL_COMPONENT=4]="STATEFUL_COMPONENT",s[s.TEXT_CHILDREN=8]="TEXT_CHILDREN",s[s.ARRAY_CHILDREN=16]="ARRAY_CHILDREN",s[s.SLOTS_CHILDREN=32]="SLOTS_CHILDREN",s))(L||{});function Z(n,e){if(e!=null)if((0,y.isStringOrNumber)(e))n.children=String(e),n.shapeFlag|=8;else if((0,y.isArray)(e)){let t=[];for(let i=0;i<e.length;i++){let o=e[i];if(!(o==null||typeof o=="boolean"))if((0,y.isArray)(o))for(let p=0;p<o.length;p++){let s=o[p];s!=null&&typeof s!="boolean"&&t.push((0,y.isVNode)(s)?s:j(String(s)))}else(0,y.isVNode)(o)?t.push(o):t.push(j(String(o)))}n.children=t,n.shapeFlag|=16}else typeof e=="object"&&(n.children=e,n.shapeFlag|=32)}function j(n,e=null,t=null){var u,f;let i=0;typeof n=="string"?i=1:n===x.Fragment?i=0:typeof n=="function"?i=2:typeof n=="object"&&n!==null&&(n.setup||n.__vccOpts||n.render)&&(i=4);let o=(u=e==null?void 0:e.key)!=null?u:null,p=(f=e==null?void 0:e.ref)!=null?f:null,s=e;if(e){let{key:C,ref:d,...b}=e;s=b}let P={type:n,props:s,children:null,key:o,ref:p,shapeFlag:i,el:null,component:null};return t!=null&&Z(P,t),P}function R(n,e,t){return j(n,e||null,t||null)}var k=require("@lytjs/common");function w(n){return Object.create(n||null)}function D(n){return n!==null&&typeof n=="object"&&typeof n.install=="function"}function V(n){return typeof n=="function"}function _(n,e,...t){if(D(e)){let i=e.onBeforeInstall?e.onBeforeInstall(n,...t):void 0;if((0,k.isPromise)(i))return i.then(()=>{let o=e.install(n,...t);if((0,k.isPromise)(o))return o.then(()=>{if(e.onInstalled)return e.onInstalled(n,...t)});if(e.onInstalled)return e.onInstalled(n,...t)});{let o=e.install(n,...t);if((0,k.isPromise)(o))return o.then(()=>{if(e.onInstalled)return e.onInstalled(n,...t)});if(e.onInstalled)return e.onInstalled(n,...t)}}else if(V(e))return e(n,...t)}function F(n,e){if(D(e)){if(typeof e.uninstall=="function")return e.uninstall(n)}else V(e)}var T=require("@lytjs/reactivity"),H=require("@lytjs/compiler"),c=require("@lytjs/component"),M=require("@lytjs/renderer"),G=100,g=new Map;function J(n){let e=g.get(n);if(e)return g.delete(n),g.set(n,e),e;let{code:t}=(0,H.compile)(n);if(e=new Function("h","_ctx",`return ${t}`),g.size>=G){let i=g.keys().next().value;i!==void 0&&g.delete(i)}return g.set(n,e),e}function Q(n){let e={...n};if(n.state&&typeof n.state!="function"){let t=n.state;e.state=()=>({...t})}if(typeof n.render=="function"){let t=n.render;e.render=(i,o)=>t(i)}if(n.computed){let t={};for(let i of Object.keys(n.computed)){let o=n.computed[i];typeof o=="function"?t[i]={get:o}:t[i]=o}e.computed=t}if(typeof n.init=="function"){let t=n.init;e.init=function(i,o){return t.call(this,i)}}return e}function W(){return{createElement(n){return document.createElement(n)},createText(n){return document.createTextNode(n)},createComment(n){return document.createComment(n)},setAttribute(n,e,t){n.setAttribute(e,String(t))},removeAttribute(n,e){n.removeAttribute(e)},setStyle(n,e){if(typeof e=="string")n.style.cssText=e;else if(e&&typeof e=="object")for(let t in e)n.style[t]=e[t]},setClass(n,e){if(typeof e=="string")n.className=e;else if(e&&typeof e=="object"){let t=[];for(let[i,o]of Object.entries(e))o&&t.push(i);n.className=t.join(" ")}else n.className=""},insert(n,e,t){t!=null?n.insertBefore(e,t):n.appendChild(e)},remove(n){n.parentNode&&n.parentNode.removeChild(n)},replace(n,e,t){n.replaceChild(t,e)},addEventListener(n,e,t,i){n.addEventListener(e,t,i)},removeEventListener(n,e,t){n.removeEventListener(e,t)},nextTick(n){Promise.resolve().then(n)},parentNode(n){return n.parentNode},nextSibling(n){return n.nextSibling},querySelector(n){return document.querySelector(n)}}}function S(n,e){let t=new Set,i={},o={},p=w(),s={},P={},u=null,f=null,C=null,d=null,b=!1,B=Q(typeof n=="function"?{render:n}:n),U=(0,c.defineComponent)(B),r={config:s,globalProperties:P,get _instance(){return u},mount(l){if(b)return r;let a;if(typeof l=="string"){let I=document.querySelector(l);if(!I)throw new Error(`[Lyt] \u6302\u8F7D\u76EE\u6807 "${l}" \u672A\u627E\u5230`);a=I}else a=l;d=a;let m=W();f=(0,M.createRenderer)(m),u=(0,c.createComponentInstance)(U),(0,c.setupComponent)(u,e||{},null);let N=u.type;if(!N.render&&N.template){let I=J(N.template);N.render=(h,z)=>I(h,z.renderProxy)}return(0,c.mountComponent)(u,R),u.subTree&&f.mount(u.subTree,a),C=(0,T.effect)(()=>{if(!(!u||!u.isMounted||!f)&&((0,c.updateComponent)(u,R),u.subTree&&d)){let I=d.firstChild,h=u.subTree;for(;d.firstChild;)d.removeChild(d.firstChild);f.mount(h,d)}},{lazy:!0}),b=!0,r},unmount(){if(b){if(C&&((0,T.stop)(C),C=null),u&&(0,c.unmountComponent)(u),d)for(;d.firstChild;)d.removeChild(d.firstChild);u=null,f=null,d=null,b=!1}},use(l,...a){if(t.has(l))return r;t.add(l);let m=_({use:r.use.bind(r),unuse:r.unuse.bind(r),isInstalled:r.isInstalled.bind(r),provide:r.provide.bind(r),inject:r.inject.bind(r),config:s,globalProperties:P},l,...a);return m instanceof Promise?m.then(()=>r):r},unuse(l){if(!t.has(l))return r;t.delete(l);let a=F({use:r.use.bind(r),unuse:r.unuse.bind(r),isInstalled:r.isInstalled.bind(r),provide:r.provide.bind(r),inject:r.inject.bind(r),config:s,globalProperties:P},l);return a instanceof Promise?a.then(()=>r):r},isInstalled(l){return t.has(l)},provide(l,a){return p[l]=a,r},inject(l,a){let m=p[l];return m!==void 0?m:a},component(l,a){return a?(i[l]=a,r):i[l]},directive(l,a){return a?(o[l]=a,r):o[l]}};return r}A(v,require("@lytjs/common"),module.exports);
1
+ 'use strict';
2
+
3
+ var component = require('@lytjs/component');
4
+ var commonError = require('@lytjs/common-error');
5
+ var vdom = require('@lytjs/vdom');
6
+ var reactivity = require('@lytjs/reactivity');
7
+ var commonScheduler = require('@lytjs/common-scheduler');
8
+ var commonIs = require('@lytjs/common-is');
9
+ var scope = require('@lytjs/reactivity/scope');
10
+ var renderer = require('@lytjs/renderer');
11
+ var commonObject = require('@lytjs/common-object');
12
+ var compiler = require('@lytjs/compiler');
13
+
14
+ var __defProp = Object.defineProperty;
15
+ var __getOwnPropNames = Object.getOwnPropertyNames;
16
+ var __esm = (fn, res) => function __init() {
17
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, { get: all[name], enumerable: true });
22
+ };
23
+ function createAppContext() {
24
+ return {
25
+ ...component.createAppContext(),
26
+ config: {
27
+ performance: false,
28
+ globalProperties: {}
29
+ },
30
+ renderer: null,
31
+ _vnode: null,
32
+ _container: null,
33
+ _instance: null
34
+ };
35
+ }
36
+ function createContextConfig(context) {
37
+ return new Proxy({}, {
38
+ get(_, key) {
39
+ if (key === "globalProperties") {
40
+ return context.config.globalProperties;
41
+ }
42
+ return context.config[key];
43
+ },
44
+ set(_, key, value) {
45
+ if (key === "globalProperties") {
46
+ context.config.globalProperties = value;
47
+ return true;
48
+ }
49
+ context.config[key] = value;
50
+ return true;
51
+ },
52
+ ownKeys() {
53
+ return Reflect.ownKeys(context.config);
54
+ },
55
+ has(_, key) {
56
+ return key in context.config;
57
+ },
58
+ getOwnPropertyDescriptor(_, key) {
59
+ return Object.getOwnPropertyDescriptor(context.config, key);
60
+ }
61
+ });
62
+ }
63
+ var init_app_context = __esm({
64
+ "src/app-context.ts"() {
65
+ }
66
+ });
67
+ exports.PluginRegistry = void 0;
68
+ var init_plugin_registry = __esm({
69
+ "src/plugin-registry.ts"() {
70
+ exports.PluginRegistry = class {
71
+ constructor() {
72
+ /** 已注册插件映射(name → RegisteredPlugin) */
73
+ this.plugins = /* @__PURE__ */ new Map();
74
+ /** 事件监听器映射 */
75
+ this.listeners = /* @__PURE__ */ new Map();
76
+ }
77
+ /**
78
+ * 注册插件
79
+ * @param plugin - 插件实例(EnhancedPlugin 或基础 Plugin)
80
+ * @param options - 安装选项
81
+ * @returns 注册结果
82
+ */
83
+ register(plugin, options = void 0) {
84
+ const name = this.getPluginName(plugin);
85
+ if (!name) {
86
+ const result = {
87
+ success: false,
88
+ name: "anonymous",
89
+ error: "Plugin must have a name property. Use EnhancedPlugin interface for full support."
90
+ };
91
+ this.emit("error", result);
92
+ return result;
93
+ }
94
+ if (this.plugins.has(name)) {
95
+ const result = {
96
+ success: false,
97
+ name,
98
+ error: `Plugin "${name}" is already registered.`
99
+ };
100
+ this.emit("error", result);
101
+ return result;
102
+ }
103
+ if (this.isEnhancedPlugin(plugin)) {
104
+ const conflict = this.checkConflicts(plugin);
105
+ if (conflict) {
106
+ const result = {
107
+ success: false,
108
+ name,
109
+ error: `Plugin "${name}" conflicts with: ${conflict.join(", ")}`
110
+ };
111
+ this.emit("error", result);
112
+ return result;
113
+ }
114
+ }
115
+ this.emit("before:register", { name, plugin });
116
+ const registered = {
117
+ plugin: this.normalizePlugin(plugin),
118
+ options,
119
+ installed: false,
120
+ registeredAt: Date.now()
121
+ };
122
+ this.plugins.set(name, registered);
123
+ this.emit("after:register", { name, plugin });
124
+ return { success: true, name };
125
+ }
126
+ /**
127
+ * 注销插件
128
+ * @param name - 插件名称
129
+ * @returns 是否成功注销
130
+ */
131
+ unregister(name) {
132
+ const registered = this.plugins.get(name);
133
+ if (!registered) {
134
+ return false;
135
+ }
136
+ this.emit("before:unregister", { name, plugin: registered.plugin });
137
+ if (registered.installed && registered.plugin.cleanup) {
138
+ try {
139
+ const cleanupResult = registered.plugin.cleanup();
140
+ if (cleanupResult instanceof Promise) {
141
+ cleanupResult.catch((err) => {
142
+ commonError.error(
143
+ `Plugin "${name}" async cleanup failed: ${err instanceof Error ? err.message : String(err)}`
144
+ );
145
+ });
146
+ }
147
+ } catch (err) {
148
+ commonError.error(
149
+ `Plugin "${name}" cleanup failed: ${err instanceof Error ? err.message : String(err)}`
150
+ );
151
+ }
152
+ }
153
+ this.plugins.delete(name);
154
+ this.emit("after:unregister", { name });
155
+ return true;
156
+ }
157
+ /**
158
+ * 获取已注册插件信息
159
+ * @param name - 插件名称
160
+ * @returns 插件注册信息,如果未找到则返回 undefined
161
+ */
162
+ get(name) {
163
+ return this.plugins.get(name);
164
+ }
165
+ /**
166
+ * 获取已注册的插件实例
167
+ * @param name - 插件名称
168
+ * @returns 插件实例,如果未找到则返回 undefined
169
+ */
170
+ getPlugin(name) {
171
+ return this.plugins.get(name)?.plugin;
172
+ }
173
+ /**
174
+ * 检查插件是否已注册
175
+ * @param name - 插件名称
176
+ */
177
+ has(name) {
178
+ return this.plugins.has(name);
179
+ }
180
+ /**
181
+ * 获取所有已注册插件名称
182
+ */
183
+ getNames() {
184
+ return Array.from(this.plugins.keys());
185
+ }
186
+ /**
187
+ * 获取所有已注册插件信息
188
+ */
189
+ getAll() {
190
+ return Array.from(this.plugins.values());
191
+ }
192
+ /**
193
+ * 获取已安装插件列表
194
+ */
195
+ getInstalled() {
196
+ return this.getAll().filter((p) => p.installed);
197
+ }
198
+ /**
199
+ * 标记插件为已安装
200
+ * @param name - 插件名称
201
+ */
202
+ markInstalled(name) {
203
+ const registered = this.plugins.get(name);
204
+ if (registered) {
205
+ registered.installed = true;
206
+ registered.installedAt = Date.now();
207
+ }
208
+ }
209
+ /**
210
+ * 标记插件为未安装
211
+ * @param name - 插件名称
212
+ */
213
+ markUninstalled(name) {
214
+ const registered = this.plugins.get(name);
215
+ if (registered) {
216
+ registered.installed = false;
217
+ registered.installedAt = void 0;
218
+ }
219
+ }
220
+ /**
221
+ * 检查插件依赖是否满足
222
+ * @param plugin - 要检查的插件
223
+ * @returns 依赖检查结果
224
+ */
225
+ checkDependencies(plugin) {
226
+ const result = {
227
+ satisfied: true,
228
+ missing: [],
229
+ missingOptional: [],
230
+ versionMismatch: []
231
+ };
232
+ if (!this.isEnhancedPlugin(plugin)) {
233
+ return result;
234
+ }
235
+ if (plugin.dependencies) {
236
+ for (const dep of plugin.dependencies) {
237
+ const registered = this.plugins.get(dep.name);
238
+ if (!registered) {
239
+ result.satisfied = false;
240
+ result.missing.push({ name: dep.name, version: dep.version });
241
+ } else if (dep.version && registered.plugin.version) {
242
+ if (!this.satisfiesVersion(registered.plugin.version, dep.version)) {
243
+ result.satisfied = false;
244
+ result.versionMismatch.push({
245
+ name: dep.name,
246
+ expected: dep.version,
247
+ actual: registered.plugin.version
248
+ });
249
+ }
250
+ }
251
+ }
252
+ }
253
+ if (plugin.optionalDependencies) {
254
+ for (const dep of plugin.optionalDependencies) {
255
+ const registered = this.plugins.get(dep.name);
256
+ if (!registered) {
257
+ result.missingOptional.push({ name: dep.name, version: dep.version });
258
+ } else if (dep.version && registered.plugin.version) {
259
+ if (!this.satisfiesVersion(registered.plugin.version, dep.version)) {
260
+ result.versionMismatch.push({
261
+ name: dep.name,
262
+ expected: dep.version,
263
+ actual: registered.plugin.version
264
+ });
265
+ }
266
+ }
267
+ }
268
+ }
269
+ return result;
270
+ }
271
+ /**
272
+ * 解析插件加载顺序(拓扑排序)
273
+ * @description 根据依赖关系计算正确的安装顺序
274
+ * @returns 排序后的插件列表
275
+ * @throws 如果存在循环依赖则抛出错误
276
+ */
277
+ resolveLoadOrder() {
278
+ const visited = /* @__PURE__ */ new Set();
279
+ const visiting = /* @__PURE__ */ new Set();
280
+ const result = [];
281
+ const visit = (name) => {
282
+ if (visited.has(name)) return;
283
+ if (visiting.has(name)) {
284
+ throw new Error(`Circular dependency detected involving plugin "${name}"`);
285
+ }
286
+ visiting.add(name);
287
+ const registered = this.plugins.get(name);
288
+ if (registered && this.isEnhancedPlugin(registered.plugin)) {
289
+ if (registered.plugin.dependencies) {
290
+ for (const dep of registered.plugin.dependencies) {
291
+ if (this.plugins.has(dep.name)) {
292
+ visit(dep.name);
293
+ }
294
+ }
295
+ }
296
+ }
297
+ visiting.delete(name);
298
+ visited.add(name);
299
+ if (registered) {
300
+ result.push(registered.plugin);
301
+ }
302
+ };
303
+ for (const name of this.plugins.keys()) {
304
+ visit(name);
305
+ }
306
+ return result;
307
+ }
308
+ /**
309
+ * 获取插件数量
310
+ */
311
+ get size() {
312
+ return this.plugins.size;
313
+ }
314
+ /**
315
+ * 清空所有已注册插件
316
+ */
317
+ clear() {
318
+ for (const [name, registered] of this.plugins) {
319
+ if (registered.installed && registered.plugin.cleanup) {
320
+ try {
321
+ registered.plugin.cleanup();
322
+ } catch (err) {
323
+ commonError.error(
324
+ `Plugin "${name}" cleanup failed during clear: ${err instanceof Error ? err.message : String(err)}`
325
+ );
326
+ }
327
+ }
328
+ }
329
+ this.plugins.clear();
330
+ }
331
+ // ==================== 事件系统 ====================
332
+ /**
333
+ * 注册事件监听器
334
+ * @param event - 事件类型
335
+ * @param handler - 事件处理函数
336
+ * @returns 取消监听的函数
337
+ */
338
+ on(event, handler) {
339
+ if (!this.listeners.has(event)) {
340
+ this.listeners.set(event, /* @__PURE__ */ new Set());
341
+ }
342
+ this.listeners.get(event).add(handler);
343
+ return () => {
344
+ this.listeners.get(event)?.delete(handler);
345
+ };
346
+ }
347
+ /**
348
+ * 触发事件
349
+ * @param event - 事件类型
350
+ * @param data - 事件数据
351
+ */
352
+ emit(event, data) {
353
+ const handlers = this.listeners.get(event);
354
+ if (handlers) {
355
+ for (const handler of handlers) {
356
+ try {
357
+ handler(event, data);
358
+ } catch (err) {
359
+ commonError.error(
360
+ `Plugin event handler error for "${event}": ${err instanceof Error ? err.message : String(err)}`
361
+ );
362
+ }
363
+ }
364
+ }
365
+ }
366
+ /**
367
+ * 移除事件监听器
368
+ * @param event - 事件类型
369
+ * @param handler - 事件处理函数
370
+ */
371
+ off(event, handler) {
372
+ this.listeners.get(event)?.delete(handler);
373
+ }
374
+ // ==================== 内部工具方法 ====================
375
+ /**
376
+ * 获取插件名称
377
+ */
378
+ getPluginName(plugin) {
379
+ if (this.isEnhancedPlugin(plugin)) {
380
+ return plugin.name;
381
+ }
382
+ return plugin.name;
383
+ }
384
+ /**
385
+ * 检查是否为 EnhancedPlugin
386
+ */
387
+ isEnhancedPlugin(plugin) {
388
+ return "name" in plugin && typeof plugin.name === "string";
389
+ }
390
+ /**
391
+ * 将基础 Plugin 标准化为 EnhancedPlugin
392
+ */
393
+ normalizePlugin(plugin) {
394
+ if (this.isEnhancedPlugin(plugin)) {
395
+ return plugin;
396
+ }
397
+ const anonymousName = `anonymous-plugin-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
398
+ return {
399
+ install: plugin.install,
400
+ name: anonymousName
401
+ };
402
+ }
403
+ /**
404
+ * 检查插件冲突
405
+ */
406
+ checkConflicts(plugin) {
407
+ if (!plugin.conflicts || plugin.conflicts.length === 0) {
408
+ return null;
409
+ }
410
+ const conflicts = [];
411
+ for (const conflictName of plugin.conflicts) {
412
+ if (this.plugins.has(conflictName)) {
413
+ conflicts.push(conflictName);
414
+ }
415
+ }
416
+ return conflicts.length > 0 ? conflicts : null;
417
+ }
418
+ /**
419
+ * 简单的 semver 版本比较
420
+ * @description 支持 ^, ~, >=, >, <, <=, = 前缀
421
+ */
422
+ satisfiesVersion(actual, expected) {
423
+ const actualVersion = this.parseVersion(actual);
424
+ if (!actualVersion) return false;
425
+ const range = expected.trim();
426
+ let prefix = "";
427
+ let expectedVersion = range;
428
+ if (range.startsWith("^") || range.startsWith("~") || range.startsWith(">") || range.startsWith("<") || range.startsWith("=")) {
429
+ const firstChar = range[0];
430
+ prefix = firstChar;
431
+ expectedVersion = range.slice(1).trim();
432
+ if (range.startsWith(">=") || range.startsWith("<=")) {
433
+ prefix = range.slice(0, 2);
434
+ expectedVersion = range.slice(2).trim();
435
+ }
436
+ }
437
+ const expectedParsed = this.parseVersion(expectedVersion);
438
+ if (!expectedParsed) return false;
439
+ switch (prefix) {
440
+ case "":
441
+ case "=":
442
+ return actualVersion.major === expectedParsed.major && actualVersion.minor === expectedParsed.minor && actualVersion.patch === expectedParsed.patch;
443
+ case "^":
444
+ return actualVersion.major === expectedParsed.major && (actualVersion.minor > expectedParsed.minor || actualVersion.minor === expectedParsed.minor && actualVersion.patch >= expectedParsed.patch);
445
+ case "~":
446
+ return actualVersion.major === expectedParsed.major && actualVersion.minor === expectedParsed.minor && actualVersion.patch >= expectedParsed.patch;
447
+ case ">":
448
+ return this.compareVersions(actualVersion, expectedParsed) > 0;
449
+ case ">=":
450
+ return this.compareVersions(actualVersion, expectedParsed) >= 0;
451
+ case "<":
452
+ return this.compareVersions(actualVersion, expectedParsed) < 0;
453
+ case "<=":
454
+ return this.compareVersions(actualVersion, expectedParsed) <= 0;
455
+ default:
456
+ return false;
457
+ }
458
+ }
459
+ /**
460
+ * 解析版本号字符串
461
+ */
462
+ parseVersion(version) {
463
+ const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
464
+ if (!match) return null;
465
+ return {
466
+ major: parseInt(match[1], 10),
467
+ minor: parseInt(match[2], 10),
468
+ patch: parseInt(match[3], 10)
469
+ };
470
+ }
471
+ /**
472
+ * 比较两个版本号
473
+ * @returns 正数表示 a > b,负数表示 a < b,0 表示相等
474
+ */
475
+ compareVersions(a, b) {
476
+ if (a.major !== b.major) return a.major - b.major;
477
+ if (a.minor !== b.minor) return a.minor - b.minor;
478
+ return a.patch - b.patch;
479
+ }
480
+ };
481
+ }
482
+ });
483
+
484
+ // src/plugin-validator.ts
485
+ exports.PluginValidator = void 0;
486
+ var init_plugin_validator = __esm({
487
+ "src/plugin-validator.ts"() {
488
+ exports.PluginValidator = class {
489
+ constructor() {
490
+ /** 内置验证规则列表 */
491
+ this.rules = [];
492
+ /** 已知插件名称集合(用于跨插件验证) */
493
+ this.knownPlugins = /* @__PURE__ */ new Set();
494
+ this.rules = [
495
+ this.validateStructure.bind(this),
496
+ this.validateName.bind(this),
497
+ this.validateVersion.bind(this),
498
+ this.validateDependencies.bind(this),
499
+ this.validateConflicts.bind(this),
500
+ this.validatePeerRequirements.bind(this),
501
+ this.validateLifecycleHooks.bind(this)
502
+ ];
503
+ }
504
+ /**
505
+ * 验证插件
506
+ * @param plugin - 要验证的插件
507
+ * @returns 验证报告
508
+ */
509
+ validate(plugin) {
510
+ const pluginName = this.getPluginName(plugin) ?? "anonymous";
511
+ const context = {
512
+ knownPlugins: this.knownPlugins
513
+ };
514
+ const issues = [];
515
+ for (const rule of this.rules) {
516
+ try {
517
+ const ruleIssues = rule(plugin, context);
518
+ issues.push(...ruleIssues);
519
+ } catch (err) {
520
+ issues.push({
521
+ level: "error",
522
+ rule: "rule-execution",
523
+ message: `Validation rule execution failed: ${err instanceof Error ? err.message : String(err)}`
524
+ });
525
+ }
526
+ }
527
+ const errorCount = issues.filter((i) => i.level === "error").length;
528
+ const warningCount = issues.filter((i) => i.level === "warning").length;
529
+ const infoCount = issues.filter((i) => i.level === "info").length;
530
+ return {
531
+ valid: errorCount === 0,
532
+ pluginName,
533
+ issues,
534
+ errorCount,
535
+ warningCount,
536
+ infoCount
537
+ };
538
+ }
539
+ /**
540
+ * 批量验证多个插件
541
+ * @param plugins - 要验证的插件列表
542
+ * @returns 验证报告列表
543
+ */
544
+ validateAll(plugins) {
545
+ return plugins.map((plugin) => this.validate(plugin));
546
+ }
547
+ /**
548
+ * 注册已知插件名称(用于跨插件验证)
549
+ * @param names - 插件名称列表
550
+ */
551
+ registerKnownPlugins(names) {
552
+ for (const name of names) {
553
+ this.knownPlugins.add(name);
554
+ }
555
+ }
556
+ /**
557
+ * 添加自定义验证规则
558
+ * @param rule - 验证规则函数
559
+ */
560
+ addRule(rule) {
561
+ this.rules.push(rule);
562
+ }
563
+ /**
564
+ * 移除验证规则
565
+ * @param rule - 要移除的验证规则函数
566
+ */
567
+ removeRule(rule) {
568
+ const index = this.rules.indexOf(rule);
569
+ if (index !== -1) {
570
+ this.rules.splice(index, 1);
571
+ }
572
+ }
573
+ // ==================== 内置验证规则 ====================
574
+ /**
575
+ * 规则:验证插件基本结构
576
+ * @description 确保插件有 install 方法
577
+ */
578
+ validateStructure(plugin) {
579
+ const issues = [];
580
+ if (!plugin || typeof plugin !== "object") {
581
+ issues.push({
582
+ level: "error",
583
+ rule: "validate-structure",
584
+ message: "Plugin must be an object."
585
+ });
586
+ return issues;
587
+ }
588
+ if (typeof plugin.install !== "function") {
589
+ issues.push({
590
+ level: "error",
591
+ rule: "validate-structure",
592
+ message: 'Plugin must have an "install" method that is a function.'
593
+ });
594
+ }
595
+ return issues;
596
+ }
597
+ /**
598
+ * 规则:验证插件名称
599
+ * @description 确保名称有效且不冲突
600
+ */
601
+ validateName(plugin) {
602
+ const issues = [];
603
+ if (!plugin || typeof plugin !== "object") {
604
+ return issues;
605
+ }
606
+ const name = this.getPluginName(plugin);
607
+ if (name === void 0) {
608
+ issues.push({
609
+ level: "warning",
610
+ rule: "validate-name",
611
+ message: 'Plugin has no name. It is recommended to use EnhancedPlugin with a "name" property for better debugging and dependency management.'
612
+ });
613
+ return issues;
614
+ }
615
+ if (typeof name !== "string") {
616
+ issues.push({
617
+ level: "error",
618
+ rule: "validate-name",
619
+ message: `Plugin name must be a string, got ${typeof name}.`
620
+ });
621
+ return issues;
622
+ }
623
+ if (name.trim().length === 0) {
624
+ issues.push({
625
+ level: "error",
626
+ rule: "validate-name",
627
+ message: "Plugin name must not be empty."
628
+ });
629
+ return issues;
630
+ }
631
+ const validNamePattern = /^[a-z][a-z0-9-]*$/;
632
+ if (!validNamePattern.test(name)) {
633
+ issues.push({
634
+ level: "warning",
635
+ rule: "validate-name",
636
+ message: `Plugin name "${name}" does not follow kebab-case convention (e.g., "my-plugin").`
637
+ });
638
+ }
639
+ if (name.length > 100) {
640
+ issues.push({
641
+ level: "warning",
642
+ rule: "validate-name",
643
+ message: `Plugin name "${name}" is too long (max 100 characters).`
644
+ });
645
+ }
646
+ return issues;
647
+ }
648
+ /**
649
+ * 规则:验证版本号格式
650
+ * @description 确保版本号符合 semver 格式
651
+ */
652
+ validateVersion(plugin) {
653
+ const issues = [];
654
+ if (!this.isEnhancedPlugin(plugin)) {
655
+ return issues;
656
+ }
657
+ if (plugin.version !== void 0) {
658
+ if (typeof plugin.version !== "string") {
659
+ issues.push({
660
+ level: "error",
661
+ rule: "validate-version",
662
+ message: `Plugin version must be a string, got ${typeof plugin.version}.`
663
+ });
664
+ } else {
665
+ const semverPattern = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$/;
666
+ if (!semverPattern.test(plugin.version)) {
667
+ issues.push({
668
+ level: "warning",
669
+ rule: "validate-version",
670
+ message: `Plugin version "${plugin.version}" does not follow semver format (e.g., "1.0.0").`
671
+ });
672
+ }
673
+ }
674
+ } else {
675
+ issues.push({
676
+ level: "info",
677
+ rule: "validate-version",
678
+ message: "Plugin has no version. It is recommended to provide a version for compatibility checks."
679
+ });
680
+ }
681
+ return issues;
682
+ }
683
+ /**
684
+ * 规则:验证依赖声明
685
+ * @description 检查依赖格式和已知性
686
+ */
687
+ validateDependencies(plugin) {
688
+ const issues = [];
689
+ if (!this.isEnhancedPlugin(plugin)) {
690
+ return issues;
691
+ }
692
+ if (plugin.dependencies) {
693
+ if (!Array.isArray(plugin.dependencies)) {
694
+ issues.push({
695
+ level: "error",
696
+ rule: "validate-dependencies",
697
+ message: 'Plugin "dependencies" must be an array.'
698
+ });
699
+ } else {
700
+ issues.push(...this.validateDependencyArray(plugin.dependencies, "dependencies", false));
701
+ }
702
+ }
703
+ if (plugin.optionalDependencies) {
704
+ if (!Array.isArray(plugin.optionalDependencies)) {
705
+ issues.push({
706
+ level: "error",
707
+ rule: "validate-dependencies",
708
+ message: 'Plugin "optionalDependencies" must be an array.'
709
+ });
710
+ } else {
711
+ issues.push(
712
+ ...this.validateDependencyArray(
713
+ plugin.optionalDependencies,
714
+ "optionalDependencies",
715
+ true
716
+ )
717
+ );
718
+ }
719
+ }
720
+ if (plugin.dependencies && plugin.name) {
721
+ for (const dep of plugin.dependencies) {
722
+ if (dep.name === plugin.name) {
723
+ issues.push({
724
+ level: "error",
725
+ rule: "validate-dependencies",
726
+ message: `Plugin "${plugin.name}" cannot depend on itself.`
727
+ });
728
+ }
729
+ }
730
+ }
731
+ return issues;
732
+ }
733
+ /**
734
+ * 验证依赖数组
735
+ */
736
+ validateDependencyArray(deps, field, isOptional) {
737
+ const issues = [];
738
+ const seenNames = /* @__PURE__ */ new Set();
739
+ for (const dep of deps) {
740
+ if (!dep.name || typeof dep.name !== "string") {
741
+ issues.push({
742
+ level: "error",
743
+ rule: "validate-dependencies",
744
+ message: `Each dependency in "${field}" must have a valid "name" string.`
745
+ });
746
+ continue;
747
+ }
748
+ if (seenNames.has(dep.name)) {
749
+ issues.push({
750
+ level: "warning",
751
+ rule: "validate-dependencies",
752
+ message: `Duplicate dependency "${dep.name}" in "${field}".`
753
+ });
754
+ }
755
+ seenNames.add(dep.name);
756
+ if (dep.version !== void 0 && typeof dep.version !== "string") {
757
+ issues.push({
758
+ level: "error",
759
+ rule: "validate-dependencies",
760
+ message: `Dependency "${dep.name}" version must be a string.`
761
+ });
762
+ }
763
+ if (dep.optional && !isOptional) {
764
+ issues.push({
765
+ level: "info",
766
+ rule: "validate-dependencies",
767
+ message: `Dependency "${dep.name}" has "optional: true" but is in required "${field}". Consider moving it to "optionalDependencies".`
768
+ });
769
+ }
770
+ }
771
+ return issues;
772
+ }
773
+ /**
774
+ * 规则:验证冲突声明
775
+ * @description 检查冲突列表格式
776
+ */
777
+ validateConflicts(plugin) {
778
+ const issues = [];
779
+ if (!this.isEnhancedPlugin(plugin)) {
780
+ return issues;
781
+ }
782
+ if (plugin.conflicts) {
783
+ if (!Array.isArray(plugin.conflicts)) {
784
+ issues.push({
785
+ level: "error",
786
+ rule: "validate-conflicts",
787
+ message: 'Plugin "conflicts" must be an array of plugin name strings.'
788
+ });
789
+ } else {
790
+ for (const conflict of plugin.conflicts) {
791
+ if (typeof conflict !== "string") {
792
+ issues.push({
793
+ level: "error",
794
+ rule: "validate-conflicts",
795
+ message: `Each conflict entry must be a string, got ${typeof conflict}.`
796
+ });
797
+ }
798
+ }
799
+ if (plugin.name && plugin.conflicts.includes(plugin.name)) {
800
+ issues.push({
801
+ level: "error",
802
+ rule: "validate-conflicts",
803
+ message: `Plugin "${plugin.name}" cannot conflict with itself.`
804
+ });
805
+ }
806
+ }
807
+ }
808
+ return issues;
809
+ }
810
+ /**
811
+ * 规则:验证 peerRequirements
812
+ * @description 检查宿主框架版本要求格式
813
+ */
814
+ validatePeerRequirements(plugin) {
815
+ const issues = [];
816
+ if (!this.isEnhancedPlugin(plugin)) {
817
+ return issues;
818
+ }
819
+ if (plugin.peerRequirements) {
820
+ if (typeof plugin.peerRequirements !== "object" || plugin.peerRequirements === null) {
821
+ issues.push({
822
+ level: "error",
823
+ rule: "validate-peer-requirements",
824
+ message: 'Plugin "peerRequirements" must be an object.'
825
+ });
826
+ return issues;
827
+ }
828
+ const { lytjs, node } = plugin.peerRequirements;
829
+ if (lytjs !== void 0 && typeof lytjs !== "string") {
830
+ issues.push({
831
+ level: "error",
832
+ rule: "validate-peer-requirements",
833
+ message: "peerRequirements.lytjs must be a version range string."
834
+ });
835
+ }
836
+ if (node !== void 0 && typeof node !== "string") {
837
+ issues.push({
838
+ level: "error",
839
+ rule: "validate-peer-requirements",
840
+ message: "peerRequirements.node must be a version range string."
841
+ });
842
+ }
843
+ }
844
+ return issues;
845
+ }
846
+ /**
847
+ * 规则:验证生命周期钩子
848
+ * @description 确保生命周期钩子是函数
849
+ */
850
+ validateLifecycleHooks(plugin) {
851
+ const issues = [];
852
+ if (!this.isEnhancedPlugin(plugin)) {
853
+ return issues;
854
+ }
855
+ const hooks = [
856
+ { name: "beforeInstall", value: plugin.beforeInstall },
857
+ { name: "afterInstall", value: plugin.afterInstall },
858
+ { name: "beforeMount", value: plugin.beforeMount },
859
+ { name: "afterMount", value: plugin.afterMount },
860
+ { name: "cleanup", value: plugin.cleanup }
861
+ ];
862
+ for (const hook of hooks) {
863
+ if (hook.value !== void 0 && typeof hook.value !== "function") {
864
+ issues.push({
865
+ level: "error",
866
+ rule: "validate-lifecycle-hooks",
867
+ message: `Plugin lifecycle hook "${hook.name}" must be a function, got ${typeof hook.value}.`
868
+ });
869
+ }
870
+ }
871
+ return issues;
872
+ }
873
+ // ==================== 工具方法 ====================
874
+ /**
875
+ * 获取插件名称
876
+ */
877
+ getPluginName(plugin) {
878
+ if (this.isEnhancedPlugin(plugin)) {
879
+ return plugin.name;
880
+ }
881
+ if (plugin == null || typeof plugin !== "object") {
882
+ return void 0;
883
+ }
884
+ const rawName = plugin.name;
885
+ return typeof rawName === "string" ? rawName : void 0;
886
+ }
887
+ /**
888
+ * 检查是否为 EnhancedPlugin
889
+ */
890
+ isEnhancedPlugin(plugin) {
891
+ return plugin != null && typeof plugin === "object" && "name" in plugin && typeof plugin.name === "string";
892
+ }
893
+ };
894
+ }
895
+ });
896
+ async function getSignalRenderer() {
897
+ if (!createSignalRenderer) {
898
+ const renderer = await import('@lytjs/renderer');
899
+ createSignalRenderer = renderer.createSignalRenderer;
900
+ }
901
+ return createSignalRenderer;
902
+ }
903
+ async function getDOMRenderer() {
904
+ if (!createDOMRenderer) {
905
+ const renderer = await import('@lytjs/renderer');
906
+ createDOMRenderer = renderer.createDOMRenderer;
907
+ }
908
+ return createDOMRenderer;
909
+ }
910
+ function createApp(rootComponent, rootProps = null, options) {
911
+ const context = createAppContext();
912
+ const installedPlugins = /* @__PURE__ */ new Set();
913
+ const pluginRegistry = new exports.PluginRegistry();
914
+ const pluginValidator = new exports.PluginValidator();
915
+ let _isUnmounted = false;
916
+ const _globalListeners = [];
917
+ const rendererMode = options?.rendererMode ?? "vnode";
918
+ const effectiveMode = rendererMode === "vapor" ? "signal" : rendererMode;
919
+ let signalRenderer = null;
920
+ const app = {
921
+ config: createContextConfig(context),
922
+ use(plugin, ...options2) {
923
+ if (installedPlugins.has(plugin)) return app;
924
+ try {
925
+ if (typeof plugin !== "function" && "name" in plugin && typeof plugin.name === "string") {
926
+ const enhancedPlugin = plugin;
927
+ const report = pluginValidator.validate(enhancedPlugin);
928
+ if (!report.valid) {
929
+ const errorMessages = report.issues.filter((i) => i.level === "error").map((i) => `[${i.rule}] ${i.message}`).join("; ");
930
+ throw new Error(`Plugin "${enhancedPlugin.name}" validation failed: ${errorMessages}`);
931
+ }
932
+ const regResult = pluginRegistry.register(enhancedPlugin, options2);
933
+ if (!regResult.success) {
934
+ throw new Error(regResult.error);
935
+ }
936
+ const depResult = pluginRegistry.checkDependencies(enhancedPlugin);
937
+ if (!depResult.satisfied && depResult.missing.length > 0) {
938
+ const missingNames = depResult.missing.map((d) => d.name).join(", ");
939
+ throw new Error(
940
+ `Plugin "${enhancedPlugin.name}" has unsatisfied dependencies: ${missingNames}`
941
+ );
942
+ }
943
+ if (enhancedPlugin.beforeInstall) {
944
+ const shouldContinue = enhancedPlugin.beforeInstall(app);
945
+ if (shouldContinue instanceof Promise) {
946
+ throw new Error(
947
+ "Plugin beforeInstall hook cannot be async when using synchronous app.use(). Use await app.use() for async plugins."
948
+ );
949
+ }
950
+ if (shouldContinue === false) {
951
+ pluginRegistry.unregister(enhancedPlugin.name);
952
+ return app;
953
+ }
954
+ }
955
+ plugin.install(app, ...options2);
956
+ pluginRegistry.markInstalled(enhancedPlugin.name);
957
+ if (enhancedPlugin.afterInstall) {
958
+ enhancedPlugin.afterInstall(app);
959
+ }
960
+ } else {
961
+ if (typeof plugin === "function") {
962
+ plugin(app, ...options2);
963
+ } else {
964
+ plugin.install(app, ...options2);
965
+ }
966
+ }
967
+ installedPlugins.add(plugin);
968
+ } catch (err) {
969
+ commonError.error(
970
+ `Plugin failed to install: ${typeof plugin === "function" ? plugin.name || "anonymous function" : plugin.install?.name || "plugin"}: ${err}`
971
+ );
972
+ throw err;
973
+ }
974
+ return app;
975
+ },
976
+ /**
977
+ * 获取插件注册表实例
978
+ * @description 提供对 PluginRegistry 的访问,用于高级插件管理
979
+ */
980
+ get _pluginRegistry() {
981
+ return pluginRegistry;
982
+ },
983
+ /**
984
+ * 获取插件验证器实例
985
+ * @description 提供对 PluginValidator 的访问,用于自定义验证
986
+ */
987
+ get _pluginValidator() {
988
+ return pluginValidator;
989
+ },
990
+ async mount(rootContainer) {
991
+ if (_isUnmounted) {
992
+ throw new Error(
993
+ `[LytJS] App has been unmounted and cannot be remounted. Create a new app instance instead.`
994
+ );
995
+ }
996
+ if (!rootComponent) {
997
+ return null;
998
+ }
999
+ if (context._container) {
1000
+ throw new Error(
1001
+ `[LytJS] App is already mounted. Call app.unmount() first before mounting again.`
1002
+ );
1003
+ }
1004
+ const container = typeof rootContainer === "string" ? document.querySelector(rootContainer) : rootContainer;
1005
+ if (!container) {
1006
+ throw new Error(
1007
+ `[LytJS] Failed to mount app: cannot find element matching selector "${rootContainer}". Make sure the target element exists in the DOM before calling app.mount().`
1008
+ );
1009
+ }
1010
+ context._container = container;
1011
+ try {
1012
+ if (effectiveMode === "signal") {
1013
+ return mountWithSignalMode(container);
1014
+ }
1015
+ return await mountWithVNodeMode(container);
1016
+ } catch (err) {
1017
+ if (app.errorHandler) {
1018
+ app.errorHandler(err, null, "mount");
1019
+ } else {
1020
+ commonError.error(`[LytJS] Failed to mount app: ${err instanceof Error ? err.message : String(err)}`);
1021
+ }
1022
+ throw err;
1023
+ }
1024
+ },
1025
+ unmount() {
1026
+ for (const listener of _globalListeners) {
1027
+ try {
1028
+ listener.target.removeEventListener(listener.event, listener.handler, listener.options);
1029
+ } catch (err) {
1030
+ }
1031
+ }
1032
+ _globalListeners.length = 0;
1033
+ for (const plugin of installedPlugins) {
1034
+ const pluginWithCleanup = plugin;
1035
+ if (typeof pluginWithCleanup?.cleanup === "function") {
1036
+ try {
1037
+ pluginWithCleanup.cleanup();
1038
+ } catch (err) {
1039
+ const pluginName = pluginWithCleanup.name ?? (typeof plugin === "function" ? plugin.name : "unknown");
1040
+ commonError.error(
1041
+ `Plugin cleanup failed for "${pluginName}": ${err instanceof Error ? err.message : String(err)}. This may cause memory leaks.`
1042
+ );
1043
+ }
1044
+ }
1045
+ }
1046
+ installedPlugins.clear();
1047
+ if (effectiveMode === "signal") {
1048
+ const componentOptions = rootComponent;
1049
+ if (componentOptions != null && typeof componentOptions === "object") {
1050
+ const beforeUnmount = componentOptions.beforeUnmount;
1051
+ if (typeof beforeUnmount === "function") {
1052
+ beforeUnmount.call(componentOptions);
1053
+ }
1054
+ }
1055
+ if (signalRenderer) {
1056
+ signalRenderer.unmount();
1057
+ signalRenderer = null;
1058
+ }
1059
+ if (context._container) {
1060
+ const container = context._container;
1061
+ while (container.firstChild) {
1062
+ container.removeChild(container.firstChild);
1063
+ }
1064
+ }
1065
+ const unmounted = componentOptions.unmounted;
1066
+ if (typeof unmounted === "function") {
1067
+ unmounted.call(componentOptions);
1068
+ }
1069
+ } else {
1070
+ if (!context.renderer || !context._vnode) return;
1071
+ const instance = context._instance;
1072
+ if (instance) {
1073
+ component.callUnmountedHook(instance);
1074
+ }
1075
+ context.renderer.unmount(context._vnode);
1076
+ context._vnode = null;
1077
+ }
1078
+ _isUnmounted = true;
1079
+ context._container = null;
1080
+ context.mixins.length = 0;
1081
+ context.components = {};
1082
+ context.directives = {};
1083
+ context.provides = {};
1084
+ context.config.globalProperties = {};
1085
+ context._instance = null;
1086
+ context.renderer = null;
1087
+ },
1088
+ provide(key, value) {
1089
+ context.provides[key] = value;
1090
+ return app;
1091
+ },
1092
+ inject(key) {
1093
+ return context.provides[key];
1094
+ },
1095
+ component(name, component) {
1096
+ if (component != null && typeof component !== "object" && typeof component !== "function") {
1097
+ return app;
1098
+ }
1099
+ context.components[name] = component;
1100
+ return app;
1101
+ },
1102
+ directive(name, directive) {
1103
+ context.directives[name] = directive;
1104
+ return app;
1105
+ },
1106
+ mixin(mixin) {
1107
+ context.mixins.push(mixin);
1108
+ return app;
1109
+ },
1110
+ /**
1111
+ * Register a global event listener that will be automatically cleaned up on unmount.
1112
+ * This ensures no leaked event listeners when the app is destroyed.
1113
+ */
1114
+ on(target, event, handler, options2) {
1115
+ target.addEventListener(event, handler, options2);
1116
+ _globalListeners.push({ target, event, handler, options: options2 });
1117
+ return app;
1118
+ },
1119
+ /**
1120
+ * Remove a previously registered global event listener.
1121
+ * FIX: P2-v11-06 off() 使用引用相等性匹配 handler,
1122
+ * 这意味着传入的 handler 必须与 on() 注册时使用同一个函数引用。
1123
+ * 如果使用匿名函数或箭头函数,将无法匹配。请保存函数引用后再传入。
1124
+ */
1125
+ off(target, event, handler, options2) {
1126
+ target.removeEventListener(event, handler, options2);
1127
+ const idx = _globalListeners.findIndex(
1128
+ (l) => l.target === target && l.event === event && l.handler === handler
1129
+ );
1130
+ if (idx !== -1) {
1131
+ _globalListeners.splice(idx, 1);
1132
+ }
1133
+ return app;
1134
+ }
1135
+ };
1136
+ async function mountWithVNodeMode(container) {
1137
+ const rootVNode = vdom.createVNode(rootComponent, rootProps);
1138
+ const instance = component.createComponentInstance(rootVNode, null);
1139
+ instance.appContext = context;
1140
+ if (context.provides) {
1141
+ const rootProvides = instance.provides;
1142
+ for (const key of Object.keys(context.provides)) {
1143
+ if (!(key in rootProvides)) {
1144
+ rootProvides[key] = context.provides[key];
1145
+ }
1146
+ }
1147
+ }
1148
+ component.setupComponent(instance);
1149
+ rootVNode.component = instance;
1150
+ context._instance = instance;
1151
+ if (effectiveMode !== "vnode") {
1152
+ throw new Error("[LytJS] Invalid renderer mode");
1153
+ }
1154
+ const domRendererFn = await getDOMRenderer();
1155
+ const renderer = domRendererFn({
1156
+ setupChildComponent(childVNode, parentComponent) {
1157
+ const childInstance = component.createComponentInstance(childVNode, parentComponent);
1158
+ if (parentComponent) {
1159
+ childInstance.appContext = parentComponent.appContext;
1160
+ } else {
1161
+ childInstance.appContext = context;
1162
+ }
1163
+ component.setupComponent(childInstance);
1164
+ childVNode.component = childInstance;
1165
+ },
1166
+ normalizeProps(inst, rawProps) {
1167
+ component.initProps(inst, rawProps);
1168
+ }
1169
+ });
1170
+ context.renderer = renderer;
1171
+ context._vnode = rootVNode;
1172
+ renderer.mount(rootVNode, container);
1173
+ const publicInstance = component.createComponentPublicInstance(instance);
1174
+ return publicInstance;
1175
+ }
1176
+ async function mountWithSignalMode(container) {
1177
+ if (!rootComponent || typeof rootComponent !== "object") {
1178
+ throw new Error(
1179
+ `[LytJS] Signal mode requires rootComponent to be a valid component options object.`
1180
+ );
1181
+ }
1182
+ const componentOptions = rootComponent;
1183
+ const template = componentOptions.template;
1184
+ if (!template) {
1185
+ throw new Error(
1186
+ `[LytJS] Signal mode requires a template string in the root component. Provide a 'template' property in your component options.`
1187
+ );
1188
+ }
1189
+ const ctx = { ...rootProps };
1190
+ if (typeof componentOptions.data === "function") {
1191
+ try {
1192
+ const dataResult = componentOptions.data();
1193
+ Object.assign(ctx, dataResult);
1194
+ } catch (e) {
1195
+ const enhancedError = new Error(
1196
+ `[LytJS] Failed to execute data() in Signal mode: ${e instanceof Error ? e.message : String(e)}. Component: ${rootComponent.name ?? "anonymous"}`
1197
+ );
1198
+ enhancedError.cause = e;
1199
+ commonError.error(enhancedError.message);
1200
+ throw enhancedError;
1201
+ }
1202
+ }
1203
+ if (typeof componentOptions.setup === "function") {
1204
+ try {
1205
+ const setupResult = componentOptions.setup(rootProps ?? {}, {});
1206
+ if (setupResult && typeof setupResult === "object") {
1207
+ Object.assign(ctx, setupResult);
1208
+ }
1209
+ } catch (e) {
1210
+ const enhancedError = new Error(
1211
+ `[LytJS] Failed to execute setup() in Signal mode: ${e instanceof Error ? e.message : String(e)}. Component: ${rootComponent.name ?? "anonymous"}`
1212
+ );
1213
+ enhancedError.cause = e;
1214
+ commonError.error(enhancedError.message);
1215
+ throw enhancedError;
1216
+ }
1217
+ }
1218
+ const beforeMount = componentOptions.beforeMount;
1219
+ if (typeof beforeMount === "function") {
1220
+ beforeMount.call(ctx);
1221
+ }
1222
+ const signalRendererFn = await getSignalRenderer();
1223
+ signalRenderer = await signalRendererFn(template, ctx);
1224
+ signalRenderer.render(container);
1225
+ const mounted = componentOptions.mounted;
1226
+ if (typeof mounted === "function") {
1227
+ mounted.call(ctx);
1228
+ }
1229
+ return new Proxy({}, {
1230
+ get(_, key) {
1231
+ if (key === "$el") return container;
1232
+ if (key === "$options") return componentOptions;
1233
+ return ctx[key];
1234
+ },
1235
+ set(_, key, value) {
1236
+ ctx[key] = value;
1237
+ return true;
1238
+ }
1239
+ });
1240
+ }
1241
+ return app;
1242
+ }
1243
+ var createSignalRenderer, createDOMRenderer;
1244
+ var init_create_app = __esm({
1245
+ "src/create-app.ts"() {
1246
+ init_app_context();
1247
+ init_plugin_registry();
1248
+ init_plugin_validator();
1249
+ createSignalRenderer = null;
1250
+ createDOMRenderer = null;
1251
+ }
1252
+ });
1253
+ function h(type, props, ...children) {
1254
+ if (props == null) {
1255
+ props = vdom.EMPTY_OBJ;
1256
+ }
1257
+ const flatChildren = children.length > 1 ? children.flat(Infinity) : Array.isArray(children[0]) ? children[0].flat(Infinity) : children[0];
1258
+ return vdom.createVNode(type, props, flatChildren);
1259
+ }
1260
+ var init_h = __esm({
1261
+ "src/h.ts"() {
1262
+ }
1263
+ });
1264
+ function defineAsyncComponent(source) {
1265
+ if (typeof source === "function") {
1266
+ source = { loader: source };
1267
+ }
1268
+ const { loader, loadingComponent, errorComponent, delay = 200, timeout, onError } = source;
1269
+ const loadedComponent = reactivity.shallowRef(void 0);
1270
+ const error3 = reactivity.ref(void 0);
1271
+ const loading = reactivity.ref(false);
1272
+ let retries = 0;
1273
+ let showLoading = false;
1274
+ let delayTimer = null;
1275
+ let loadingPromise = null;
1276
+ const MAX_RETRIES = 3;
1277
+ const retry = () => {
1278
+ if (retries >= MAX_RETRIES) {
1279
+ error3.value = new Error(
1280
+ `[lytjs/core] AsyncComponent: max retries (${MAX_RETRIES}) exceeded.`
1281
+ );
1282
+ return Promise.reject(error3.value);
1283
+ }
1284
+ retries++;
1285
+ loadedComponent.value = void 0;
1286
+ error3.value = void 0;
1287
+ loadingPromise = null;
1288
+ startTimeout();
1289
+ return load();
1290
+ };
1291
+ const load = () => {
1292
+ if (loadingPromise) return loadingPromise;
1293
+ loading.value = true;
1294
+ showLoading = false;
1295
+ if (delayTimer) clearTimeout(delayTimer);
1296
+ delayTimer = setTimeout(() => {
1297
+ showLoading = true;
1298
+ }, delay);
1299
+ return loadingPromise = Promise.resolve(loader()).then((comp2) => {
1300
+ if (comp2 == null || typeof comp2 !== "object" && typeof comp2 !== "function") {
1301
+ throw new Error(
1302
+ `[lytjs/core] AsyncComponent: loader() returned an invalid component value: ${String(comp2)}. Expected a component options object or function.`
1303
+ );
1304
+ }
1305
+ loadedComponent.value = comp2;
1306
+ error3.value = void 0;
1307
+ loading.value = false;
1308
+ loadingPromise = null;
1309
+ if (delayTimer) {
1310
+ clearTimeout(delayTimer);
1311
+ delayTimer = null;
1312
+ }
1313
+ showLoading = false;
1314
+ if (timeoutId !== null) {
1315
+ clearTimeout(timeoutId);
1316
+ timeoutId = null;
1317
+ }
1318
+ return comp2;
1319
+ }).catch((err) => {
1320
+ error3.value = err;
1321
+ loading.value = false;
1322
+ if (onError) {
1323
+ return new Promise((resolve, reject) => {
1324
+ let settled = false;
1325
+ const ON_ERROR_TIMEOUT = DEFAULT_ON_ERROR_TIMEOUT;
1326
+ const timer = setTimeout(() => {
1327
+ if (!settled) {
1328
+ settled = true;
1329
+ reject(
1330
+ new Error(
1331
+ `[lytjs/core] AsyncComponent: onError callback did not call retry() or reject() within ${ON_ERROR_TIMEOUT / 1e3}s.`
1332
+ )
1333
+ );
1334
+ }
1335
+ }, ON_ERROR_TIMEOUT);
1336
+ onError(
1337
+ err,
1338
+ () => {
1339
+ if (!settled) {
1340
+ settled = true;
1341
+ clearTimeout(timer);
1342
+ const result = retry();
1343
+ if (result) resolve(result);
1344
+ }
1345
+ },
1346
+ (reason) => {
1347
+ if (!settled) {
1348
+ settled = true;
1349
+ clearTimeout(timer);
1350
+ reject(reason ?? err);
1351
+ }
1352
+ },
1353
+ retries
1354
+ );
1355
+ });
1356
+ }
1357
+ return Promise.reject(err);
1358
+ });
1359
+ };
1360
+ let timeoutId = null;
1361
+ const startTimeout = () => {
1362
+ if (timeout == null) return;
1363
+ if (timeoutId !== null) {
1364
+ clearTimeout(timeoutId);
1365
+ }
1366
+ timeoutId = setTimeout(() => {
1367
+ if (!loadedComponent.value && !error3.value) {
1368
+ error3.value = new Error(`[lytjs/core] AsyncComponent timed out after ${timeout}ms.`);
1369
+ loading.value = false;
1370
+ }
1371
+ }, timeout);
1372
+ };
1373
+ startTimeout();
1374
+ const comp = {
1375
+ name: "AsyncComponent",
1376
+ setup() {
1377
+ const instance = {
1378
+ resolved: loadedComponent,
1379
+ loading,
1380
+ error: error3,
1381
+ delay,
1382
+ timeout
1383
+ };
1384
+ component.onBeforeUnmount(() => {
1385
+ if (timeoutId !== null) {
1386
+ clearTimeout(timeoutId);
1387
+ timeoutId = null;
1388
+ }
1389
+ if (delayTimer !== null) {
1390
+ clearTimeout(delayTimer);
1391
+ delayTimer = null;
1392
+ }
1393
+ });
1394
+ if (!loadedComponent.value && !error3.value && !loading.value) {
1395
+ load();
1396
+ }
1397
+ return instance;
1398
+ },
1399
+ render() {
1400
+ if (loadedComponent.value) {
1401
+ return h(loadedComponent.value);
1402
+ }
1403
+ if (error3.value && errorComponent) {
1404
+ return h(errorComponent);
1405
+ }
1406
+ if (showLoading && loadingComponent) {
1407
+ return h(loadingComponent);
1408
+ }
1409
+ return null;
1410
+ }
1411
+ };
1412
+ return comp;
1413
+ }
1414
+ var DEFAULT_ON_ERROR_TIMEOUT; exports.defineComponent = void 0;
1415
+ var init_define_component = __esm({
1416
+ "src/define-component.ts"() {
1417
+ init_h();
1418
+ DEFAULT_ON_ERROR_TIMEOUT = 3e4;
1419
+ exports.defineComponent = component.defineComponent;
1420
+ }
1421
+ });
1422
+ var init_next_tick = __esm({
1423
+ "src/next-tick.ts"() {
1424
+ }
1425
+ });
1426
+ function resolveComponent(name) {
1427
+ const instance = component.getCurrentInstance();
1428
+ if (!instance) {
1429
+ return void 0;
1430
+ }
1431
+ const components = instance.type?.components;
1432
+ if (components && components[name]) {
1433
+ return components[name];
1434
+ }
1435
+ const globalComponents = instance.appContext?.components;
1436
+ if (globalComponents && globalComponents[name]) {
1437
+ return globalComponents[name];
1438
+ }
1439
+ return void 0;
1440
+ }
1441
+ function resolveDirective(name) {
1442
+ const instance = component.getCurrentInstance();
1443
+ if (!instance) {
1444
+ return void 0;
1445
+ }
1446
+ const directives = instance.type?.directives;
1447
+ if (directives && directives[name]) {
1448
+ return directives[name];
1449
+ }
1450
+ const globalDirectives = instance.appContext?.directives;
1451
+ if (globalDirectives && globalDirectives[name]) {
1452
+ return globalDirectives[name];
1453
+ }
1454
+ return void 0;
1455
+ }
1456
+ function resolveDynamicComponent(tag) {
1457
+ if (typeof tag === "string") {
1458
+ const resolved = resolveComponent(tag);
1459
+ return resolved ?? tag;
1460
+ }
1461
+ return tag;
1462
+ }
1463
+ var init_resolve = __esm({
1464
+ "src/resolve.ts"() {
1465
+ }
1466
+ });
1467
+ function withDirectives(vnode, directives) {
1468
+ const dirVNode = vdom.cloneVNode(vnode);
1469
+ const normalizedDirectives = directives.map(
1470
+ ([dir, value, arg, modifiers]) => [
1471
+ dir,
1472
+ value,
1473
+ arg,
1474
+ modifiers || {}
1475
+ ]
1476
+ );
1477
+ dirVNode._directives = normalizedDirectives.map(
1478
+ ([dir, value, arg, modifiers]) => ({
1479
+ dir,
1480
+ value,
1481
+ arg,
1482
+ modifiers: modifiers ?? {}
1483
+ })
1484
+ );
1485
+ for (const dirEntry of dirVNode._directives) {
1486
+ const dirObj = dirEntry;
1487
+ if (dirObj.dir.deep) {
1488
+ applyDirectiveDeep(dirVNode, [
1489
+ dirObj.dir,
1490
+ dirObj.value,
1491
+ dirObj.arg,
1492
+ dirObj.modifiers
1493
+ ]);
1494
+ }
1495
+ }
1496
+ return dirVNode;
1497
+ }
1498
+ function applyDirectiveDeep(vnode, directive) {
1499
+ const children = vnode.children;
1500
+ if (!children) return;
1501
+ const visited = /* @__PURE__ */ new Set();
1502
+ visited.add(vnode);
1503
+ const childArray = commonIs.isArray(children) ? children : [children];
1504
+ for (const child of childArray) {
1505
+ if (!child || typeof child !== "object") continue;
1506
+ const childVNode = child;
1507
+ if (visited.has(childVNode)) continue;
1508
+ visited.add(childVNode);
1509
+ if (!childVNode._directives) {
1510
+ childVNode._directives = [];
1511
+ }
1512
+ childVNode._directives.push(directive);
1513
+ applyDirectiveDeep(childVNode, directive);
1514
+ }
1515
+ }
1516
+ function withMemo(memo, render, cache, index) {
1517
+ if (index < 0 || index >= cache.length) {
1518
+ const result2 = render();
1519
+ cache[index] = { memo, result: result2 };
1520
+ return result2;
1521
+ }
1522
+ const cached = cache[index];
1523
+ if (cached && isMemoSame(cached.memo, memo)) {
1524
+ return cached.result;
1525
+ }
1526
+ const result = render();
1527
+ cache[index] = { memo, result };
1528
+ return result;
1529
+ }
1530
+ function isMemoSame(prev, next) {
1531
+ if (prev.length !== next.length) return false;
1532
+ for (let i = 0; i < prev.length; i++) {
1533
+ if (prev[i] !== next[i]) return false;
1534
+ }
1535
+ return true;
1536
+ }
1537
+ var init_directives = __esm({
1538
+ "src/directives.ts"() {
1539
+ }
1540
+ });
1541
+ function useSlots() {
1542
+ const instance = component.getCurrentInstance();
1543
+ if (!instance) {
1544
+ return {};
1545
+ }
1546
+ return instance.slots || {};
1547
+ }
1548
+ function useAttrs() {
1549
+ const instance = component.getCurrentInstance();
1550
+ if (!instance) {
1551
+ return {};
1552
+ }
1553
+ return instance.attrs || {};
1554
+ }
1555
+ function useModel(props, key) {
1556
+ const instance = component.getCurrentInstance();
1557
+ if (!instance) {
1558
+ return reactivity.computed({
1559
+ get() {
1560
+ return void 0;
1561
+ },
1562
+ set() {
1563
+ }
1564
+ });
1565
+ }
1566
+ return reactivity.computed({
1567
+ get() {
1568
+ return props[key];
1569
+ },
1570
+ set(newValue) {
1571
+ instance.emit(`update:${key}`, newValue);
1572
+ }
1573
+ });
1574
+ }
1575
+ function defineModel(name, options) {
1576
+ const instance = component.getCurrentInstance();
1577
+ const modelName = name ?? "modelValue";
1578
+ if (!instance) {
1579
+ return reactivity.computed({
1580
+ get() {
1581
+ return options?.default;
1582
+ },
1583
+ set() {
1584
+ }
1585
+ });
1586
+ }
1587
+ const props = instance.props;
1588
+ return reactivity.computed({
1589
+ get() {
1590
+ const value = props[modelName];
1591
+ if (value === void 0) {
1592
+ return options?.default;
1593
+ }
1594
+ return value;
1595
+ },
1596
+ set(newValue) {
1597
+ const emitValue = options?.transform ? options.transform(newValue) : newValue;
1598
+ instance.emit(`update:${modelName}`, emitValue);
1599
+ }
1600
+ });
1601
+ }
1602
+ function useTemplateRef(key) {
1603
+ const instance = component.getCurrentInstance();
1604
+ const ref3 = reactivity.shallowRef(null);
1605
+ if (instance) {
1606
+ const stop = reactivity.watch(
1607
+ () => instance.refs[key] ?? null,
1608
+ (newVal) => {
1609
+ ref3.value = newVal;
1610
+ },
1611
+ { immediate: true, flush: "pre" }
1612
+ );
1613
+ scope.onScopeDispose(stop);
1614
+ }
1615
+ return ref3;
1616
+ }
1617
+ function generateIdSuffix() {
1618
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
1619
+ return crypto.randomUUID().slice(0, 8);
1620
+ }
1621
+ return Math.random().toString(36).slice(2, 10);
1622
+ }
1623
+ function useId() {
1624
+ const instance = component.getCurrentInstance();
1625
+ const id = reactivity.shallowRef("");
1626
+ if (instance) {
1627
+ const prefix = `lyt-${instance.uid}`;
1628
+ let map = instanceIdMap.get(instance);
1629
+ if (!map) {
1630
+ map = /* @__PURE__ */ new Map();
1631
+ instanceIdMap.set(instance, map);
1632
+ }
1633
+ const counter = (map.get("useId") ?? 0) + 1;
1634
+ map.set("useId", counter);
1635
+ id.value = `${prefix}-${counter}-${generateIdSuffix()}`;
1636
+ } else {
1637
+ id.value = `lyt-${generateIdSuffix()}`;
1638
+ }
1639
+ return reactivity.readonly(id);
1640
+ }
1641
+ function useCssModule(name = "$style") {
1642
+ const instance = component.getCurrentInstance();
1643
+ if (!instance) {
1644
+ return {};
1645
+ }
1646
+ const modules = instanceCssModulesMap.get(instance);
1647
+ return modules?.[name] ?? {};
1648
+ }
1649
+ function useCssVars(vars) {
1650
+ const instance = component.getCurrentInstance();
1651
+ if (!instance) {
1652
+ return;
1653
+ }
1654
+ const updateStyle = () => {
1655
+ const el = instance.vnode?.el;
1656
+ if (!el) return;
1657
+ const varsObj = vars();
1658
+ for (const [key, value] of Object.entries(varsObj)) {
1659
+ const cssVar = key.startsWith("--") ? key : `--${key}`;
1660
+ el.style.setProperty(cssVar, value);
1661
+ }
1662
+ };
1663
+ component.onMounted(updateStyle);
1664
+ const stop = reactivity.watchEffect(updateStyle);
1665
+ scope.onScopeDispose(() => {
1666
+ stop();
1667
+ const el = instance.vnode?.el;
1668
+ if (el) {
1669
+ const varsObj = vars();
1670
+ for (const key of Object.keys(varsObj)) {
1671
+ const cssVar = key.startsWith("--") ? key : `--${key}`;
1672
+ el.style.removeProperty(cssVar);
1673
+ }
1674
+ }
1675
+ });
1676
+ }
1677
+ var instanceIdMap, instanceCssModulesMap;
1678
+ var init_composition = __esm({
1679
+ "src/composition.ts"() {
1680
+ instanceIdMap = /* @__PURE__ */ new WeakMap();
1681
+ instanceCssModulesMap = /* @__PURE__ */ new WeakMap();
1682
+ }
1683
+ });
1684
+ function getElementContext(host) {
1685
+ let ctx = elementContextMap.get(host);
1686
+ if (!ctx) {
1687
+ ctx = { shadowRoot: null, host, slotCallback: null };
1688
+ elementContextMap.set(host, ctx);
1689
+ }
1690
+ return ctx;
1691
+ }
1692
+ function getCurrentContext() {
1693
+ const host = setupStack[setupStack.length - 1];
1694
+ return host ? elementContextMap.get(host) : void 0;
1695
+ }
1696
+ function extractObservedAttributes(propsOptions) {
1697
+ const attributes = [];
1698
+ for (const key in propsOptions) {
1699
+ const attrName = key.replace(/([A-Z])/g, "-$1").toLowerCase();
1700
+ attributes.push(attrName);
1701
+ }
1702
+ return attributes;
1703
+ }
1704
+ function attrToProp(attrName) {
1705
+ return attrName.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1706
+ }
1707
+ function deserializeValue(value, propOptions) {
1708
+ if (value === null) return void 0;
1709
+ const options = propOptions;
1710
+ if (options === true || options === void 0) {
1711
+ return value;
1712
+ }
1713
+ const type = options.type;
1714
+ if (type === Number) {
1715
+ const num = Number(value);
1716
+ return isNaN(num) ? value : num;
1717
+ }
1718
+ if (type === Boolean) {
1719
+ return value !== "false" && value !== "0" && value !== "";
1720
+ }
1721
+ return value;
1722
+ }
1723
+ function defineCustomElement(componentOptions, options) {
1724
+ const useShadowDOM = options?.shadowRoot !== false;
1725
+ const tagName = options?.name || (componentOptions.name ? componentOptions.name.replace(/([A-Z])/g, "-$1").toLowerCase() : "lyt-component");
1726
+ const css = options?.css || "";
1727
+ const propsOptions = componentOptions.props || {};
1728
+ const observedAttributes = extractObservedAttributes(propsOptions);
1729
+ class LytCustomElement extends HTMLElement {
1730
+ constructor() {
1731
+ super();
1732
+ this._instance = null;
1733
+ this._renderer = null;
1734
+ this._vnode = null;
1735
+ this._slotObserver = null;
1736
+ if (useShadowDOM) {
1737
+ this._root = this.attachShadow({ mode: "open" });
1738
+ if (css) {
1739
+ const style = document.createElement("style");
1740
+ style.textContent = css;
1741
+ this._root.appendChild(style);
1742
+ }
1743
+ } else {
1744
+ this._root = this;
1745
+ }
1746
+ this._appContext = component.createAppContext();
1747
+ }
1748
+ static get observedAttributes() {
1749
+ return observedAttributes;
1750
+ }
1751
+ connectedCallback() {
1752
+ const ctx = getElementContext(this);
1753
+ ctx.shadowRoot = useShadowDOM ? this._root : null;
1754
+ ctx.host = this;
1755
+ setupStack.push(this);
1756
+ try {
1757
+ const props = {};
1758
+ for (const attr of observedAttributes) {
1759
+ const propKey = attrToProp(attr);
1760
+ const value = this.getAttribute(attr);
1761
+ props[propKey] = deserializeValue(value, propsOptions[propKey]);
1762
+ }
1763
+ const vnode = vdom.createVNode(componentOptions, props);
1764
+ this._vnode = vnode;
1765
+ const instance = component.createComponentInstance(vnode, null);
1766
+ instance.appContext = this._appContext;
1767
+ this._instance = instance;
1768
+ component.setupComponent(instance);
1769
+ const renderer$1 = renderer.createDOMRenderer();
1770
+ this._renderer = renderer$1;
1771
+ renderer$1.mount(vnode, this._root);
1772
+ this._setupSlotObserver();
1773
+ } finally {
1774
+ setupStack.pop();
1775
+ }
1776
+ }
1777
+ disconnectedCallback() {
1778
+ if (this._instance) {
1779
+ component.callUnmountedHook(this._instance);
1780
+ }
1781
+ if (this._renderer && this._vnode) {
1782
+ this._renderer.unmount(this._vnode);
1783
+ }
1784
+ if (this._slotObserver) {
1785
+ this._slotObserver.disconnect();
1786
+ this._slotObserver = null;
1787
+ }
1788
+ elementContextMap.delete(this);
1789
+ this._instance = null;
1790
+ this._renderer = null;
1791
+ this._vnode = null;
1792
+ }
1793
+ attributeChangedCallback(name, _oldValue, newValue) {
1794
+ if (!this._instance || !this._vnode) return;
1795
+ const propKey = attrToProp(name);
1796
+ if (!(propKey in propsOptions)) return;
1797
+ const deserializedValue = deserializeValue(newValue, propsOptions[propKey]);
1798
+ if (this._instance.props[propKey] === deserializedValue) return;
1799
+ this._instance.props[propKey] = deserializedValue;
1800
+ this._vnode.props[propKey] = deserializedValue;
1801
+ if (this._renderer && this._vnode) {
1802
+ if (this._renderer.patch) {
1803
+ const newVNode = { ...this._vnode, props: { ...this._vnode.props } };
1804
+ this._renderer.patch(this._vnode, newVNode, this._root);
1805
+ this._vnode = newVNode;
1806
+ } else if (this._renderer.render) {
1807
+ this._renderer.render(this._vnode, this._root);
1808
+ }
1809
+ }
1810
+ }
1811
+ _setupSlotObserver() {
1812
+ this._slotObserver = new MutationObserver(() => {
1813
+ const ctx = elementContextMap.get(this);
1814
+ if (ctx?.slotCallback) {
1815
+ ctx.slotCallback();
1816
+ }
1817
+ });
1818
+ this._slotObserver.observe(this, {
1819
+ childList: true,
1820
+ subtree: true,
1821
+ characterData: true
1822
+ });
1823
+ }
1824
+ }
1825
+ try {
1826
+ customElements.define(tagName, LytCustomElement);
1827
+ } catch (e) {
1828
+ }
1829
+ return LytCustomElement;
1830
+ }
1831
+ function useShadowRoot() {
1832
+ const ctx = getCurrentContext();
1833
+ return ctx?.shadowRoot ?? null;
1834
+ }
1835
+ function useHost() {
1836
+ const ctx = getCurrentContext();
1837
+ return ctx?.host ?? null;
1838
+ }
1839
+ function useWebComponentSlots(onChange) {
1840
+ const ctx = getCurrentContext();
1841
+ if (ctx) {
1842
+ ctx.slotCallback = onChange;
1843
+ }
1844
+ }
1845
+ function injectChildStyles(styles) {
1846
+ const ctx = getCurrentContext();
1847
+ const shadowRoot = ctx?.shadowRoot ?? null;
1848
+ if (!shadowRoot) {
1849
+ return;
1850
+ }
1851
+ const style = document.createElement("style");
1852
+ style.textContent = styles;
1853
+ shadowRoot.appendChild(style);
1854
+ }
1855
+ var elementContextMap, setupStack;
1856
+ var init_web_component = __esm({
1857
+ "src/web-component.ts"() {
1858
+ elementContextMap = /* @__PURE__ */ new WeakMap();
1859
+ setupStack = [];
1860
+ }
1861
+ });
1862
+ var init_lifecycle = __esm({
1863
+ "src/lifecycle.ts"() {
1864
+ }
1865
+ });
1866
+
1867
+ // src/config-validator.ts
1868
+ function validateConfig(value, schema) {
1869
+ const validator = new exports.ConfigValidator();
1870
+ return validator.validate(value, schema);
1871
+ }
1872
+ exports.ConfigValidator = void 0;
1873
+ var init_config_validator = __esm({
1874
+ "src/config-validator.ts"() {
1875
+ exports.ConfigValidator = class {
1876
+ constructor() {
1877
+ /** 自定义验证规则 */
1878
+ this.rules = [];
1879
+ }
1880
+ /**
1881
+ * 验证配置值
1882
+ * @param value - 要验证的值
1883
+ * @param schema - 配置 Schema
1884
+ * @param path - 当前路径(用于错误报告)
1885
+ * @returns 验证报告
1886
+ */
1887
+ validate(value, schema, path = "") {
1888
+ const errors = [];
1889
+ const context = { path, root: value };
1890
+ if (value === null) {
1891
+ if (!schema.nullable && schema.default === void 0) {
1892
+ errors.push(this.createError(path, "type_error", "Value cannot be null"));
1893
+ }
1894
+ return { valid: errors.length === 0, errors, errorCount: errors.length, warningCount: 0 };
1895
+ }
1896
+ if (value === void 0) {
1897
+ if (schema.required) {
1898
+ errors.push(this.createError(path, "required", "Value is required"));
1899
+ } else if (schema.default !== void 0) ;
1900
+ return { valid: errors.length === 0, errors, errorCount: errors.length, warningCount: 0 };
1901
+ }
1902
+ if (schema.validate) {
1903
+ const result = schema.validate(value, context);
1904
+ if (!result.valid) {
1905
+ errors.push(this.createError(path, "custom_error", result.message || "Custom validation failed"));
1906
+ }
1907
+ }
1908
+ switch (schema.type) {
1909
+ case "string":
1910
+ errors.push(...this.validateString(value, schema, path));
1911
+ break;
1912
+ case "number":
1913
+ errors.push(...this.validateNumber(value, schema, path));
1914
+ break;
1915
+ case "boolean":
1916
+ errors.push(...this.validateBoolean(value, schema, path));
1917
+ break;
1918
+ case "object":
1919
+ errors.push(...this.validateObject(value, schema, path));
1920
+ break;
1921
+ case "array":
1922
+ errors.push(...this.validateArray(value, schema, path));
1923
+ break;
1924
+ case "enum":
1925
+ errors.push(...this.validateEnum(value, schema, path));
1926
+ break;
1927
+ case "union":
1928
+ errors.push(...this.validateUnion(value, schema, path));
1929
+ break;
1930
+ }
1931
+ for (const rule of this.rules) {
1932
+ const error3 = rule(value, schema, context);
1933
+ if (error3) {
1934
+ errors.push(error3);
1935
+ }
1936
+ }
1937
+ return {
1938
+ valid: errors.length === 0,
1939
+ errors,
1940
+ errorCount: errors.length,
1941
+ warningCount: 0
1942
+ };
1943
+ }
1944
+ /**
1945
+ * 验证字符串值
1946
+ */
1947
+ validateString(value, schema, path) {
1948
+ const errors = [];
1949
+ if (typeof value !== "string") {
1950
+ errors.push(this.createError(path, "type_error", `Expected string, got ${typeof value}`, "string", value));
1951
+ return errors;
1952
+ }
1953
+ const stringSchema = schema.string || {};
1954
+ if (stringSchema.minLength !== void 0 && value.length < stringSchema.minLength) {
1955
+ errors.push(this.createError(
1956
+ path,
1957
+ "min_length",
1958
+ `String must be at least ${stringSchema.minLength} characters`,
1959
+ `minLength: ${stringSchema.minLength}`,
1960
+ value.length
1961
+ ));
1962
+ }
1963
+ if (stringSchema.maxLength !== void 0 && value.length > stringSchema.maxLength) {
1964
+ errors.push(this.createError(
1965
+ path,
1966
+ "max_length",
1967
+ `String must be at most ${stringSchema.maxLength} characters`,
1968
+ `maxLength: ${stringSchema.maxLength}`,
1969
+ value.length
1970
+ ));
1971
+ }
1972
+ if (stringSchema.pattern) {
1973
+ const pattern = typeof stringSchema.pattern === "string" ? new RegExp(stringSchema.pattern) : stringSchema.pattern;
1974
+ if (!pattern.test(value)) {
1975
+ errors.push(this.createError(
1976
+ path,
1977
+ "pattern_mismatch",
1978
+ `String does not match pattern: ${stringSchema.pattern}`,
1979
+ String(stringSchema.pattern),
1980
+ value
1981
+ ));
1982
+ }
1983
+ }
1984
+ if (stringSchema.format && this.isStringType(value)) {
1985
+ const formatError = this.validateFormat(value, stringSchema.format);
1986
+ if (formatError) {
1987
+ errors.push(this.createError(path, "format_error", formatError, stringSchema.format, value));
1988
+ }
1989
+ }
1990
+ if (stringSchema.enum && !stringSchema.enum.includes(value)) {
1991
+ errors.push(this.createError(
1992
+ path,
1993
+ "enum_mismatch",
1994
+ `Value must be one of: ${stringSchema.enum.join(", ")}`,
1995
+ stringSchema.enum.join(" | "),
1996
+ value
1997
+ ));
1998
+ }
1999
+ return errors;
2000
+ }
2001
+ /**
2002
+ * 验证数字值
2003
+ */
2004
+ validateNumber(value, schema, path) {
2005
+ const errors = [];
2006
+ if (typeof value !== "number" || Number.isNaN(value)) {
2007
+ errors.push(this.createError(path, "type_error", `Expected number, got ${typeof value}`, "number", value));
2008
+ return errors;
2009
+ }
2010
+ const numberSchema = schema.number || {};
2011
+ if (numberSchema.integer && !Number.isInteger(value)) {
2012
+ errors.push(this.createError(path, "type_error", "Value must be an integer", "integer", value));
2013
+ }
2014
+ if (numberSchema.minimum !== void 0 && value < numberSchema.minimum) {
2015
+ errors.push(this.createError(
2016
+ path,
2017
+ "minimum",
2018
+ `Value must be >= ${numberSchema.minimum}`,
2019
+ `minimum: ${numberSchema.minimum}`,
2020
+ value
2021
+ ));
2022
+ }
2023
+ if (numberSchema.maximum !== void 0 && value > numberSchema.maximum) {
2024
+ errors.push(this.createError(
2025
+ path,
2026
+ "maximum",
2027
+ `Value must be <= ${numberSchema.maximum}`,
2028
+ `maximum: ${numberSchema.maximum}`,
2029
+ value
2030
+ ));
2031
+ }
2032
+ if (numberSchema.exclusiveMinimum !== void 0 && value <= numberSchema.exclusiveMinimum) {
2033
+ errors.push(this.createError(
2034
+ path,
2035
+ "minimum",
2036
+ `Value must be > ${numberSchema.exclusiveMinimum}`,
2037
+ `exclusiveMinimum: ${numberSchema.exclusiveMinimum}`,
2038
+ value
2039
+ ));
2040
+ }
2041
+ if (numberSchema.exclusiveMaximum !== void 0 && value >= numberSchema.exclusiveMaximum) {
2042
+ errors.push(this.createError(
2043
+ path,
2044
+ "maximum",
2045
+ `Value must be < ${numberSchema.exclusiveMaximum}`,
2046
+ `exclusiveMaximum: ${numberSchema.exclusiveMaximum}`,
2047
+ value
2048
+ ));
2049
+ }
2050
+ if (numberSchema.enum && !numberSchema.enum.includes(value)) {
2051
+ errors.push(this.createError(
2052
+ path,
2053
+ "enum_mismatch",
2054
+ `Value must be one of: ${numberSchema.enum.join(", ")}`,
2055
+ numberSchema.enum.join(" | "),
2056
+ value
2057
+ ));
2058
+ }
2059
+ return errors;
2060
+ }
2061
+ /**
2062
+ * 验证布尔值
2063
+ */
2064
+ validateBoolean(value, _schema, path) {
2065
+ const errors = [];
2066
+ if (typeof value !== "boolean") {
2067
+ errors.push(this.createError(path, "type_error", `Expected boolean, got ${typeof value}`, "boolean", value));
2068
+ }
2069
+ return errors;
2070
+ }
2071
+ /**
2072
+ * 验证对象值
2073
+ */
2074
+ validateObject(value, schema, path) {
2075
+ const errors = [];
2076
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2077
+ errors.push(this.createError(path, "type_error", `Expected object, got ${typeof value}`, "object", value));
2078
+ return errors;
2079
+ }
2080
+ const objectSchema = schema.object;
2081
+ if (!objectSchema) return errors;
2082
+ const obj = value;
2083
+ const keys = Object.keys(obj);
2084
+ if (objectSchema.maxProperties !== void 0 && keys.length > objectSchema.maxProperties) {
2085
+ errors.push(this.createError(
2086
+ path,
2087
+ "max_items",
2088
+ `Object must have at most ${objectSchema.maxProperties} properties`,
2089
+ `maxProperties: ${objectSchema.maxProperties}`,
2090
+ keys.length
2091
+ ));
2092
+ }
2093
+ if (objectSchema.minProperties !== void 0 && keys.length < objectSchema.minProperties) {
2094
+ errors.push(this.createError(
2095
+ path,
2096
+ "min_items",
2097
+ `Object must have at least ${objectSchema.minProperties} properties`,
2098
+ `minProperties: ${objectSchema.minProperties}`,
2099
+ keys.length
2100
+ ));
2101
+ }
2102
+ for (const [key, propertySchema] of Object.entries(objectSchema.properties || {})) {
2103
+ const propertyPath = path ? `${path}.${key}` : key;
2104
+ const propertyValue = obj[key];
2105
+ if (propertyValue !== void 0) {
2106
+ const propertyReport = this.validate(propertyValue, propertySchema, propertyPath);
2107
+ errors.push(...propertyReport.errors);
2108
+ } else if (propertySchema.required) {
2109
+ errors.push(this.createError(propertyPath, "required", `Property "${key}" is required`));
2110
+ }
2111
+ }
2112
+ const definedKeys = new Set(Object.keys(objectSchema.properties || {}));
2113
+ if (!objectSchema.additionalProperties) {
2114
+ for (const key of keys) {
2115
+ if (!definedKeys.has(key)) {
2116
+ let matchesPattern = false;
2117
+ if (objectSchema.patternProperties) {
2118
+ for (const pattern of Object.keys(objectSchema.patternProperties)) {
2119
+ const regex = new RegExp(pattern);
2120
+ if (regex.test(key)) {
2121
+ matchesPattern = true;
2122
+ break;
2123
+ }
2124
+ }
2125
+ }
2126
+ if (!matchesPattern) {
2127
+ errors.push(this.createError(
2128
+ `${path}.${key}`,
2129
+ "additional_properties",
2130
+ `Additional property "${key}" is not allowed`,
2131
+ key,
2132
+ key
2133
+ ));
2134
+ }
2135
+ }
2136
+ }
2137
+ }
2138
+ return errors;
2139
+ }
2140
+ /**
2141
+ * 验证数组值
2142
+ */
2143
+ validateArray(value, schema, path) {
2144
+ const errors = [];
2145
+ if (!Array.isArray(value)) {
2146
+ errors.push(this.createError(path, "type_error", `Expected array, got ${typeof value}`, "array", value));
2147
+ return errors;
2148
+ }
2149
+ const arraySchema = schema.array || {};
2150
+ if (arraySchema.minItems !== void 0 && value.length < arraySchema.minItems) {
2151
+ errors.push(this.createError(
2152
+ path,
2153
+ "min_items",
2154
+ `Array must have at least ${arraySchema.minItems} items`,
2155
+ `minItems: ${arraySchema.minItems}`,
2156
+ value.length
2157
+ ));
2158
+ }
2159
+ if (arraySchema.maxItems !== void 0 && value.length > arraySchema.maxItems) {
2160
+ errors.push(this.createError(
2161
+ path,
2162
+ "max_items",
2163
+ `Array must have at most ${arraySchema.maxItems} items`,
2164
+ `maxItems: ${arraySchema.maxItems}`,
2165
+ value.length
2166
+ ));
2167
+ }
2168
+ if (arraySchema.uniqueItems) {
2169
+ const seen = /* @__PURE__ */ new Set();
2170
+ for (let i = 0; i < value.length; i++) {
2171
+ const item = value[i];
2172
+ const key = JSON.stringify(item);
2173
+ if (seen.has(key)) {
2174
+ errors.push(this.createError(
2175
+ `${path}[${i}]`,
2176
+ "unique_items",
2177
+ `Duplicate item found at index ${i}`,
2178
+ "uniqueItems",
2179
+ item
2180
+ ));
2181
+ }
2182
+ seen.add(key);
2183
+ }
2184
+ }
2185
+ if (arraySchema.items) {
2186
+ for (let i = 0; i < value.length; i++) {
2187
+ const itemPath = `${path}[${i}]`;
2188
+ const itemReport = this.validate(value[i], arraySchema.items, itemPath);
2189
+ errors.push(...itemReport.errors);
2190
+ }
2191
+ }
2192
+ if (arraySchema.tuple) {
2193
+ for (let i = 0; i < Math.min(value.length, arraySchema.tuple.length); i++) {
2194
+ const itemPath = `${path}[${i}]`;
2195
+ const itemReport = this.validate(value[i], arraySchema.tuple[i], itemPath);
2196
+ errors.push(...itemReport.errors);
2197
+ }
2198
+ if (value.length !== arraySchema.tuple.length) {
2199
+ errors.push(this.createError(
2200
+ path,
2201
+ "max_items",
2202
+ `Tuple must have exactly ${arraySchema.tuple.length} items, got ${value.length}`,
2203
+ `tuple length: ${arraySchema.tuple.length}`,
2204
+ value.length
2205
+ ));
2206
+ }
2207
+ }
2208
+ return errors;
2209
+ }
2210
+ /**
2211
+ * 验证枚举值
2212
+ */
2213
+ validateEnum(value, schema, path) {
2214
+ const errors = [];
2215
+ const enumSchema = schema.enum;
2216
+ if (!enumSchema.values.includes(value)) {
2217
+ errors.push(this.createError(
2218
+ path,
2219
+ "enum_mismatch",
2220
+ `Value must be one of: ${enumSchema.values.map((v) => JSON.stringify(v)).join(", ")}`,
2221
+ enumSchema.values.map((v) => JSON.stringify(v)).join(" | "),
2222
+ value
2223
+ ));
2224
+ }
2225
+ return errors;
2226
+ }
2227
+ /**
2228
+ * 验证联合类型
2229
+ */
2230
+ validateUnion(value, schema, path) {
2231
+ const errors = [];
2232
+ const unionSchema = schema.union;
2233
+ if (unionSchema.anyOf) {
2234
+ let matched = false;
2235
+ for (const subSchema of unionSchema.anyOf) {
2236
+ const report = this.validate(value, subSchema, path);
2237
+ if (report.valid) {
2238
+ matched = true;
2239
+ break;
2240
+ }
2241
+ }
2242
+ if (!matched) {
2243
+ errors.push(this.createError(
2244
+ path,
2245
+ "type_error",
2246
+ "Value does not match any of the allowed types",
2247
+ "union",
2248
+ value
2249
+ ));
2250
+ }
2251
+ }
2252
+ if (unionSchema.oneOf) {
2253
+ let matchCount = 0;
2254
+ for (const subSchema of unionSchema.oneOf) {
2255
+ const report = this.validate(value, subSchema, path);
2256
+ if (report.valid) {
2257
+ matchCount++;
2258
+ }
2259
+ }
2260
+ if (matchCount !== 1) {
2261
+ errors.push(this.createError(
2262
+ path,
2263
+ "type_error",
2264
+ `Value must match exactly one of the allowed types, matched ${matchCount}`,
2265
+ "oneOf",
2266
+ value
2267
+ ));
2268
+ }
2269
+ }
2270
+ return errors;
2271
+ }
2272
+ /**
2273
+ * 验证字符串格式
2274
+ */
2275
+ validateFormat(value, format) {
2276
+ switch (format) {
2277
+ case "date":
2278
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(value) || isNaN(Date.parse(value))) {
2279
+ return `Invalid date format, expected YYYY-MM-DD`;
2280
+ }
2281
+ return null;
2282
+ case "time":
2283
+ if (!/^\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/.test(value)) {
2284
+ return `Invalid time format`;
2285
+ }
2286
+ return null;
2287
+ case "date-time":
2288
+ if (isNaN(Date.parse(value))) {
2289
+ return `Invalid ISO 8601 date-time format`;
2290
+ }
2291
+ return null;
2292
+ case "email":
2293
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
2294
+ return `Invalid email format`;
2295
+ }
2296
+ return null;
2297
+ case "url":
2298
+ case "uri":
2299
+ try {
2300
+ new URL(value);
2301
+ return null;
2302
+ } catch {
2303
+ return `Invalid URL format`;
2304
+ }
2305
+ case "uuid":
2306
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
2307
+ return `Invalid UUID format`;
2308
+ }
2309
+ return null;
2310
+ case "semver":
2311
+ if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?(\+[a-zA-Z0-9.]+)?$/.test(value)) {
2312
+ return `Invalid semver format, expected MAJOR.MINOR.PATCH`;
2313
+ }
2314
+ return null;
2315
+ default:
2316
+ return null;
2317
+ }
2318
+ }
2319
+ /**
2320
+ * 创建验证错误
2321
+ */
2322
+ createError(path, code, message, expected, actual) {
2323
+ return { path, code, message, expected, actual };
2324
+ }
2325
+ /**
2326
+ * 添加自定义验证规则
2327
+ */
2328
+ addRule(rule) {
2329
+ this.rules.push(rule);
2330
+ }
2331
+ /**
2332
+ * 移除自定义验证规则
2333
+ */
2334
+ removeRule(rule) {
2335
+ const index = this.rules.indexOf(rule);
2336
+ if (index !== -1) {
2337
+ this.rules.splice(index, 1);
2338
+ }
2339
+ }
2340
+ // ==================== 类型守卫 ====================
2341
+ isStringType(value) {
2342
+ return typeof value === "string";
2343
+ }
2344
+ };
2345
+ }
2346
+ });
2347
+
2348
+ // src/config-transformer.ts
2349
+ function transformConfig(value, schema) {
2350
+ const transformer = new exports.ConfigTransformer();
2351
+ return transformer.transform(value, schema);
2352
+ }
2353
+ function mergeConfig(defaults, overrides, schema) {
2354
+ const transformer = new exports.ConfigTransformer();
2355
+ return transformer.merge(defaults, overrides, schema);
2356
+ }
2357
+ exports.ConfigTransformer = void 0;
2358
+ var init_config_transformer = __esm({
2359
+ "src/config-transformer.ts"() {
2360
+ init_config_validator();
2361
+ exports.ConfigTransformer = class {
2362
+ constructor() {
2363
+ this.validator = new exports.ConfigValidator();
2364
+ }
2365
+ /**
2366
+ * 转换并验证配置
2367
+ * @param value - 原始配置值
2368
+ * @param schema - 配置 Schema
2369
+ * @param path - 当前路径
2370
+ * @returns 转换报告
2371
+ */
2372
+ transform(value, schema, path = "") {
2373
+ const warnings = [];
2374
+ const transforms = [];
2375
+ const errors = [];
2376
+ let transformed = value;
2377
+ if (transformed === void 0) {
2378
+ if (schema.default !== void 0) {
2379
+ transformed = schema.default;
2380
+ transforms.push(`Applied default value: ${JSON.stringify(schema.default)}`);
2381
+ } else if (schema.required) {
2382
+ errors.push({
2383
+ path,
2384
+ code: "required",
2385
+ message: "Value is required"
2386
+ });
2387
+ return { config: void 0, success: false, errors, warnings, transforms };
2388
+ }
2389
+ }
2390
+ if (transformed === null) {
2391
+ if (schema.nullable) ; else if (schema.default !== void 0) {
2392
+ transformed = schema.default;
2393
+ transforms.push(`Applied default value for null: ${JSON.stringify(schema.default)}`);
2394
+ warnings.push("Null value was replaced with default");
2395
+ } else {
2396
+ errors.push({
2397
+ path,
2398
+ code: "type_error",
2399
+ message: "Value cannot be null"
2400
+ });
2401
+ return { config: null, success: false, errors, warnings, transforms };
2402
+ }
2403
+ }
2404
+ if (transformed !== void 0 && transformed !== null) {
2405
+ if (schema.transform) {
2406
+ try {
2407
+ const original = transformed;
2408
+ transformed = schema.transform(transformed);
2409
+ if (original !== transformed) {
2410
+ transforms.push(`Applied transform function`);
2411
+ }
2412
+ } catch (err) {
2413
+ errors.push({
2414
+ path,
2415
+ code: "custom_error",
2416
+ message: `Transform failed: ${err instanceof Error ? err.message : String(err)}`
2417
+ });
2418
+ return { config: transformed, success: false, errors, warnings, transforms };
2419
+ }
2420
+ }
2421
+ }
2422
+ if (schema.type === "object" && schema.object && typeof transformed === "object" && transformed !== null) {
2423
+ const objectResult = this.transformObject(transformed, schema, path);
2424
+ transformed = objectResult.value;
2425
+ errors.push(...objectResult.errors);
2426
+ warnings.push(...objectResult.warnings);
2427
+ transforms.push(...objectResult.transforms);
2428
+ } else if (schema.type === "array" && schema.array && Array.isArray(transformed)) {
2429
+ const arrayResult = this.transformArray(transformed, schema, path);
2430
+ transformed = arrayResult.value;
2431
+ errors.push(...arrayResult.errors);
2432
+ warnings.push(...arrayResult.warnings);
2433
+ transforms.push(...arrayResult.transforms);
2434
+ }
2435
+ if (transformed !== void 0 && transformed !== null) {
2436
+ const validationReport = this.validator.validate(transformed, schema, path);
2437
+ errors.push(...validationReport.errors);
2438
+ }
2439
+ return {
2440
+ config: transformed,
2441
+ success: errors.length === 0,
2442
+ errors,
2443
+ warnings,
2444
+ transforms
2445
+ };
2446
+ }
2447
+ /**
2448
+ * 转换对象配置
2449
+ */
2450
+ transformObject(obj, schema, path) {
2451
+ const result = {};
2452
+ const errors = [];
2453
+ const warnings = [];
2454
+ const transforms = [];
2455
+ const objectSchema = schema.object;
2456
+ const definedKeys = new Set(Object.keys(objectSchema.properties || {}));
2457
+ for (const [key, propertySchema] of Object.entries(objectSchema.properties || {})) {
2458
+ const propertyPath = path ? `${path}.${key}` : key;
2459
+ const propertyValue = obj[key];
2460
+ if (propertyValue !== void 0) {
2461
+ const propertyResult = this.transform(propertyValue, propertySchema, propertyPath);
2462
+ result[key] = propertyResult.config;
2463
+ errors.push(...propertyResult.errors);
2464
+ warnings.push(...propertyResult.warnings);
2465
+ transforms.push(...propertyResult.transforms);
2466
+ } else if (propertySchema.default !== void 0) {
2467
+ result[key] = propertySchema.default;
2468
+ transforms.push(`Applied default for "${key}": ${JSON.stringify(propertySchema.default)}`);
2469
+ } else if (propertySchema.required) {
2470
+ errors.push({
2471
+ path: propertyPath,
2472
+ code: "required",
2473
+ message: `Property "${key}" is required`
2474
+ });
2475
+ }
2476
+ }
2477
+ if (objectSchema.patternProperties) {
2478
+ for (const key of Object.keys(obj)) {
2479
+ if (!definedKeys.has(key)) {
2480
+ for (const [pattern, patternSchema] of Object.entries(objectSchema.patternProperties)) {
2481
+ const regex = new RegExp(pattern);
2482
+ if (regex.test(key)) {
2483
+ const propertyPath = `${path}.${key}`;
2484
+ const propertyResult = this.transform(obj[key], patternSchema, propertyPath);
2485
+ result[key] = propertyResult.config;
2486
+ errors.push(...propertyResult.errors);
2487
+ warnings.push(...propertyResult.warnings);
2488
+ transforms.push(...propertyResult.transforms);
2489
+ }
2490
+ }
2491
+ }
2492
+ }
2493
+ }
2494
+ if (!objectSchema.additionalProperties) {
2495
+ for (const key of Object.keys(obj)) {
2496
+ if (!definedKeys.has(key)) {
2497
+ let matchesPattern = false;
2498
+ if (objectSchema.patternProperties) {
2499
+ for (const pattern of Object.keys(objectSchema.patternProperties)) {
2500
+ const regex = new RegExp(pattern);
2501
+ if (regex.test(key)) {
2502
+ matchesPattern = true;
2503
+ break;
2504
+ }
2505
+ }
2506
+ }
2507
+ if (!matchesPattern) {
2508
+ warnings.push(`Additional property "${key}" will be ignored`);
2509
+ }
2510
+ }
2511
+ }
2512
+ }
2513
+ return { value: result, errors, warnings, transforms };
2514
+ }
2515
+ /**
2516
+ * 转换数组配置
2517
+ */
2518
+ transformArray(arr, schema, path) {
2519
+ const result = [];
2520
+ const errors = [];
2521
+ const warnings = [];
2522
+ const transforms = [];
2523
+ const arraySchema = schema.array;
2524
+ for (let i = 0; i < arr.length; i++) {
2525
+ const itemPath = `${path}[${i}]`;
2526
+ const itemResult = this.transform(arr[i], arraySchema.items, itemPath);
2527
+ result.push(itemResult.config);
2528
+ errors.push(...itemResult.errors);
2529
+ warnings.push(...itemResult.warnings);
2530
+ transforms.push(...itemResult.transforms);
2531
+ }
2532
+ if (arraySchema.tuple) {
2533
+ for (let i = arr.length; i < arraySchema.tuple.length; i++) {
2534
+ const itemSchema = arraySchema.tuple[i];
2535
+ if (itemSchema && itemSchema.default !== void 0) {
2536
+ result.push(itemSchema.default);
2537
+ transforms.push(`Applied default for tuple[${i}]: ${JSON.stringify(itemSchema.default)}`);
2538
+ }
2539
+ }
2540
+ }
2541
+ return { value: result, errors, warnings, transforms };
2542
+ }
2543
+ /**
2544
+ * 合并多个配置(用户配置覆盖默认配置)
2545
+ * @param defaults - 默认配置
2546
+ * @param overrides - 用户配置
2547
+ * @param schema - 配置 Schema
2548
+ * @returns 合并后的配置
2549
+ */
2550
+ merge(defaults, overrides, schema) {
2551
+ const merged = this.deepMerge(defaults, overrides);
2552
+ return this.transform(merged, schema);
2553
+ }
2554
+ /**
2555
+ * 深度合并两个对象
2556
+ */
2557
+ deepMerge(target, source) {
2558
+ const result = { ...target };
2559
+ for (const [key, value] of Object.entries(source)) {
2560
+ if (value !== void 0) {
2561
+ if (typeof value === "object" && value !== null && !Array.isArray(value) && typeof result[key] === "object" && result[key] !== null && !Array.isArray(result[key])) {
2562
+ result[key] = this.deepMerge(result[key], value);
2563
+ } else {
2564
+ result[key] = value;
2565
+ }
2566
+ }
2567
+ }
2568
+ return result;
2569
+ }
2570
+ /**
2571
+ * 从配置中提取指定字段
2572
+ * @param config - 完整配置
2573
+ * @param schema - 配置 Schema
2574
+ * @param keys - 要提取的键
2575
+ * @returns 提取的配置子集
2576
+ */
2577
+ extract(config, schema, keys) {
2578
+ const result = {};
2579
+ const configObj = config;
2580
+ for (const key of keys) {
2581
+ if (key in configObj) {
2582
+ const propertySchema = schema.object?.properties?.[key];
2583
+ if (propertySchema) {
2584
+ const propertyReport = this.transform(configObj[key], propertySchema, String(key));
2585
+ if (propertyReport.success) {
2586
+ result[key] = propertyReport.config;
2587
+ }
2588
+ } else {
2589
+ result[key] = configObj[key];
2590
+ }
2591
+ }
2592
+ }
2593
+ return result;
2594
+ }
2595
+ };
2596
+ }
2597
+ });
2598
+
2599
+ // src/plugin-sdk.ts
2600
+ function definePlugin(config) {
2601
+ const { name, version, description, author, keywords, schema, install } = config;
2602
+ const plugin = {
2603
+ name,
2604
+ version,
2605
+ meta: {
2606
+ description,
2607
+ author,
2608
+ keywords
2609
+ },
2610
+ configSchema: schema,
2611
+ install: async (app, ...options) => {
2612
+ const rawOptions = options[0];
2613
+ if (schema) {
2614
+ const transformer = new exports.ConfigTransformer();
2615
+ const report = transformer.transform(rawOptions, schema);
2616
+ if (!report.success) {
2617
+ const errors = report.errors.map((e) => `${e.path}: ${e.message}`).join(", ");
2618
+ throw new Error(`Plugin "${name}" configuration validation failed: ${errors}`);
2619
+ }
2620
+ await install(app, report.config);
2621
+ } else {
2622
+ await install(app, rawOptions);
2623
+ }
2624
+ }
2625
+ };
2626
+ return plugin;
2627
+ }
2628
+ function validatePluginConfig(plugin, userConfig) {
2629
+ if (!plugin.configSchema) {
2630
+ return { valid: true, errors: [], errorCount: 0, warningCount: 0 };
2631
+ }
2632
+ return validateConfig(userConfig, plugin.configSchema);
2633
+ }
2634
+ function transformPluginConfig(plugin, userConfig) {
2635
+ if (!plugin.configSchema) {
2636
+ return {
2637
+ config: userConfig,
2638
+ success: true,
2639
+ errors: [],
2640
+ warnings: [],
2641
+ transforms: []
2642
+ };
2643
+ }
2644
+ return transformConfig(userConfig, plugin.configSchema);
2645
+ }
2646
+ function mergePluginConfig(plugin, defaults, overrides) {
2647
+ if (!plugin.configSchema) {
2648
+ const merged = { ...defaults, ...overrides };
2649
+ return {
2650
+ config: merged,
2651
+ success: true,
2652
+ errors: [],
2653
+ warnings: [],
2654
+ transforms: []
2655
+ };
2656
+ }
2657
+ const transformer = new exports.ConfigTransformer();
2658
+ return transformer.merge(defaults, overrides, plugin.configSchema);
2659
+ }
2660
+ function createPluginTester(options) {
2661
+ return new PluginTester(options);
2662
+ }
2663
+ async function testPluginInstall(plugin, options, testerOptions) {
2664
+ const tester = createPluginTester(testerOptions);
2665
+ try {
2666
+ await tester.installPlugin(plugin, options);
2667
+ return { success: true, app: tester.getApp() };
2668
+ } catch (err) {
2669
+ return { success: false, error: err instanceof Error ? err : new Error(String(err)) };
2670
+ } finally {
2671
+ tester.cleanup();
2672
+ }
2673
+ }
2674
+ var PluginTester;
2675
+ var init_plugin_sdk = __esm({
2676
+ "src/plugin-sdk.ts"() {
2677
+ init_config_transformer();
2678
+ init_config_validator();
2679
+ PluginTester = class {
2680
+ constructor(options = {}) {
2681
+ this.app = null;
2682
+ this.installedPlugins = /* @__PURE__ */ new Set();
2683
+ this.options = {
2684
+ appConfig: options.appConfig || {},
2685
+ debug: options.debug || false,
2686
+ onValidationError: options.onValidationError || (() => {
2687
+ }),
2688
+ onBeforeInstall: options.onBeforeInstall || (() => {
2689
+ }),
2690
+ onAfterInstall: options.onAfterInstall || (() => {
2691
+ }),
2692
+ onCleanup: options.onCleanup || (() => {
2693
+ })
2694
+ };
2695
+ }
2696
+ /**
2697
+ * 创建测试 App
2698
+ */
2699
+ async createApp() {
2700
+ const { createApp: createApp2, h: h2 } = await Promise.resolve().then(() => (init_src(), src_exports));
2701
+ const app = createApp2({
2702
+ render: () => h2("div")
2703
+ });
2704
+ this.app = app;
2705
+ return app;
2706
+ }
2707
+ /**
2708
+ * 安装插件进行测试
2709
+ */
2710
+ async installPlugin(plugin, options) {
2711
+ if (!this.app) {
2712
+ await this.createApp();
2713
+ }
2714
+ if (plugin.configSchema) {
2715
+ const report = validatePluginConfig(plugin, options);
2716
+ if (!report.valid) {
2717
+ this.options.onValidationError(report);
2718
+ if (this.options.debug) {
2719
+ console.error("[PluginTester] Validation errors:", report.errors);
2720
+ }
2721
+ }
2722
+ }
2723
+ this.options.onBeforeInstall(this.app);
2724
+ if (this.options.debug) {
2725
+ console.log(`[PluginTester] Installing plugin: ${plugin.name}`);
2726
+ }
2727
+ this.app.use(plugin, options);
2728
+ this.installedPlugins.add(plugin.name);
2729
+ this.options.onAfterInstall(this.app);
2730
+ }
2731
+ /**
2732
+ * 卸载插件进行测试
2733
+ */
2734
+ uninstallPlugin(name) {
2735
+ if (!this.app || !this.installedPlugins.has(name)) {
2736
+ return;
2737
+ }
2738
+ if (this.options.debug) {
2739
+ console.log(`[PluginTester] Uninstalling plugin: ${name}`);
2740
+ }
2741
+ this.app._pluginRegistry.unregister(name);
2742
+ this.installedPlugins.delete(name);
2743
+ }
2744
+ /**
2745
+ * 运行清理
2746
+ */
2747
+ cleanup() {
2748
+ if (this.app) {
2749
+ this.app.unmount();
2750
+ }
2751
+ this.app = null;
2752
+ this.installedPlugins.clear();
2753
+ this.options.onCleanup();
2754
+ }
2755
+ /**
2756
+ * 获取已安装插件列表
2757
+ */
2758
+ getInstalledPlugins() {
2759
+ return Array.from(this.installedPlugins);
2760
+ }
2761
+ /**
2762
+ * 获取 App 实例
2763
+ */
2764
+ getApp() {
2765
+ return this.app;
2766
+ }
2767
+ };
2768
+ }
2769
+ });
2770
+ function getGlobalConfig() {
2771
+ if (!globalConfigManager) {
2772
+ globalConfigManager = new exports.ConfigManager(defaultGlobalConfig);
2773
+ }
2774
+ return globalConfigManager;
2775
+ }
2776
+ function setGlobalConfig(config, merge = true) {
2777
+ if (merge) {
2778
+ getGlobalConfig().merge(config);
2779
+ } else {
2780
+ getGlobalConfig().reset(config);
2781
+ }
2782
+ }
2783
+ function getConfig(path, defaultValue) {
2784
+ return getGlobalConfig().get(path, defaultValue);
2785
+ }
2786
+ function setConfig(path, value) {
2787
+ return getGlobalConfig().set(path, value);
2788
+ }
2789
+ function watchConfig(path, callback) {
2790
+ return getGlobalConfig().watch(path, callback);
2791
+ }
2792
+ function applyConfigPreset(preset) {
2793
+ const config = exports.configPresets[preset]();
2794
+ setGlobalConfig(config, true);
2795
+ }
2796
+ exports.ConfigManager = void 0; var defaultGlobalConfig, globalConfigManager; exports.configPresets = void 0;
2797
+ var init_config = __esm({
2798
+ "src/config.ts"() {
2799
+ exports.ConfigManager = class {
2800
+ constructor(initialConfig = {}, options = {}) {
2801
+ this.config = {};
2802
+ this.listeners = /* @__PURE__ */ new Map();
2803
+ this.globalListeners = /* @__PURE__ */ new Set();
2804
+ this.options = {
2805
+ mutable: true,
2806
+ deepMerge: true,
2807
+ ...options
2808
+ };
2809
+ this.config = this.options.deepMerge ? commonObject.deepClone(initialConfig) : { ...initialConfig };
2810
+ }
2811
+ /**
2812
+ * 获取配置值
2813
+ *
2814
+ * @param path - 配置路径(支持点号分隔,如 'api.baseURL')
2815
+ * @param defaultValue - 默认值
2816
+ * @returns 配置值或默认值
2817
+ *
2818
+ * @example
2819
+ * ```ts
2820
+ * config.get('api.baseURL') // '/api'
2821
+ * config.get('api.timeout', 5000) // 5000 (如果不存在)
2822
+ * config.get('theme.colors.primary') // 嵌套值
2823
+ * ```
2824
+ */
2825
+ get(path, defaultValue) {
2826
+ const keys = path.split(".");
2827
+ let value = this.config;
2828
+ for (const key of keys) {
2829
+ if (commonIs.isObject(value) && key in value) {
2830
+ value = value[key];
2831
+ } else {
2832
+ return defaultValue;
2833
+ }
2834
+ }
2835
+ return value;
2836
+ }
2837
+ /**
2838
+ * 设置配置值
2839
+ *
2840
+ * @param path - 配置路径
2841
+ * @param value - 新值
2842
+ * @returns 是否设置成功
2843
+ *
2844
+ * @example
2845
+ * ```ts
2846
+ * config.set('api.timeout', 10000)
2847
+ * config.set('theme.colors.primary', '#ff0000')
2848
+ * ```
2849
+ */
2850
+ set(path, value) {
2851
+ if (!this.options.mutable) {
2852
+ console.warn("[ConfigManager] Configuration is immutable");
2853
+ return false;
2854
+ }
2855
+ const keys = path.split(".");
2856
+ const lastKey = keys.pop();
2857
+ let target = this.config;
2858
+ for (const key of keys) {
2859
+ if (!commonIs.isObject(target[key])) {
2860
+ target[key] = {};
2861
+ }
2862
+ target = target[key];
2863
+ }
2864
+ const oldValue = target[lastKey];
2865
+ if (!commonIs.hasChanged(value, oldValue)) {
2866
+ return false;
2867
+ }
2868
+ const parentOldValues = /* @__PURE__ */ new Map();
2869
+ const parentParts = path.split(".");
2870
+ while (parentParts.length > 1) {
2871
+ parentParts.pop();
2872
+ const parentPath = parentParts.join(".");
2873
+ const parentVal = this.get(parentPath);
2874
+ parentOldValues.set(
2875
+ parentPath,
2876
+ parentVal !== null && typeof parentVal === "object" ? commonObject.deepClone(parentVal) : parentVal
2877
+ );
2878
+ }
2879
+ target[lastKey] = value;
2880
+ this.notify(path, value, oldValue, parentOldValues);
2881
+ return true;
2882
+ }
2883
+ /**
2884
+ * 批量设置配置
2885
+ *
2886
+ * @param config - 配置对象
2887
+ * @param merge - 是否合并(true)或替换(false)
2888
+ *
2889
+ * @example
2890
+ * ```ts
2891
+ * config.setMultiple({
2892
+ * 'api.timeout': 10000,
2893
+ * 'theme.primary': '#ff0000'
2894
+ * })
2895
+ * ```
2896
+ */
2897
+ setMultiple(config, merge = true) {
2898
+ if (!this.options.mutable) {
2899
+ console.warn("[ConfigManager] Configuration is immutable");
2900
+ return;
2901
+ }
2902
+ if (!merge) {
2903
+ this.config = {};
2904
+ }
2905
+ Object.entries(config).forEach(([path, value]) => {
2906
+ this.set(path, value);
2907
+ });
2908
+ }
2909
+ /**
2910
+ * 检查配置是否存在
2911
+ *
2912
+ * @param path - 配置路径
2913
+ * @returns 是否存在
2914
+ */
2915
+ has(path) {
2916
+ const keys = path.split(".");
2917
+ let value = this.config;
2918
+ for (const key of keys) {
2919
+ if (commonIs.isObject(value) && key in value) {
2920
+ value = value[key];
2921
+ } else {
2922
+ return false;
2923
+ }
2924
+ }
2925
+ return true;
2926
+ }
2927
+ /**
2928
+ * 删除配置
2929
+ *
2930
+ * @param path - 配置路径
2931
+ * @returns 是否删除成功
2932
+ */
2933
+ delete(path) {
2934
+ if (!this.options.mutable) {
2935
+ console.warn("[ConfigManager] Configuration is immutable");
2936
+ return false;
2937
+ }
2938
+ const keys = path.split(".");
2939
+ const lastKey = keys.pop();
2940
+ let target = this.config;
2941
+ for (const key of keys) {
2942
+ if (commonIs.isObject(target) && key in target) {
2943
+ target = target[key];
2944
+ } else {
2945
+ return false;
2946
+ }
2947
+ }
2948
+ if (commonIs.isObject(target) && lastKey in target) {
2949
+ const oldValue = target[lastKey];
2950
+ delete target[lastKey];
2951
+ this.notify(path, void 0, oldValue);
2952
+ return true;
2953
+ }
2954
+ return false;
2955
+ }
2956
+ /**
2957
+ * 合并配置
2958
+ *
2959
+ * @param config - 要合并的配置
2960
+ * @param deep - 是否深度合并
2961
+ *
2962
+ * @example
2963
+ * ```ts
2964
+ * config.merge({
2965
+ * api: { timeout: 10000 },
2966
+ * newKey: 'value'
2967
+ * })
2968
+ * ```
2969
+ */
2970
+ merge(config, deep = true) {
2971
+ if (!this.options.mutable) {
2972
+ console.warn("[ConfigManager] Configuration is immutable");
2973
+ return;
2974
+ }
2975
+ const mergedKeys = [];
2976
+ if (deep) {
2977
+ this.deepMergeNotify(this.config, config, "", mergedKeys);
2978
+ } else {
2979
+ for (const key of Object.keys(config)) {
2980
+ const oldValue = this.config[key];
2981
+ this.config[key] = config[key];
2982
+ if (commonIs.hasChanged(this.config[key], oldValue)) {
2983
+ this.notify(key, this.config[key], oldValue);
2984
+ mergedKeys.push(key);
2985
+ }
2986
+ }
2987
+ }
2988
+ this.globalListeners.forEach((cb) => cb(this.config, this.config, ""));
2989
+ }
2990
+ /**
2991
+ * 深度合并对象,并在值变更时通知监听器
2992
+ * FIX: P2-v11-08 替代原 deepMerge,在合并过程中收集变更的键并通知监听器
2993
+ */
2994
+ deepMergeNotify(target, source, prefix, mergedKeys) {
2995
+ Object.entries(source).forEach(([key, value]) => {
2996
+ const fullPath = prefix ? `${prefix}.${key}` : key;
2997
+ if (commonIs.isObject(target[key]) && commonIs.isObject(value)) {
2998
+ this.deepMergeNotify(
2999
+ target[key],
3000
+ value,
3001
+ fullPath,
3002
+ mergedKeys
3003
+ );
3004
+ } else {
3005
+ const oldValue = target[key];
3006
+ target[key] = commonIs.isObject(value) ? commonObject.deepClone(value) : value;
3007
+ if (commonIs.hasChanged(target[key], oldValue)) {
3008
+ this.notify(fullPath, target[key], oldValue);
3009
+ mergedKeys.push(fullPath);
3010
+ }
3011
+ }
3012
+ });
3013
+ }
3014
+ /**
3015
+ * 获取所有配置
3016
+ *
3017
+ * @returns 配置对象的深拷贝
3018
+ */
3019
+ getAll() {
3020
+ return commonObject.deepClone(this.config);
3021
+ }
3022
+ /**
3023
+ * 重置配置
3024
+ *
3025
+ * @param newConfig - 新的配置对象
3026
+ */
3027
+ reset(newConfig = {}) {
3028
+ if (!this.options.mutable) {
3029
+ console.warn("[ConfigManager] Configuration is immutable");
3030
+ return;
3031
+ }
3032
+ const oldConfig = this.config;
3033
+ this.config = this.options.deepMerge ? commonObject.deepClone(newConfig) : { ...newConfig };
3034
+ this.globalListeners.forEach((cb) => cb(this.config, oldConfig, ""));
3035
+ }
3036
+ /**
3037
+ * 清空配置
3038
+ */
3039
+ clear() {
3040
+ this.reset({});
3041
+ }
3042
+ /**
3043
+ * 监听配置变更
3044
+ *
3045
+ * @param path - 配置路径(空字符串表示监听所有变更)
3046
+ * @param callback - 变更回调
3047
+ * @returns 取消监听函数
3048
+ *
3049
+ * @example
3050
+ * ```ts
3051
+ * // 监听特定路径
3052
+ * const unwatch = config.watch('api.timeout', (newVal, oldVal) => {
3053
+ * console.log(`timeout 从 ${oldVal} 变为 ${newVal}`)
3054
+ * })
3055
+ *
3056
+ * // 监听所有变更
3057
+ * config.watch('', (newConfig) => {
3058
+ * console.log('配置已更新:', newConfig)
3059
+ * })
3060
+ * ```
3061
+ */
3062
+ watch(path, callback) {
3063
+ if (path === "") {
3064
+ this.globalListeners.add(callback);
3065
+ return () => {
3066
+ this.globalListeners.delete(callback);
3067
+ };
3068
+ }
3069
+ if (!this.listeners.has(path)) {
3070
+ this.listeners.set(path, /* @__PURE__ */ new Set());
3071
+ }
3072
+ this.listeners.get(path).add(callback);
3073
+ return () => {
3074
+ this.listeners.get(path)?.delete(callback);
3075
+ };
3076
+ }
3077
+ /**
3078
+ * 通知监听器
3079
+ */
3080
+ // FIX: P1-10 增加 parentOldValues 参数,由调用方在修改值之前收集父路径旧值快照
3081
+ notify(path, newValue, oldValue, parentOldValues) {
3082
+ const specificListeners = this.listeners.get(path);
3083
+ if (specificListeners) {
3084
+ specificListeners.forEach((cb) => cb(newValue, oldValue, path));
3085
+ }
3086
+ const parts = path.split(".");
3087
+ while (parts.length > 1) {
3088
+ parts.pop();
3089
+ const parentPath = parts.join(".");
3090
+ const parentListeners = this.listeners.get(parentPath);
3091
+ if (parentListeners) {
3092
+ const parentValue = this.get(parentPath);
3093
+ const parentOldValue = parentOldValues?.get(parentPath);
3094
+ parentListeners.forEach((cb) => cb(parentValue, parentOldValue, path));
3095
+ }
3096
+ }
3097
+ if (this.options.onChange) {
3098
+ this.options.onChange(newValue, oldValue, path);
3099
+ }
3100
+ this.globalListeners.forEach((cb) => cb(newValue, oldValue, path));
3101
+ }
3102
+ /**
3103
+ * 设置可变性
3104
+ *
3105
+ * @param mutable - 是否可变
3106
+ */
3107
+ setMutable(mutable) {
3108
+ this.options.mutable = mutable;
3109
+ }
3110
+ /**
3111
+ * 检查是否可变
3112
+ * FIX: P2-v11-09 简化 isMutable():mutable 在构造函数中已设置默认值为 true,
3113
+ * 不可能为 undefined,因此 ?? true 是冗余的
3114
+ */
3115
+ isMutable() {
3116
+ return this.options.mutable ?? true;
3117
+ }
3118
+ };
3119
+ defaultGlobalConfig = {
3120
+ // 开发配置
3121
+ dev: {
3122
+ warnOnImmutable: true,
3123
+ logLevel: "warn"
3124
+ },
3125
+ // 性能配置
3126
+ performance: {
3127
+ asyncComponentTimeout: 5e3,
3128
+ keepAliveMax: 10,
3129
+ transitionDuration: 300
3130
+ },
3131
+ // 编译配置
3132
+ compiler: {
3133
+ comments: false,
3134
+ sourceMap: true,
3135
+ optimize: true
3136
+ },
3137
+ // 运行时配置
3138
+ runtime: {
3139
+ errorHandler: null,
3140
+ warnHandler: null,
3141
+ globalProperties: {}
3142
+ }
3143
+ };
3144
+ globalConfigManager = null;
3145
+ exports.configPresets = {
3146
+ /**
3147
+ * 开发环境预设
3148
+ */
3149
+ development: () => ({
3150
+ dev: {
3151
+ warnOnImmutable: true,
3152
+ logLevel: "debug"
3153
+ },
3154
+ compiler: {
3155
+ comments: true,
3156
+ sourceMap: true,
3157
+ optimize: false
3158
+ }
3159
+ }),
3160
+ /**
3161
+ * 生产环境预设
3162
+ */
3163
+ production: () => ({
3164
+ dev: {
3165
+ warnOnImmutable: false,
3166
+ logLevel: "error"
3167
+ },
3168
+ compiler: {
3169
+ comments: false,
3170
+ sourceMap: false,
3171
+ optimize: true
3172
+ }
3173
+ }),
3174
+ /**
3175
+ * 测试环境预设
3176
+ */
3177
+ test: () => ({
3178
+ dev: {
3179
+ warnOnImmutable: true,
3180
+ logLevel: "silent"
3181
+ },
3182
+ performance: {
3183
+ asyncComponentTimeout: 1e3,
3184
+ keepAliveMax: 5,
3185
+ transitionDuration: 0
3186
+ }
3187
+ })
3188
+ };
3189
+ }
3190
+ });
3191
+
3192
+ // src/common-integration.ts
3193
+ function registerIntegrations(integrations) {
3194
+ _integrations = { ..._integrations, ...integrations };
3195
+ }
3196
+ function getHttpClient() {
3197
+ return _integrations.http;
3198
+ }
3199
+ function getQueryUtils() {
3200
+ return _integrations.query;
3201
+ }
3202
+ function getSecurityUtils() {
3203
+ return _integrations.security;
3204
+ }
3205
+ function getCacheUtils() {
3206
+ return _integrations.cache;
3207
+ }
3208
+ function safeEscapeHtml(str) {
3209
+ const security = getSecurityUtils();
3210
+ if (security) {
3211
+ return security.escapeHtml(str);
3212
+ }
3213
+ return str.replace(/\\/g, "&#92;").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
3214
+ }
3215
+ function safeParseQueryString(str) {
3216
+ const query = getQueryUtils();
3217
+ if (query) {
3218
+ return query.parseQueryString(str);
3219
+ }
3220
+ const result = {};
3221
+ if (!str) return result;
3222
+ const searchParams = new URLSearchParams(str.startsWith("?") ? str.slice(1) : str);
3223
+ for (const [key, value] of searchParams) {
3224
+ result[key] = value;
3225
+ }
3226
+ return result;
3227
+ }
3228
+ var _integrations;
3229
+ var init_common_integration = __esm({
3230
+ "src/common-integration.ts"() {
3231
+ _integrations = {};
3232
+ }
3233
+ });
3234
+
3235
+ // src/index.ts
3236
+ var src_exports = {};
3237
+ __export(src_exports, {
3238
+ Comment: () => vdom.Comment,
3239
+ ConfigManager: () => exports.ConfigManager,
3240
+ ConfigTransformer: () => exports.ConfigTransformer,
3241
+ ConfigValidator: () => exports.ConfigValidator,
3242
+ Fragment: () => vdom.Fragment,
3243
+ PluginRegistry: () => exports.PluginRegistry,
3244
+ PluginValidator: () => exports.PluginValidator,
3245
+ Text: () => vdom.Text,
3246
+ applyConfigPreset: () => applyConfigPreset,
3247
+ cloneVNode: () => vdom.cloneVNode,
3248
+ compile: () => compiler.compile,
3249
+ computed: () => reactivity.computed,
3250
+ configPresets: () => exports.configPresets,
3251
+ createApp: () => createApp,
3252
+ createElement: () => h,
3253
+ createPluginTester: () => createPluginTester,
3254
+ createVNode: () => vdom.createVNode,
3255
+ defineAsyncComponent: () => defineAsyncComponent,
3256
+ defineComponent: () => exports.defineComponent,
3257
+ defineCustomElement: () => defineCustomElement,
3258
+ defineModel: () => defineModel,
3259
+ definePlugin: () => definePlugin,
3260
+ effect: () => reactivity.effect,
3261
+ getCacheUtils: () => getCacheUtils,
3262
+ getConfig: () => getConfig,
3263
+ getGlobalConfig: () => getGlobalConfig,
3264
+ getHttpClient: () => getHttpClient,
3265
+ getQueryUtils: () => getQueryUtils,
3266
+ getSecurityUtils: () => getSecurityUtils,
3267
+ h: () => h,
3268
+ injectChildStyles: () => injectChildStyles,
3269
+ mergeConfig: () => mergeConfig,
3270
+ mergePluginConfig: () => mergePluginConfig,
3271
+ mergeProps: () => vdom.mergeProps,
3272
+ nextTick: () => commonScheduler.nextTick,
3273
+ onActivated: () => component.onActivated,
3274
+ onBeforeMount: () => component.onBeforeMount,
3275
+ onBeforeUnmount: () => component.onBeforeUnmount,
3276
+ onBeforeUpdate: () => component.onBeforeUpdate,
3277
+ onDeactivated: () => component.onDeactivated,
3278
+ onErrorCaptured: () => component.onErrorCaptured,
3279
+ onMounted: () => component.onMounted,
3280
+ onRenderTracked: () => component.onRenderTracked,
3281
+ onRenderTriggered: () => component.onRenderTriggered,
3282
+ onUnmounted: () => component.onUnmounted,
3283
+ onUpdated: () => component.onUpdated,
3284
+ reactive: () => reactivity.reactive,
3285
+ ref: () => reactivity.ref,
3286
+ registerIntegrations: () => registerIntegrations,
3287
+ resolveComponent: () => resolveComponent,
3288
+ resolveDirective: () => resolveDirective,
3289
+ resolveDynamicComponent: () => resolveDynamicComponent,
3290
+ safeEscapeHtml: () => safeEscapeHtml,
3291
+ safeParseQueryString: () => safeParseQueryString,
3292
+ setConfig: () => setConfig,
3293
+ setGlobalConfig: () => setGlobalConfig,
3294
+ testPluginInstall: () => testPluginInstall,
3295
+ transformConfig: () => transformConfig,
3296
+ transformPluginConfig: () => transformPluginConfig,
3297
+ useAttrs: () => useAttrs,
3298
+ useCssModule: () => useCssModule,
3299
+ useCssVars: () => useCssVars,
3300
+ useHost: () => useHost,
3301
+ useId: () => useId,
3302
+ useModel: () => useModel,
3303
+ useShadowRoot: () => useShadowRoot,
3304
+ useSlots: () => useSlots,
3305
+ useTemplateRef: () => useTemplateRef,
3306
+ useWebComponentSlots: () => useWebComponentSlots,
3307
+ validateConfig: () => validateConfig,
3308
+ validatePluginConfig: () => validatePluginConfig,
3309
+ watch: () => reactivity.watch,
3310
+ watchConfig: () => watchConfig,
3311
+ watchEffect: () => reactivity.watchEffect,
3312
+ withDirectives: () => withDirectives,
3313
+ withMemo: () => withMemo
3314
+ });
3315
+ var init_src = __esm({
3316
+ "src/index.ts"() {
3317
+ init_create_app();
3318
+ init_h();
3319
+ init_define_component();
3320
+ init_next_tick();
3321
+ init_resolve();
3322
+ init_directives();
3323
+ init_composition();
3324
+ init_web_component();
3325
+ init_lifecycle();
3326
+ init_plugin_registry();
3327
+ init_plugin_validator();
3328
+ init_config_validator();
3329
+ init_config_transformer();
3330
+ init_plugin_sdk();
3331
+ init_config();
3332
+ init_common_integration();
3333
+ }
3334
+ });
3335
+ init_src();
3336
+
3337
+ Object.defineProperty(exports, "onActivated", {
3338
+ enumerable: true,
3339
+ get: function () { return component.onActivated; }
3340
+ });
3341
+ Object.defineProperty(exports, "onBeforeMount", {
3342
+ enumerable: true,
3343
+ get: function () { return component.onBeforeMount; }
3344
+ });
3345
+ Object.defineProperty(exports, "onBeforeUnmount", {
3346
+ enumerable: true,
3347
+ get: function () { return component.onBeforeUnmount; }
3348
+ });
3349
+ Object.defineProperty(exports, "onBeforeUpdate", {
3350
+ enumerable: true,
3351
+ get: function () { return component.onBeforeUpdate; }
3352
+ });
3353
+ Object.defineProperty(exports, "onDeactivated", {
3354
+ enumerable: true,
3355
+ get: function () { return component.onDeactivated; }
3356
+ });
3357
+ Object.defineProperty(exports, "onErrorCaptured", {
3358
+ enumerable: true,
3359
+ get: function () { return component.onErrorCaptured; }
3360
+ });
3361
+ Object.defineProperty(exports, "onMounted", {
3362
+ enumerable: true,
3363
+ get: function () { return component.onMounted; }
3364
+ });
3365
+ Object.defineProperty(exports, "onRenderTracked", {
3366
+ enumerable: true,
3367
+ get: function () { return component.onRenderTracked; }
3368
+ });
3369
+ Object.defineProperty(exports, "onRenderTriggered", {
3370
+ enumerable: true,
3371
+ get: function () { return component.onRenderTriggered; }
3372
+ });
3373
+ Object.defineProperty(exports, "onUnmounted", {
3374
+ enumerable: true,
3375
+ get: function () { return component.onUnmounted; }
3376
+ });
3377
+ Object.defineProperty(exports, "onUpdated", {
3378
+ enumerable: true,
3379
+ get: function () { return component.onUpdated; }
3380
+ });
3381
+ Object.defineProperty(exports, "Comment", {
3382
+ enumerable: true,
3383
+ get: function () { return vdom.Comment; }
3384
+ });
3385
+ Object.defineProperty(exports, "Fragment", {
3386
+ enumerable: true,
3387
+ get: function () { return vdom.Fragment; }
3388
+ });
3389
+ Object.defineProperty(exports, "Text", {
3390
+ enumerable: true,
3391
+ get: function () { return vdom.Text; }
3392
+ });
3393
+ Object.defineProperty(exports, "cloneVNode", {
3394
+ enumerable: true,
3395
+ get: function () { return vdom.cloneVNode; }
3396
+ });
3397
+ Object.defineProperty(exports, "createVNode", {
3398
+ enumerable: true,
3399
+ get: function () { return vdom.createVNode; }
3400
+ });
3401
+ Object.defineProperty(exports, "mergeProps", {
3402
+ enumerable: true,
3403
+ get: function () { return vdom.mergeProps; }
3404
+ });
3405
+ Object.defineProperty(exports, "computed", {
3406
+ enumerable: true,
3407
+ get: function () { return reactivity.computed; }
3408
+ });
3409
+ Object.defineProperty(exports, "effect", {
3410
+ enumerable: true,
3411
+ get: function () { return reactivity.effect; }
3412
+ });
3413
+ Object.defineProperty(exports, "reactive", {
3414
+ enumerable: true,
3415
+ get: function () { return reactivity.reactive; }
3416
+ });
3417
+ Object.defineProperty(exports, "ref", {
3418
+ enumerable: true,
3419
+ get: function () { return reactivity.ref; }
3420
+ });
3421
+ Object.defineProperty(exports, "watch", {
3422
+ enumerable: true,
3423
+ get: function () { return reactivity.watch; }
3424
+ });
3425
+ Object.defineProperty(exports, "watchEffect", {
3426
+ enumerable: true,
3427
+ get: function () { return reactivity.watchEffect; }
3428
+ });
3429
+ Object.defineProperty(exports, "nextTick", {
3430
+ enumerable: true,
3431
+ get: function () { return commonScheduler.nextTick; }
3432
+ });
3433
+ Object.defineProperty(exports, "compile", {
3434
+ enumerable: true,
3435
+ get: function () { return compiler.compile; }
3436
+ });
3437
+ exports.applyConfigPreset = applyConfigPreset;
3438
+ exports.createApp = createApp;
3439
+ exports.createElement = h;
3440
+ exports.createPluginTester = createPluginTester;
3441
+ exports.defineAsyncComponent = defineAsyncComponent;
3442
+ exports.defineCustomElement = defineCustomElement;
3443
+ exports.defineModel = defineModel;
3444
+ exports.definePlugin = definePlugin;
3445
+ exports.getCacheUtils = getCacheUtils;
3446
+ exports.getConfig = getConfig;
3447
+ exports.getGlobalConfig = getGlobalConfig;
3448
+ exports.getHttpClient = getHttpClient;
3449
+ exports.getQueryUtils = getQueryUtils;
3450
+ exports.getSecurityUtils = getSecurityUtils;
3451
+ exports.h = h;
3452
+ exports.injectChildStyles = injectChildStyles;
3453
+ exports.mergeConfig = mergeConfig;
3454
+ exports.mergePluginConfig = mergePluginConfig;
3455
+ exports.registerIntegrations = registerIntegrations;
3456
+ exports.resolveComponent = resolveComponent;
3457
+ exports.resolveDirective = resolveDirective;
3458
+ exports.resolveDynamicComponent = resolveDynamicComponent;
3459
+ exports.safeEscapeHtml = safeEscapeHtml;
3460
+ exports.safeParseQueryString = safeParseQueryString;
3461
+ exports.setConfig = setConfig;
3462
+ exports.setGlobalConfig = setGlobalConfig;
3463
+ exports.testPluginInstall = testPluginInstall;
3464
+ exports.transformConfig = transformConfig;
3465
+ exports.transformPluginConfig = transformPluginConfig;
3466
+ exports.useAttrs = useAttrs;
3467
+ exports.useCssModule = useCssModule;
3468
+ exports.useCssVars = useCssVars;
3469
+ exports.useHost = useHost;
3470
+ exports.useId = useId;
3471
+ exports.useModel = useModel;
3472
+ exports.useShadowRoot = useShadowRoot;
3473
+ exports.useSlots = useSlots;
3474
+ exports.useTemplateRef = useTemplateRef;
3475
+ exports.useWebComponentSlots = useWebComponentSlots;
3476
+ exports.validateConfig = validateConfig;
3477
+ exports.validatePluginConfig = validatePluginConfig;
3478
+ exports.watchConfig = watchConfig;
3479
+ exports.withDirectives = withDirectives;
3480
+ exports.withMemo = withMemo;
3481
+ //# sourceMappingURL=index.cjs.map
3482
+ //# sourceMappingURL=index.cjs.map