@vobs/dict 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +53 -225
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18 -212
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,218 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
var __VOBS_CJS_FILE_URL = require("url").pathToFileURL(__filename).href;
|
|
2
|
+
"use strict";
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
7
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
var signalNames = /* @__PURE__ */ new WeakMap();
|
|
9
|
-
function hasDebugHooks() {
|
|
10
|
-
return activeDebugHooks !== null;
|
|
11
|
-
}
|
|
12
|
-
__name(hasDebugHooks, "hasDebugHooks");
|
|
13
|
-
function setSignalDebugName(signal, name) {
|
|
14
|
-
signalNames.set(signal, name);
|
|
15
|
-
invokeDebug("signalNamed", signal, name);
|
|
16
|
-
}
|
|
17
|
-
__name(setSignalDebugName, "setSignalDebugName");
|
|
18
|
-
function invokeDebug(name, ...args) {
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
__name(invokeDebug, "invokeDebug");
|
|
22
|
-
|
|
23
|
-
// packages/reactivity/src/owner.ts
|
|
24
|
-
var currentOwner = null;
|
|
25
|
-
function getCurrentOwner() {
|
|
26
|
-
return currentOwner;
|
|
27
|
-
}
|
|
28
|
-
__name(getCurrentOwner, "getCurrentOwner");
|
|
29
|
-
function onDispose(cleanup) {
|
|
30
|
-
throw new Error("Vobs: onDispose \u5FC5\u987B\u5728 Owner \u4F5C\u7528\u57DF\u5185\u8C03\u7528");
|
|
31
|
-
}
|
|
32
|
-
__name(onDispose, "onDispose");
|
|
33
|
-
|
|
34
|
-
// packages/reactivity/src/signal.ts
|
|
35
|
-
var currentSubscriber = null;
|
|
36
|
-
function getCurrentSubscriber() {
|
|
37
|
-
return currentSubscriber;
|
|
38
|
-
}
|
|
39
|
-
__name(getCurrentSubscriber, "getCurrentSubscriber");
|
|
40
|
-
function trackDependency(dependency) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
__name(trackDependency, "trackDependency");
|
|
44
|
-
function state(initialValue, debugName) {
|
|
45
|
-
let value = initialValue;
|
|
46
|
-
let disposed = false;
|
|
47
|
-
const subscribers = /* @__PURE__ */ new Set();
|
|
48
|
-
const signalInstance = {
|
|
49
|
-
get value() {
|
|
50
|
-
return value;
|
|
51
|
-
},
|
|
52
|
-
set value(nextValue) {
|
|
53
|
-
if (disposed || Object.is(value, nextValue)) return;
|
|
54
|
-
value = nextValue;
|
|
55
|
-
for (const subscriber of [...subscribers]) subscriber.notify();
|
|
56
|
-
},
|
|
57
|
-
unsubscribe(subscriber) {
|
|
58
|
-
subscribers.delete(subscriber);
|
|
59
|
-
},
|
|
60
|
-
// 与 `.value =` 赋值同一条路径:判等短路、debug hook、notify 全部一致。
|
|
61
|
-
// 以闭包实现,可安全地作为回调直接传递(无 this 绑定问题)。
|
|
62
|
-
set(next) {
|
|
63
|
-
signalInstance.value = next;
|
|
64
|
-
},
|
|
65
|
-
dispose() {
|
|
66
|
-
if (disposed) return;
|
|
67
|
-
disposed = true;
|
|
68
|
-
subscribers.clear();
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
if (debugName?.trim()) setSignalDebugName(signalInstance, debugName.trim());
|
|
72
|
-
return signalInstance;
|
|
73
|
-
}
|
|
74
|
-
__name(state, "state");
|
|
75
|
-
|
|
76
|
-
// packages/reactivity/src/scheduler.ts
|
|
77
|
-
var _Scheduler = class _Scheduler {
|
|
78
|
-
constructor() {
|
|
79
|
-
this.dirtyEffects = /* @__PURE__ */ new Set();
|
|
80
|
-
this.lowPriorityEffects = /* @__PURE__ */ new Set();
|
|
81
|
-
// flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
|
|
82
|
-
this.normalBuffer = [];
|
|
83
|
-
this.lowBuffer = [];
|
|
84
|
-
this.flushing = false;
|
|
85
|
-
this.scheduled = false;
|
|
86
|
-
this.batchDepth = 0;
|
|
87
|
-
}
|
|
88
|
-
schedule(effect2) {
|
|
89
|
-
if (effect2.disposed) return;
|
|
90
|
-
this.dirtyEffects.add(effect2);
|
|
91
|
-
this.lowPriorityEffects.delete(effect2);
|
|
92
|
-
this.ensureScheduled();
|
|
93
|
-
}
|
|
94
|
-
/** Queue an effect behind normal updates while preserving deterministic order. */
|
|
95
|
-
scheduleLow(effect2) {
|
|
96
|
-
if (effect2.disposed) return;
|
|
97
|
-
if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
|
|
98
|
-
this.ensureScheduled();
|
|
99
|
-
}
|
|
100
|
-
ensureScheduled() {
|
|
101
|
-
if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
|
|
102
|
-
this.scheduled = true;
|
|
103
|
-
queueMicrotask(() => {
|
|
104
|
-
this.scheduled = false;
|
|
105
|
-
this.flush();
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
remove(effect2) {
|
|
110
|
-
this.dirtyEffects.delete(effect2);
|
|
111
|
-
this.lowPriorityEffects.delete(effect2);
|
|
112
|
-
}
|
|
113
|
-
batch(fn) {
|
|
114
|
-
this.batchDepth++;
|
|
115
|
-
try {
|
|
116
|
-
return fn();
|
|
117
|
-
} finally {
|
|
118
|
-
this.batchDepth--;
|
|
119
|
-
if (this.batchDepth === 0) this.flush();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
flush() {
|
|
123
|
-
if (this.flushing || this.batchDepth > 0) return;
|
|
124
|
-
this.flushing = true;
|
|
125
|
-
let rounds = 0;
|
|
126
|
-
let firstError;
|
|
127
|
-
let hasError = false;
|
|
128
|
-
try {
|
|
129
|
-
while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
|
|
130
|
-
if (++rounds > 100) {
|
|
131
|
-
this.dirtyEffects.clear();
|
|
132
|
-
this.lowPriorityEffects.clear();
|
|
133
|
-
throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
|
|
134
|
-
}
|
|
135
|
-
this.collectRunnable(this.dirtyEffects, this.normalBuffer);
|
|
136
|
-
this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
|
|
137
|
-
sortEffects(this.normalBuffer);
|
|
138
|
-
sortEffects(this.lowBuffer);
|
|
139
|
-
for (const effect2 of this.normalBuffer) {
|
|
140
|
-
try {
|
|
141
|
-
effect2.run();
|
|
142
|
-
} catch (error) {
|
|
143
|
-
if (!hasError) {
|
|
144
|
-
firstError = error;
|
|
145
|
-
hasError = true;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
for (const effect2 of this.lowBuffer) {
|
|
150
|
-
try {
|
|
151
|
-
effect2.run();
|
|
152
|
-
} catch (error) {
|
|
153
|
-
if (!hasError) {
|
|
154
|
-
firstError = error;
|
|
155
|
-
hasError = true;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
this.normalBuffer.length = 0;
|
|
160
|
-
this.lowBuffer.length = 0;
|
|
161
|
-
}
|
|
162
|
-
} finally {
|
|
163
|
-
this.normalBuffer.length = 0;
|
|
164
|
-
this.lowBuffer.length = 0;
|
|
165
|
-
this.flushing = false;
|
|
166
|
-
}
|
|
167
|
-
if (hasError) throw firstError;
|
|
168
|
-
}
|
|
169
|
-
/** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
|
|
170
|
-
collectRunnable(source, target) {
|
|
171
|
-
for (const effect2 of source) {
|
|
172
|
-
if (!effect2.disposed) target.push(effect2);
|
|
173
|
-
}
|
|
174
|
-
source.clear();
|
|
175
|
-
}
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
176
11
|
};
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
__name(sortEffects, "sortEffects");
|
|
184
|
-
|
|
185
|
-
// packages/runtime/src/hmr.ts
|
|
186
|
-
var globalTarget = globalThis;
|
|
187
|
-
var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
|
|
188
|
-
globalTarget.__VOBS_HMR__ = hmrGlobal;
|
|
189
|
-
|
|
190
|
-
// packages/vobs/src/context.ts
|
|
191
|
-
var ownerProviders = /* @__PURE__ */ new WeakMap();
|
|
192
|
-
function inject(key, fallback) {
|
|
193
|
-
const owner = getCurrentOwner();
|
|
194
|
-
const value = owner ? injectFromOwner(owner, key) : void 0;
|
|
195
|
-
return value === void 0 ? fallback : value;
|
|
196
|
-
}
|
|
197
|
-
__name(inject, "inject");
|
|
198
|
-
function injectFromOwner(owner, key) {
|
|
199
|
-
let current = owner;
|
|
200
|
-
while (current) {
|
|
201
|
-
const providers = ownerProviders.get(current);
|
|
202
|
-
if (providers?.has(key)) return providers.get(key);
|
|
203
|
-
current = current.parent;
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
204
17
|
}
|
|
205
|
-
return
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
// packages/vobs/src/app.ts
|
|
210
|
-
function createInjectionKey(description) {
|
|
211
|
-
return Symbol(description);
|
|
212
|
-
}
|
|
213
|
-
__name(createInjectionKey, "createInjectionKey");
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
214
21
|
|
|
215
22
|
// packages/dict/src/index.ts
|
|
23
|
+
var src_exports = {};
|
|
24
|
+
__export(src_exports, {
|
|
25
|
+
DICT_KEY: () => DICT_KEY,
|
|
26
|
+
DictError: () => DictError,
|
|
27
|
+
createDict: () => createDict,
|
|
28
|
+
dictPlugin: () => dictPlugin,
|
|
29
|
+
useDict: () => useDict
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(src_exports);
|
|
32
|
+
var import_reactivity = require("@vobs/reactivity");
|
|
33
|
+
var import_vobs = require("@vobs/vobs");
|
|
216
34
|
var _DictError = class _DictError extends Error {
|
|
217
35
|
constructor(code, message, cause) {
|
|
218
36
|
super(message);
|
|
@@ -223,15 +41,15 @@ var _DictError = class _DictError extends Error {
|
|
|
223
41
|
};
|
|
224
42
|
__name(_DictError, "DictError");
|
|
225
43
|
var DictError = _DictError;
|
|
226
|
-
var DICT_KEY = createInjectionKey("vobs.dict");
|
|
44
|
+
var DICT_KEY = (0, import_vobs.createInjectionKey)("vobs.dict");
|
|
227
45
|
var EMPTY_ITEMS = Object.freeze([]);
|
|
228
46
|
function createDict(options = {}) {
|
|
229
47
|
const staleTime = validateStaleTime(options.staleTime ?? 5 * 60 * 1e3);
|
|
230
48
|
const now = options.now ?? Date.now;
|
|
231
49
|
const initial = normalizeData(options.data ?? {});
|
|
232
|
-
const data = state(initial);
|
|
233
|
-
const loading = state(false);
|
|
234
|
-
const error = state(null);
|
|
50
|
+
const data = (0, import_reactivity.state)(initial);
|
|
51
|
+
const loading = (0, import_reactivity.state)(false);
|
|
52
|
+
const error = (0, import_reactivity.state)(null);
|
|
235
53
|
const entries = /* @__PURE__ */ new Map();
|
|
236
54
|
let disposed = false;
|
|
237
55
|
for (const [name, items] of Object.entries(initial)) {
|
|
@@ -370,6 +188,7 @@ function createDict(options = {}) {
|
|
|
370
188
|
error.dispose();
|
|
371
189
|
}
|
|
372
190
|
};
|
|
191
|
+
if ((0, import_reactivity.getCurrentOwner)()) (0, import_reactivity.onDispose)(context.dispose);
|
|
373
192
|
return context;
|
|
374
193
|
function getEntry(name) {
|
|
375
194
|
const existing = entries.get(name);
|
|
@@ -378,13 +197,14 @@ function createDict(options = {}) {
|
|
|
378
197
|
entries.set(name, entry);
|
|
379
198
|
return entry;
|
|
380
199
|
}
|
|
200
|
+
__name(getEntry, "getEntry");
|
|
381
201
|
function createEntry(name, items, updatedAt) {
|
|
382
202
|
const entry = {
|
|
383
203
|
name,
|
|
384
|
-
items: state(items),
|
|
385
|
-
loading: state(false),
|
|
386
|
-
error: state(null),
|
|
387
|
-
updatedAt: state(updatedAt),
|
|
204
|
+
items: (0, import_reactivity.state)(items),
|
|
205
|
+
loading: (0, import_reactivity.state)(false),
|
|
206
|
+
error: (0, import_reactivity.state)(null),
|
|
207
|
+
updatedAt: (0, import_reactivity.state)(updatedAt),
|
|
388
208
|
controller: null,
|
|
389
209
|
inFlight: null,
|
|
390
210
|
revision: 0,
|
|
@@ -393,6 +213,7 @@ function createDict(options = {}) {
|
|
|
393
213
|
};
|
|
394
214
|
return entry;
|
|
395
215
|
}
|
|
216
|
+
__name(createEntry, "createEntry");
|
|
396
217
|
function commit(entry, items, updatedAt, replaceRequest = true) {
|
|
397
218
|
if (replaceRequest) {
|
|
398
219
|
entry.revision++;
|
|
@@ -407,6 +228,7 @@ function createDict(options = {}) {
|
|
|
407
228
|
error.value = null;
|
|
408
229
|
refreshLoading();
|
|
409
230
|
}
|
|
231
|
+
__name(commit, "commit");
|
|
410
232
|
function invalidateEntry(entry) {
|
|
411
233
|
entry.revision++;
|
|
412
234
|
entry.controller?.abort();
|
|
@@ -416,21 +238,26 @@ function createDict(options = {}) {
|
|
|
416
238
|
entry.updatedAt.value = 0;
|
|
417
239
|
refreshLoading();
|
|
418
240
|
}
|
|
241
|
+
__name(invalidateEntry, "invalidateEntry");
|
|
419
242
|
function isFresh(entry) {
|
|
420
243
|
return entry.updatedAt.value > 0 && now() - entry.updatedAt.value < staleTime;
|
|
421
244
|
}
|
|
245
|
+
__name(isFresh, "isFresh");
|
|
422
246
|
function refreshLoading() {
|
|
423
247
|
loading.value = [...entries.values()].some((entry) => entry.loading.value);
|
|
424
248
|
}
|
|
249
|
+
__name(refreshLoading, "refreshLoading");
|
|
425
250
|
function report(dictError, name) {
|
|
426
251
|
try {
|
|
427
252
|
options.onError?.(dictError, name);
|
|
428
253
|
} catch {
|
|
429
254
|
}
|
|
430
255
|
}
|
|
256
|
+
__name(report, "report");
|
|
431
257
|
function ensureActive() {
|
|
432
258
|
if (disposed) throw new DictError("DICT_CONTEXT_DISPOSED", "Vobs Dict: \u4E0A\u4E0B\u6587\u5DF2\u9500\u6BC1");
|
|
433
259
|
}
|
|
260
|
+
__name(ensureActive, "ensureActive");
|
|
434
261
|
}
|
|
435
262
|
__name(createDict, "createDict");
|
|
436
263
|
function dictPlugin(options = {}) {
|
|
@@ -446,7 +273,7 @@ function dictPlugin(options = {}) {
|
|
|
446
273
|
}
|
|
447
274
|
__name(dictPlugin, "dictPlugin");
|
|
448
275
|
function useDict() {
|
|
449
|
-
const dict = inject(DICT_KEY);
|
|
276
|
+
const dict = (0, import_vobs.inject)(DICT_KEY);
|
|
450
277
|
if (!dict) throw new DictError("DICT_CONTEXT_MISSING", "Vobs Dict: \u627E\u4E0D\u5230\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5B89\u88C5 dictPlugin");
|
|
451
278
|
return dict;
|
|
452
279
|
}
|
|
@@ -521,11 +348,12 @@ function isAbortError(value) {
|
|
|
521
348
|
return Boolean(value) && typeof value === "object" && value.name === "AbortError";
|
|
522
349
|
}
|
|
523
350
|
__name(isAbortError, "isAbortError");
|
|
524
|
-
|
|
525
|
-
exports
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
351
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
352
|
+
0 && (module.exports = {
|
|
353
|
+
DICT_KEY,
|
|
354
|
+
DictError,
|
|
355
|
+
createDict,
|
|
356
|
+
dictPlugin,
|
|
357
|
+
useDict
|
|
358
|
+
});
|
|
531
359
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../reactivity/src/debug.ts","../../reactivity/src/owner.ts","../../reactivity/src/signal.ts","../../reactivity/src/scheduler.ts","../../runtime/src/hmr.ts","../../vobs/src/context.ts","../../vobs/src/app.ts","../src/index.ts"],"names":["effect"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { Effect } from './effect'\nimport type { Owner } from './owner'\nimport type { Dependency, ReadableSignal, Subscriber } from './signal'\n\nexport interface ReactivityDebugHooks {\n ownerCreated?(owner: Owner): void\n ownerNamed?(owner: Owner, name: string): void\n ownerDisposed?(owner: Owner): void\n signalCreated?(signal: ReadableSignal<unknown>, owner: Owner | null): void\n signalNamed?(signal: ReadableSignal<unknown>, name: string): void\n signalRead?(signal: ReadableSignal<unknown>, subscriber: Subscriber): void\n signalChanged?(signal: ReadableSignal<unknown>, previousValue: unknown, nextValue: unknown): void\n signalDisposed?(signal: ReadableSignal<unknown>): void\n dependencyTracked?(dependency: Dependency, subscriber: Subscriber): void\n dependencyUntracked?(dependency: Dependency, subscriber: Subscriber): void\n effectCreated?(effect: Effect, owner: Owner | null): void\n effectInvalidated?(effect: Effect): void\n effectRunStart?(effect: Effect): void\n effectRunEnd?(effect: Effect, error?: unknown, handled?: boolean): void\n effectDisposed?(effect: Effect): void\n memoCreated?(signal: ReadableSignal<unknown>, subscriber: Subscriber, owner: Owner | null): void\n memoInvalidated?(signal: ReadableSignal<unknown>): void\n flushStart?(): void\n flushEnd?(): void\n}\n\nlet activeDebugHooks: ReactivityDebugHooks | null = null\nconst signalNames = new WeakMap<object, string>()\n\nexport function setDebugHooks(hooks: ReactivityDebugHooks | null): ReactivityDebugHooks | null {\n const previous = activeDebugHooks\n activeDebugHooks = hooks\n return previous\n}\n\nexport function getDebugHooks(): ReactivityDebugHooks | null {\n return activeDebugHooks\n}\n\n/** 热路径守卫:无 hooks 时跳过 invokeDebug 调用,避免 rest 参数数组分配。 */\nexport function hasDebugHooks(): boolean {\n return activeDebugHooks !== null\n}\n\nexport function setSignalDebugName(signal: ReadableSignal<unknown>, name: string): void {\n signalNames.set(signal, name)\n invokeDebug('signalNamed', signal, name)\n}\n\nexport function getSignalDebugName(signal: ReadableSignal<unknown>): string | undefined {\n return signalNames.get(signal)\n}\n\nexport function invokeDebug<K extends keyof ReactivityDebugHooks>(\n name: K,\n ...args: Parameters<NonNullable<ReactivityDebugHooks[K]>>\n): void {\n const callback = activeDebugHooks?.[name] as ((...values: unknown[]) => void) | undefined\n if (!callback) return\n try {\n callback(...args)\n } catch {\n // Debug tooling must never change application behavior.\n }\n}\n","import { invokeDebug, hasDebugHooks } from './debug'\n\nexport interface Owner {\n readonly id: string\n readonly parent: Owner | null\n readonly children: readonly Owner[]\n readonly depth: number\n readonly disposed: boolean\n run<T>(fn: () => T): T\n addCleanup(cleanup: () => void): void\n onDispose(cleanup: () => void): void\n onError(handler: (error: unknown) => void): () => void\n handleError(error: unknown): boolean\n dispose(): void\n}\n\nlet currentOwner: Owner | null = null\nlet nextOwnerId = 1\nconst ownerNames = new WeakMap<Owner, string>()\n\nexport function createOwner(): Owner {\n const parent = currentOwner\n let disposed = parent?.disposed ?? false\n const children: Owner[] = []\n const cleanups: Array<() => void> = []\n const errorHandlers = new Set<(error: unknown) => void>()\n\n const owner: Owner = {\n id: `owner-${nextOwnerId++}`,\n parent,\n children,\n depth: (parent?.depth ?? -1) + 1,\n\n get disposed(): boolean {\n return disposed\n },\n\n run<T>(fn: () => T): T {\n if (disposed) throw new Error('Vobs: 已销毁的 Owner 不能继续运行')\n const previous = currentOwner\n currentOwner = owner\n try {\n return fn()\n } finally {\n currentOwner = previous\n }\n },\n\n addCleanup(cleanup: () => void): void {\n if (disposed) {\n cleanup()\n return\n }\n cleanups.push(cleanup)\n },\n\n onDispose(cleanup: () => void): void {\n owner.addCleanup(cleanup)\n },\n\n onError(handler: (error: unknown) => void): () => void {\n errorHandlers.add(handler)\n const remove = () => errorHandlers.delete(handler)\n owner.addCleanup(remove)\n return remove\n },\n\n handleError(error: unknown): boolean {\n for (const handler of [...errorHandlers].reverse()) {\n try {\n handler(error)\n return true\n } catch (handlerError) {\n return parent?.handleError(handlerError) ?? false\n }\n }\n return parent?.handleError(error) ?? false\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n for (const child of [...children]) child.dispose()\n children.length = 0\n\n let firstError: unknown\n for (let index = cleanups.length - 1; index >= 0; index--) {\n try {\n cleanups[index]()\n } catch (error) {\n firstError ??= error\n }\n }\n cleanups.length = 0\n\n if (parent) {\n const index = parent.children.indexOf(owner)\n if (index >= 0) (parent.children as Owner[]).splice(index, 1)\n }\n if (hasDebugHooks()) invokeDebug('ownerDisposed', owner)\n if (firstError) throw firstError\n }\n }\n\n if (parent && !parent.disposed) (parent.children as Owner[]).push(owner)\n if (hasDebugHooks()) invokeDebug('ownerCreated', owner)\n return owner\n}\n\nexport function setOwnerDebugName(owner: Owner, name: string): void {\n ownerNames.set(owner, name)\n if (hasDebugHooks()) invokeDebug('ownerNamed', owner, name)\n}\n\nexport function getOwnerDebugName(owner: Owner): string | undefined {\n return ownerNames.get(owner)\n}\n\nexport function getCurrentOwner(): Owner | null {\n return currentOwner\n}\n\n/** Re-enter an Owner for an explicitly captured asynchronous continuation. */\nexport function runWithOwner<T>(owner: Owner, fn: () => T): T {\n return owner.run(fn)\n}\n\nexport function onDispose(cleanup: () => void): void {\n const owner = getCurrentOwner()\n if (!owner) throw new Error('Vobs: onDispose 必须在 Owner 作用域内调用')\n owner.onDispose(cleanup)\n}\n","import { getCurrentOwner } from './owner'\nimport { invokeDebug, hasDebugHooks, setSignalDebugName } from './debug'\n\nexport interface Dependency {\n unsubscribe(subscriber: Subscriber): void\n}\n\nexport interface Subscriber {\n readonly dependencies: Set<Dependency>\n readonly disposed: boolean\n notify(): void\n}\n\n/** 只读信号:派生值(memo)与只读上下文的最小契约,只能订阅与读取。 */\nexport interface ReadableSignal<T> extends Dependency {\n readonly value: T\n dispose(): void\n}\n\n/** 可写信号:state() 的返回类型。`set` 与 `.value =` 赋值语义完全一致。 */\nexport interface Signal<T> extends ReadableSignal<T> {\n value: T\n set(next: T): void\n}\n\nlet currentSubscriber: Subscriber | null = null\n\nexport function getCurrentSubscriber(): Subscriber | null {\n return currentSubscriber\n}\n\nexport function setCurrentSubscriber(subscriber: Subscriber | null): void {\n currentSubscriber = subscriber\n}\n\nexport function untrack<T>(fn: () => T): T {\n const previous = currentSubscriber\n currentSubscriber = null\n try {\n return fn()\n } finally {\n currentSubscriber = previous\n }\n}\n\nexport function trackDependency(dependency: Dependency): void {\n if (!currentSubscriber || currentSubscriber.disposed) return\n const added = !currentSubscriber.dependencies.has(dependency)\n currentSubscriber.dependencies.add(dependency)\n if (added && hasDebugHooks()) invokeDebug('dependencyTracked', dependency, currentSubscriber)\n}\n\n/**\n * Create a reactive state signal.\n *\n * State uses identity (`Object.is`) change detection. Objects and arrays are\n * intentionally shallow: mutating a nested property in place does not notify\n * subscribers; assign a new object/array to `value` to publish the change.\n *\n * The optional debug name is metadata for inspection tools only. It does not\n * affect subscriptions, scheduling, serialization, or the signal contract.\n */\nexport function state<T>(initialValue: T, debugName?: string): Signal<T> {\n let value = initialValue\n let disposed = false\n const subscribers = new Set<Subscriber>()\n\n const signalInstance: Signal<T> = {\n get value(): T {\n const subscriber = getCurrentSubscriber()\n if (subscriber && !subscriber.disposed) {\n subscribers.add(subscriber)\n if (hasDebugHooks()) invokeDebug('signalRead', signalInstance as Signal<unknown>, subscriber)\n trackDependency(signalInstance)\n }\n return value\n },\n\n set value(nextValue: T) {\n if (disposed || Object.is(value, nextValue)) return\n const previousValue = value\n value = nextValue\n if (hasDebugHooks()) invokeDebug('signalChanged', signalInstance as Signal<unknown>, previousValue, nextValue)\n for (const subscriber of [...subscribers]) subscriber.notify()\n },\n\n unsubscribe(subscriber: Subscriber): void {\n subscribers.delete(subscriber)\n },\n\n // 与 `.value =` 赋值同一条路径:判等短路、debug hook、notify 全部一致。\n // 以闭包实现,可安全地作为回调直接传递(无 this 绑定问题)。\n set(next: T): void {\n signalInstance.value = next\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n subscribers.clear()\n if (hasDebugHooks()) invokeDebug('signalDisposed', signalInstance as Signal<unknown>)\n }\n }\n\n const owner = getCurrentOwner()\n owner?.addCleanup(signalInstance.dispose)\n if (hasDebugHooks()) invokeDebug('signalCreated', signalInstance as Signal<unknown>, owner)\n if (debugName?.trim()) setSignalDebugName(signalInstance as Signal<unknown>, debugName.trim())\n return signalInstance\n}\n","import type { Effect } from './effect'\nimport { hasDebugHooks, invokeDebug } from './debug'\n\nexport class Scheduler {\n private readonly dirtyEffects = new Set<Effect>()\n private readonly lowPriorityEffects = new Set<Effect>()\n // flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。\n private readonly normalBuffer: Effect[] = []\n private readonly lowBuffer: Effect[] = []\n private flushing = false\n private scheduled = false\n private batchDepth = 0\n\n schedule(effect: Effect): void {\n if (effect.disposed) return\n this.dirtyEffects.add(effect)\n this.lowPriorityEffects.delete(effect)\n this.ensureScheduled()\n }\n\n /** Queue an effect behind normal updates while preserving deterministic order. */\n scheduleLow(effect: Effect): void {\n if (effect.disposed) return\n if (!this.dirtyEffects.has(effect)) this.lowPriorityEffects.add(effect)\n this.ensureScheduled()\n }\n\n private ensureScheduled(): void {\n if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {\n this.scheduled = true\n queueMicrotask(() => {\n this.scheduled = false\n this.flush()\n })\n }\n }\n\n remove(effect: Effect): void {\n this.dirtyEffects.delete(effect)\n this.lowPriorityEffects.delete(effect)\n }\n\n batch<T>(fn: () => T): T {\n this.batchDepth++\n try {\n return fn()\n } finally {\n this.batchDepth--\n if (this.batchDepth === 0) this.flush()\n }\n }\n\n flush(): void {\n if (this.flushing || this.batchDepth > 0) return\n this.flushing = true\n const debugEnabled = hasDebugHooks()\n if (debugEnabled) invokeDebug('flushStart')\n let rounds = 0\n let firstError: unknown\n let hasError = false\n try {\n while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {\n if (++rounds > 100) {\n this.dirtyEffects.clear()\n this.lowPriorityEffects.clear()\n throw new Error('Vobs: 响应式更新超过 100 轮,可能存在循环依赖')\n }\n\n // normal 先、low 后,两组分别排序:与旧的合并排序语义一致\n // (旧比较器里 low 优先级本就高于 depth),但消除了比较器内的 Set 查找。\n this.collectRunnable(this.dirtyEffects, this.normalBuffer)\n this.collectRunnable(this.lowPriorityEffects, this.lowBuffer)\n sortEffects(this.normalBuffer)\n sortEffects(this.lowBuffer)\n for (const effect of this.normalBuffer) {\n try {\n effect.run()\n } catch (error) {\n // Isolate one failed effect from the rest of the flush. Re-throw\n // the first error after all runnable effects have had a chance.\n if (!hasError) {\n firstError = error\n hasError = true\n }\n }\n }\n for (const effect of this.lowBuffer) {\n try {\n effect.run()\n } catch (error) {\n if (!hasError) {\n firstError = error\n hasError = true\n }\n }\n }\n this.normalBuffer.length = 0\n this.lowBuffer.length = 0\n }\n } finally {\n this.normalBuffer.length = 0\n this.lowBuffer.length = 0\n this.flushing = false\n if (debugEnabled) invokeDebug('flushEnd')\n }\n if (hasError) throw firstError\n }\n\n /** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */\n private collectRunnable(source: Set<Effect>, target: Effect[]): void {\n for (const effect of source) {\n if (!effect.disposed) target.push(effect)\n }\n source.clear()\n }\n}\n\n/** depth 深的先跑(子 effect 先于父),同深度按创建顺序。 */\nfunction sortEffects(effects: Effect[]): void {\n if (effects.length > 1) {\n effects.sort((a, b) => b.depth - a.depth || a.order - b.order)\n }\n}\n\nexport const scheduler = new Scheduler()\n\nexport function batch<T>(fn: () => T): T {\n return scheduler.batch(fn)\n}\n\n/** Schedule a low-priority effect explicitly. */\nexport function scheduleLow(effect: Effect): void {\n effect.scheduleLow()\n}\n","import type { VobsNode } from './fragment'\n\nexport type HmrComponent<Props extends object = Record<string, unknown>> =\n (props: Props) => VobsNode\n\nexport interface HmrStateStore {\n get<T>(key: string, initial: T | (() => T)): T\n set<T>(key: string, value: T): void\n has(key: string): boolean\n delete(key: string): void\n clear(): void\n}\n\nexport interface HmrInstance {\n node: VobsNode\n parent: Node | null\n refresh(): void\n}\n\ninterface HmrModuleState {\n readonly components: Map<string, HmrComponent>\n readonly state: Map<string, unknown>\n readonly instances: Set<HmrInstance>\n}\n\ninterface HmrGlobal {\n modules: Map<string, HmrModuleState>\n}\n\nconst globalTarget = globalThis as typeof globalThis & { __VOBS_HMR__?: HmrGlobal }\nconst hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: new Map<string, HmrModuleState>() }\nglobalTarget.__VOBS_HMR__ = hmrGlobal\n\nexport function resolveComponent<Props extends object>(\n component: HmrComponent<Props>,\n moduleId: string,\n exportName: string\n): HmrComponent<Props> {\n const module = getModule(moduleId)\n const existing = module.components.get(exportName)\n if (existing) return existing as HmrComponent<Props>\n\n const proxy = ((props: Props) => {\n const current = (proxy as HmrComponent<Props> & { current: HmrComponent<Props> }).current\n return current(props)\n }) as HmrComponent<Props> & { current: HmrComponent<Props> }\n proxy.current = component\n Object.defineProperties(proxy, {\n displayName: { configurable: true, value: component.name || exportName },\n hmrKey: { configurable: false, value: `${moduleId}:${exportName}` }\n })\n module.components.set(exportName, proxy as HmrComponent)\n return proxy\n}\n\nexport function updateHmrModule(_moduleId: string, nextModule: Record<string, unknown>): void {\n const modules = [...hmrGlobal.modules.values()]\n for (const module of modules) {\n let changed = false\n for (const [name, proxy] of module.components) {\n const next = nextModule[name]\n if (typeof next !== 'function') continue\n const hmrProxy = proxy as HmrComponent & { current: HmrComponent; displayName?: string }\n hmrProxy.current = next as HmrComponent\n Object.defineProperty(hmrProxy, 'displayName', { configurable: true, value: next.name || name })\n changed = true\n }\n if (!changed) continue\n for (const instance of module.instances) {\n try {\n instance.refresh()\n } catch {\n // HMR failures remain application errors on the next normal render.\n }\n }\n }\n}\n\nexport function disposeHmrModule(_moduleId: string): void {\n // State and component proxies intentionally survive module disposal.\n}\n\nexport function createHmrStateStore(moduleId: string): HmrStateStore {\n const state = getModule(moduleId).state\n return {\n get<T>(key: string, initial: T | (() => T)): T {\n if (!state.has(key)) state.set(key, typeof initial === 'function' ? (initial as () => T)() : initial)\n return state.get(key) as T\n },\n set<T>(key: string, value: T): void {\n state.set(key, value)\n },\n has: key => state.has(key),\n delete: key => { state.delete(key) },\n clear: () => { state.clear() }\n }\n}\n\nexport function registerHmrInstance(moduleId: string, instance: HmrInstance): () => void {\n const instances = getModule(moduleId).instances\n instances.add(instance)\n return () => instances.delete(instance)\n}\n\nexport function markHmrInstanceMounted(node: VobsNode, parent: Node): void {\n const instance = hmrInstances.get(node as object)\n if (instance) instance.parent = parent\n}\n\nfunction getModule(moduleId: string): HmrModuleState {\n let module = hmrGlobal.modules.get(moduleId)\n if (!module) {\n module = { components: new Map(), state: new Map(), instances: new Set() }\n hmrGlobal.modules.set(moduleId, module)\n }\n return module\n}\n\nconst hmrInstances = new WeakMap<object, HmrInstance>()\n\nexport function associateHmrInstance(node: VobsNode, instance: HmrInstance): void {\n hmrInstances.set(node as object, instance)\n}\n","import { getCurrentOwner, type Owner } from '@vobs/reactivity'\nimport type { InjectionKey, ProvideOptions } from './app'\n\nconst ownerProviders = new WeakMap<Owner, Map<InjectionKey<unknown>, unknown>>()\n\nexport function provide<T>(key: InjectionKey<T>, value: T, options: ProvideOptions = {}): void {\n const owner = getCurrentOwner()\n if (!owner) throw new Error('Vobs: provide 必须在组件或 Owner 作用域内调用')\n provideToOwner(owner, key, value, options)\n}\n\nexport function inject<T>(key: InjectionKey<T>): T | undefined\nexport function inject<T>(key: InjectionKey<T>, fallback: T): T\nexport function inject<T>(key: InjectionKey<T>, fallback?: T): T | undefined {\n const owner = getCurrentOwner()\n const value = owner ? injectFromOwner(owner, key) : undefined\n return value === undefined ? fallback : value\n}\n\nexport function injectRequired<T>(key: InjectionKey<T>, description?: string): T {\n const value = inject(key)\n if (value === undefined) {\n throw new Error(`Vobs: 找不到必需注入项${description ? ` ${description}` : ''}`)\n }\n return value\n}\n\nexport function provideToOwner<T>(\n owner: Owner,\n key: InjectionKey<T>,\n value: T,\n options: ProvideOptions = {}\n): void {\n let providers = ownerProviders.get(owner)\n if (!providers) {\n providers = new Map<InjectionKey<unknown>, unknown>()\n ownerProviders.set(owner, providers)\n owner.onDispose(() => ownerProviders.delete(owner))\n }\n if (providers.has(key) && !options.override) {\n throw new Error(`Vobs: 注入项 ${String(key)} 已存在;如需覆盖请传入 override: true`)\n }\n providers.set(key, value)\n}\n\nexport function injectFromOwner<T>(owner: Owner, key: InjectionKey<T>): T | undefined {\n let current: Owner | null = owner\n while (current) {\n const providers = ownerProviders.get(current)\n if (providers?.has(key)) return providers.get(key) as T\n current = current.parent\n }\n return undefined\n}\n","import { createOwner, scheduler, setOwnerDebugName, type Owner } from '@vobs/reactivity'\nimport { createDOMRenderer } from '@vobs/dom'\nimport { insertBefore as insertRuntimeNode, setRenderer, type VobsFragment, type VobsRenderer } from '@vobs/runtime'\nimport { injectFromOwner, provideToOwner } from './context'\n\nexport type InjectionKey<T> = symbol & {\n readonly __vobsType?: T\n}\n\nexport interface ProvideOptions {\n override?: boolean\n}\n\nexport interface VobsPlugin {\n name: string\n version?: string\n requires?: readonly VobsPlugin[]\n optional?: readonly VobsPlugin[]\n install?: (ctx: VobsContext) => void | (() => void)\n}\n\nexport interface VobsContext {\n readonly app: VobsApp\n provide<T>(key: InjectionKey<T>, value: T, options?: ProvideOptions): void\n inject<T>(key: InjectionKey<T>): T | undefined\n injectRequired<T>(key: InjectionKey<T>, description?: string): T\n onDestroy(cleanup: () => void): void\n onError(handler: (error: unknown) => void): () => void\n}\n\nexport interface VobsConfig<\n NodeType = Node,\n TextNode extends NodeType = NodeType,\n ElementNode extends NodeType = NodeType,\n CommentNode extends NodeType = NodeType\n> {\n render: () => NodeType | VobsFragment | Node | null | undefined\n renderer?: VobsRenderer<NodeType, TextNode, ElementNode, CommentNode>\n plugins?: VobsPlugin[]\n /** Optional application-level error observer. Observers are isolated from the app. */\n onError?: (error: unknown) => void\n}\n\nexport interface VobsApp<NodeType = Node> {\n readonly mounted: boolean\n readonly destroyed: boolean\n use(plugin: VobsPlugin): VobsApp<NodeType>\n mount(target: string | NodeType): void\n hydrate(target: string | NodeType): void\n update(): void\n destroy(): void\n}\n\nexport function createInjectionKey<T>(description: string): InjectionKey<T> {\n return Symbol(description) as InjectionKey<T>\n}\n\nexport function createVobs(\n config: VobsConfig<Node, Text, Element, Comment>\n): VobsApp<Node>\nexport function createVobs<\n NodeType = Node,\n TextNode extends NodeType = NodeType,\n ElementNode extends NodeType = NodeType,\n CommentNode extends NodeType = NodeType\n>(\n config: VobsConfig<NodeType, TextNode, ElementNode, CommentNode> & {\n renderer: VobsRenderer<NodeType, TextNode, ElementNode, CommentNode>\n }\n): VobsApp<NodeType>\nexport function createVobs(\n config: VobsConfig<any, any, any, any>\n): VobsApp<any> {\n if (!config.render) throw new Error('createVobs: render 不能为空')\n\n const renderer = config.renderer ?? createDOMRenderer()\n const rootOwner: Owner = createOwner()\n setOwnerDebugName(rootOwner, 'App')\n const cleanups: Array<() => void> = []\n const errorHandlers = new Set<(error: unknown) => void>()\n const installed = new Set<string>()\n const installing = new Set<string>()\n let mounted = false\n let destroyed = false\n let container: any = null\n let app!: VobsApp<any>\n\n if (config.onError) {\n errorHandlers.add(config.onError)\n cleanups.push(() => errorHandlers.delete(config.onError!))\n }\n\n const context: VobsContext = {\n get app(): VobsApp<any> {\n return app\n },\n\n provide<T>(key: InjectionKey<T>, value: T, options: ProvideOptions = {}): void {\n provideToOwner(rootOwner, key, value, options)\n },\n\n inject<T>(key: InjectionKey<T>): T | undefined {\n return injectFromOwner(rootOwner, key)\n },\n\n injectRequired<T>(key: InjectionKey<T>, description?: string): T {\n const value = injectFromOwner(rootOwner, key)\n if (value === undefined) {\n throw new Error(`Vobs: 找不到必需注入项${description ? ` ${description}` : ''}`)\n }\n return value\n },\n\n onDestroy(cleanup: () => void): void {\n cleanups.push(cleanup)\n },\n\n onError(handler: (error: unknown) => void): () => void {\n errorHandlers.add(handler)\n const remove = () => errorHandlers.delete(handler)\n cleanups.push(remove)\n return remove\n }\n }\n\n function notifyError(error: unknown): void {\n for (const handler of [...errorHandlers]) {\n try {\n handler(error)\n } catch {\n // 错误处理器不能覆盖触发它的原始错误。\n }\n }\n }\n\n function installPlugin(plugin: VobsPlugin): void {\n if (installed.has(plugin.name)) return\n if (installing.has(plugin.name)) {\n throw new Error(`Vobs: 插件依赖存在循环:${plugin.name}`)\n }\n\n installing.add(plugin.name)\n try {\n for (const dependency of plugin.requires ?? []) installPlugin(dependency)\n const cleanup = plugin.install?.(context)\n if (cleanup) cleanups.push(cleanup)\n installed.add(plugin.name)\n } finally {\n installing.delete(plugin.name)\n }\n }\n\n function cleanup(clearContainer = true): unknown {\n let firstError: unknown\n for (let index = cleanups.length - 1; index >= 0; index--) {\n try {\n cleanups[index]()\n } catch (error) {\n firstError ??= error\n }\n }\n cleanups.length = 0\n\n try {\n rootOwner.dispose()\n } catch (error) {\n firstError ??= error\n }\n\n if (container && clearContainer) {\n try {\n renderer.clear(container)\n } catch (error) {\n firstError ??= error\n }\n }\n return firstError\n }\n\n function start(target: string | any, hydrating: boolean): void {\n if (destroyed) throw new Error('Vobs: 已销毁的应用不能挂载')\n if (mounted) return\n\n container = typeof target === 'string' ? document.querySelector(target) : target\n if (!container) throw new Error(`mount: 目标不存在: ${target}`)\n if (hydrating && !renderer.beginHydration) {\n throw new Error('Vobs: 当前渲染器不支持 Hydration')\n }\n\n setRenderer(renderer)\n try {\n if (hydrating) renderer.beginHydration?.()\n const rootNode = rootOwner.run(config.render)\n if (!hydrating) renderer.clear(container)\n if (rootNode) insertRuntimeNode(container, rootNode as any, null)\n if (hydrating) renderer.completeHydration?.()\n mounted = true\n } catch (error) {\n notifyError(error)\n const cleanupError = cleanup(!hydrating)\n destroyed = true\n throw cleanupError ?? error\n }\n }\n\n app = {\n get mounted(): boolean {\n return mounted\n },\n\n get destroyed(): boolean {\n return destroyed\n },\n\n use(plugin: VobsPlugin): VobsApp<any> {\n if (destroyed) throw new Error('Vobs: 已销毁的应用不能安装插件')\n installPlugin(plugin)\n return app\n },\n\n mount(target: string | any): void {\n start(target, false)\n },\n\n hydrate(target: string | any): void {\n start(target, true)\n },\n\n update(): void {\n if (destroyed) throw new Error('Vobs: 已销毁的应用不能更新')\n try {\n scheduler.flush()\n } catch (error) {\n notifyError(error)\n throw error\n }\n },\n\n destroy(): void {\n if (destroyed) return\n try {\n const cleanupError = cleanup()\n if (cleanupError) {\n notifyError(cleanupError)\n throw cleanupError\n }\n } finally {\n mounted = false\n destroyed = true\n }\n }\n }\n\n try {\n for (const plugin of config.plugins ?? []) app.use(plugin)\n } catch (error) {\n notifyError(error)\n cleanup()\n destroyed = true\n throw error\n }\n\n return app\n}\n","import { getCurrentOwner, onDispose, state, type Signal } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type DictName = string\nexport type DictValue = string | number\n\nexport interface DictItem {\n readonly value: DictValue\n readonly label: string\n readonly disabled?: boolean\n readonly [key: string]: unknown\n}\n\nexport type DictItems = readonly DictItem[]\nexport type DictData = Readonly<Record<DictName, DictItems>>\nexport type DictLoader = (name: DictName, signal: AbortSignal) => DictItems | PromiseLike<DictItems>\n\nexport interface DictQuery {\n readonly name: DictName\n readonly items: Signal<DictItems>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly updatedAt: Signal<number>\n load(options?: { readonly force?: boolean }): Promise<DictItems>\n invalidate(): void\n}\n\nexport interface DictDehydratedEntry {\n readonly name: DictName\n readonly items: DictItems\n readonly updatedAt: number\n}\n\nexport interface DictDehydratedState {\n readonly version: 1\n readonly entries: readonly DictDehydratedEntry[]\n}\n\nexport interface DictOptions {\n readonly data?: DictData\n readonly loader?: DictLoader\n readonly staleTime?: number\n readonly now?: () => number\n readonly onError?: (error: DictError, name: DictName) => void\n}\n\nexport interface DictPluginOptions extends DictOptions {\n readonly dict?: DictContext\n}\n\nexport interface DictContext {\n readonly data: Signal<DictData>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly staleTime: number\n get(name: DictName): DictItems\n find(name: DictName, value: DictValue): DictItem | undefined\n label(name: DictName, value: DictValue, fallback?: string): string\n query(name: DictName): DictQuery\n load(name: DictName, options?: { readonly force?: boolean }): Promise<DictItems>\n set(name: DictName, items: DictItems): void\n invalidate(name?: DictName): void\n dehydrate(): DictDehydratedState\n hydrate(snapshot: unknown): void\n dispose(): void\n}\n\nexport type DictErrorCode =\n | 'DICT_CONTEXT_MISSING'\n | 'DICT_CONTEXT_DISPOSED'\n | 'INVALID_DICT_NAME'\n | 'INVALID_DICT_ITEMS'\n | 'DICT_LOADER_MISSING'\n | 'DICT_LOAD_FAILED'\n | 'INVALID_DEHYDRATED_STATE'\n\nexport class DictError extends Error {\n readonly code: DictErrorCode\n readonly cause: unknown\n\n constructor(code: DictErrorCode, message: string, cause?: unknown) {\n super(message)\n this.name = 'DictError'\n this.code = code\n this.cause = cause\n }\n}\n\nexport const DICT_KEY: InjectionKey<DictContext> = createInjectionKey<DictContext>('vobs.dict')\n\nconst EMPTY_ITEMS: DictItems = Object.freeze([])\n\ninterface DictEntry extends DictQuery {\n controller: AbortController | null\n inFlight: Promise<DictItems> | null\n revision: number\n}\n\nexport function createDict(options: DictOptions = {}): DictContext {\n const staleTime = validateStaleTime(options.staleTime ?? 5 * 60 * 1000)\n const now = options.now ?? Date.now\n const initial = normalizeData(options.data ?? {})\n const data = state<DictData>(initial)\n const loading = state(false)\n const error = state<Error | null>(null)\n const entries = new Map<DictName, DictEntry>()\n let disposed = false\n\n for (const [name, items] of Object.entries(initial)) {\n const entry = createEntry(name, items, now())\n entries.set(name, entry)\n }\n\n const context: DictContext = {\n data,\n loading,\n error,\n staleTime,\n\n get(name): DictItems {\n ensureActive()\n return data.value[validateName(name)] ?? EMPTY_ITEMS\n },\n\n find(name, value): DictItem | undefined {\n ensureActive()\n return context.get(name).find(item => item.value === value)\n },\n\n label(name, value, fallback): string {\n ensureActive()\n return context.find(name, value)?.label ?? fallback ?? String(value)\n },\n\n query(name): DictQuery {\n ensureActive()\n return getEntry(validateName(name))\n },\n\n load(name, loadOptions = {}): Promise<DictItems> {\n ensureActive()\n const entry = getEntry(validateName(name))\n if (!loadOptions.force && isFresh(entry)) return Promise.resolve(entry.items.value)\n if (entry.inFlight) return entry.inFlight\n if (!options.loader) {\n const loadError = new DictError('DICT_LOADER_MISSING', `Vobs Dict: ${entry.name} 未配置 loader`)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n return Promise.reject(loadError)\n }\n\n const revision = ++entry.revision\n const controller = new AbortController()\n entry.controller = controller\n entry.loading.value = true\n refreshLoading()\n const request = Promise.resolve()\n .then(() => options.loader!(entry.name, controller.signal))\n .then(items => {\n if (disposed || revision !== entry.revision) return entry.items.value\n const normalized = normalizeItems(items)\n commit(entry, normalized, now(), false)\n return normalized\n })\n .catch(reason => {\n if (disposed || revision !== entry.revision || isAbortError(reason)) return entry.items.value\n const loadError = reason instanceof DictError\n ? reason\n : new DictError('DICT_LOAD_FAILED', `Vobs Dict: ${entry.name} 加载失败`, reason)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n throw loadError\n })\n .finally(() => {\n if (revision !== entry.revision) return\n entry.inFlight = null\n entry.controller = null\n entry.loading.value = false\n refreshLoading()\n })\n entry.inFlight = request\n return request\n },\n\n set(name, items): void {\n ensureActive()\n commit(getEntry(validateName(name)), normalizeItems(items), now())\n },\n\n invalidate(name): void {\n ensureActive()\n if (name === undefined) {\n for (const entry of entries.values()) invalidateEntry(entry)\n return\n }\n invalidateEntry(getEntry(validateName(name)))\n },\n\n dehydrate(): DictDehydratedState {\n ensureActive()\n return {\n version: 1,\n entries: Object.freeze([...entries.values()]\n .filter(entry => entry.updatedAt.value > 0)\n .map(entry => Object.freeze({\n name: entry.name,\n items: entry.items.value,\n updatedAt: entry.updatedAt.value\n })))\n }\n },\n\n hydrate(snapshot): void {\n ensureActive()\n const restored = parseDehydratedState(snapshot)\n const nextData: Record<DictName, DictItems> = {}\n const restoredNames = new Set<DictName>()\n for (const item of restored.entries) {\n const entry = getEntry(item.name)\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = item.items\n entry.error.value = null\n entry.updatedAt.value = item.updatedAt\n nextData[item.name] = item.items\n restoredNames.add(item.name)\n }\n for (const [name, entry] of entries) {\n if (restoredNames.has(name)) continue\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = EMPTY_ITEMS\n entry.error.value = null\n entry.updatedAt.value = 0\n }\n data.value = Object.freeze(nextData)\n error.value = null\n refreshLoading()\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n for (const entry of entries.values()) {\n entry.controller?.abort()\n entry.items.dispose()\n entry.loading.dispose()\n entry.error.dispose()\n entry.updatedAt.dispose()\n }\n entries.clear()\n data.dispose()\n loading.dispose()\n error.dispose()\n }\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function getEntry(name: DictName): DictEntry {\n const existing = entries.get(name)\n if (existing) return existing\n const entry = createEntry(name, data.value[name] ?? EMPTY_ITEMS, 0)\n entries.set(name, entry)\n return entry\n }\n\n function createEntry(name: DictName, items: DictItems, updatedAt: number): DictEntry {\n const entry = {\n name,\n items: state(items),\n loading: state(false),\n error: state<Error | null>(null),\n updatedAt: state(updatedAt),\n controller: null,\n inFlight: null,\n revision: 0,\n load: (loadOptions?: { readonly force?: boolean }) => context.load(name, loadOptions),\n invalidate: () => context.invalidate(name)\n } as DictEntry\n return entry\n }\n\n function commit(entry: DictEntry, items: DictItems, updatedAt: number, replaceRequest = true): void {\n if (replaceRequest) {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n }\n entry.items.value = items\n entry.error.value = null\n entry.updatedAt.value = updatedAt\n data.value = Object.freeze({ ...data.value, [entry.name]: items })\n error.value = null\n refreshLoading()\n }\n\n function invalidateEntry(entry: DictEntry): void {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.updatedAt.value = 0\n refreshLoading()\n }\n\n function isFresh(entry: DictEntry): boolean {\n return entry.updatedAt.value > 0 && now() - entry.updatedAt.value < staleTime\n }\n\n function refreshLoading(): void {\n loading.value = [...entries.values()].some(entry => entry.loading.value)\n }\n\n function report(dictError: DictError, name: DictName): void {\n try { options.onError?.(dictError, name) } catch { /* observers cannot break dictionary state */ }\n }\n\n function ensureActive(): void {\n if (disposed) throw new DictError('DICT_CONTEXT_DISPOSED', 'Vobs Dict: 上下文已销毁')\n }\n}\n\nexport function dictPlugin(options: DictPluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/dict',\n version: '0.1.0',\n install(context) {\n const ownedDict = options.dict ? undefined : createDict(options)\n context.provide(DICT_KEY, options.dict ?? ownedDict!)\n return () => ownedDict?.dispose()\n }\n }\n}\n\nexport function useDict(): DictContext {\n const dict = inject(DICT_KEY)\n if (!dict) throw new DictError('DICT_CONTEXT_MISSING', 'Vobs Dict: 找不到上下文,请安装 dictPlugin')\n return dict\n}\n\nfunction validateName(name: string): DictName {\n if (typeof name !== 'string' || name.trim() === '') {\n throw new DictError('INVALID_DICT_NAME', 'Vobs Dict: 字典名必须是非空字符串')\n }\n return name\n}\n\nfunction validateStaleTime(value: number): number {\n if (!Number.isFinite(value) || value < 0) {\n throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: staleTime 必须是大于等于 0 的有限数字')\n }\n return value\n}\n\nfunction normalizeData(data: DictData): DictData {\n const normalized: Record<DictName, DictItems> = {}\n for (const [name, items] of Object.entries(data)) normalized[validateName(name)] = normalizeItems(items)\n return Object.freeze(normalized)\n}\n\nfunction normalizeItems(items: unknown): DictItems {\n if (!Array.isArray(items)) throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: 字典项必须是数组')\n return Object.freeze(items.map((item, index) => {\n if (!item || typeof item !== 'object'\n || (typeof (item as DictItem).value !== 'string' && typeof (item as DictItem).value !== 'number')\n || typeof (item as DictItem).label !== 'string') {\n throw new DictError('INVALID_DICT_ITEMS', `Vobs Dict: 第 ${index + 1} 个字典项必须包含 value 和 label`)\n }\n return Object.freeze({ ...item }) as DictItem\n }))\n}\n\nfunction parseDehydratedState(snapshot: unknown): DictDehydratedState {\n let value: unknown = snapshot\n if (typeof snapshot === 'string') {\n try { value = JSON.parse(snapshot) } catch {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态不是有效 JSON')\n }\n }\n if (!value || typeof value !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态格式无效')\n }\n const candidate = value as Partial<DictDehydratedState>\n if (candidate.version !== 1 || !Array.isArray(candidate.entries)) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态版本或 entries 无效')\n }\n const seen = new Set<string>()\n const entries = candidate.entries.map(entry => {\n if (!entry || typeof entry !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目无效')\n }\n const name = validateName((entry as Partial<DictDehydratedEntry>).name as string)\n const updatedAt = (entry as Partial<DictDehydratedEntry>).updatedAt\n if (seen.has(name) || typeof updatedAt !== 'number' || !Number.isFinite(updatedAt) || updatedAt < 0) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目字段无效')\n }\n seen.add(name)\n return Object.freeze({\n name,\n items: normalizeItems((entry as Partial<DictDehydratedEntry>).items),\n updatedAt\n })\n })\n return { version: 1, entries: Object.freeze(entries) }\n}\n\nfunction isAbortError(value: unknown): boolean {\n return Boolean(value) && typeof value === 'object' && (value as { name?: unknown }).name === 'AbortError'\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getCurrentOwner, onDispose, state, type Signal } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type DictName = string\nexport type DictValue = string | number\n\nexport interface DictItem {\n readonly value: DictValue\n readonly label: string\n readonly disabled?: boolean\n readonly [key: string]: unknown\n}\n\nexport type DictItems = readonly DictItem[]\nexport type DictData = Readonly<Record<DictName, DictItems>>\nexport type DictLoader = (name: DictName, signal: AbortSignal) => DictItems | PromiseLike<DictItems>\n\nexport interface DictQuery {\n readonly name: DictName\n readonly items: Signal<DictItems>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly updatedAt: Signal<number>\n load(options?: { readonly force?: boolean }): Promise<DictItems>\n invalidate(): void\n}\n\nexport interface DictDehydratedEntry {\n readonly name: DictName\n readonly items: DictItems\n readonly updatedAt: number\n}\n\nexport interface DictDehydratedState {\n readonly version: 1\n readonly entries: readonly DictDehydratedEntry[]\n}\n\nexport interface DictOptions {\n readonly data?: DictData\n readonly loader?: DictLoader\n readonly staleTime?: number\n readonly now?: () => number\n readonly onError?: (error: DictError, name: DictName) => void\n}\n\nexport interface DictPluginOptions extends DictOptions {\n readonly dict?: DictContext\n}\n\nexport interface DictContext {\n readonly data: Signal<DictData>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly staleTime: number\n get(name: DictName): DictItems\n find(name: DictName, value: DictValue): DictItem | undefined\n label(name: DictName, value: DictValue, fallback?: string): string\n query(name: DictName): DictQuery\n load(name: DictName, options?: { readonly force?: boolean }): Promise<DictItems>\n set(name: DictName, items: DictItems): void\n invalidate(name?: DictName): void\n dehydrate(): DictDehydratedState\n hydrate(snapshot: unknown): void\n dispose(): void\n}\n\nexport type DictErrorCode =\n | 'DICT_CONTEXT_MISSING'\n | 'DICT_CONTEXT_DISPOSED'\n | 'INVALID_DICT_NAME'\n | 'INVALID_DICT_ITEMS'\n | 'DICT_LOADER_MISSING'\n | 'DICT_LOAD_FAILED'\n | 'INVALID_DEHYDRATED_STATE'\n\nexport class DictError extends Error {\n readonly code: DictErrorCode\n readonly cause: unknown\n\n constructor(code: DictErrorCode, message: string, cause?: unknown) {\n super(message)\n this.name = 'DictError'\n this.code = code\n this.cause = cause\n }\n}\n\nexport const DICT_KEY: InjectionKey<DictContext> = createInjectionKey<DictContext>('vobs.dict')\n\nconst EMPTY_ITEMS: DictItems = Object.freeze([])\n\ninterface DictEntry extends DictQuery {\n controller: AbortController | null\n inFlight: Promise<DictItems> | null\n revision: number\n}\n\nexport function createDict(options: DictOptions = {}): DictContext {\n const staleTime = validateStaleTime(options.staleTime ?? 5 * 60 * 1000)\n const now = options.now ?? Date.now\n const initial = normalizeData(options.data ?? {})\n const data = state<DictData>(initial)\n const loading = state(false)\n const error = state<Error | null>(null)\n const entries = new Map<DictName, DictEntry>()\n let disposed = false\n\n for (const [name, items] of Object.entries(initial)) {\n const entry = createEntry(name, items, now())\n entries.set(name, entry)\n }\n\n const context: DictContext = {\n data,\n loading,\n error,\n staleTime,\n\n get(name): DictItems {\n ensureActive()\n return data.value[validateName(name)] ?? EMPTY_ITEMS\n },\n\n find(name, value): DictItem | undefined {\n ensureActive()\n return context.get(name).find(item => item.value === value)\n },\n\n label(name, value, fallback): string {\n ensureActive()\n return context.find(name, value)?.label ?? fallback ?? String(value)\n },\n\n query(name): DictQuery {\n ensureActive()\n return getEntry(validateName(name))\n },\n\n load(name, loadOptions = {}): Promise<DictItems> {\n ensureActive()\n const entry = getEntry(validateName(name))\n if (!loadOptions.force && isFresh(entry)) return Promise.resolve(entry.items.value)\n if (entry.inFlight) return entry.inFlight\n if (!options.loader) {\n const loadError = new DictError('DICT_LOADER_MISSING', `Vobs Dict: ${entry.name} 未配置 loader`)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n return Promise.reject(loadError)\n }\n\n const revision = ++entry.revision\n const controller = new AbortController()\n entry.controller = controller\n entry.loading.value = true\n refreshLoading()\n const request = Promise.resolve()\n .then(() => options.loader!(entry.name, controller.signal))\n .then(items => {\n if (disposed || revision !== entry.revision) return entry.items.value\n const normalized = normalizeItems(items)\n commit(entry, normalized, now(), false)\n return normalized\n })\n .catch(reason => {\n if (disposed || revision !== entry.revision || isAbortError(reason)) return entry.items.value\n const loadError = reason instanceof DictError\n ? reason\n : new DictError('DICT_LOAD_FAILED', `Vobs Dict: ${entry.name} 加载失败`, reason)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n throw loadError\n })\n .finally(() => {\n if (revision !== entry.revision) return\n entry.inFlight = null\n entry.controller = null\n entry.loading.value = false\n refreshLoading()\n })\n entry.inFlight = request\n return request\n },\n\n set(name, items): void {\n ensureActive()\n commit(getEntry(validateName(name)), normalizeItems(items), now())\n },\n\n invalidate(name): void {\n ensureActive()\n if (name === undefined) {\n for (const entry of entries.values()) invalidateEntry(entry)\n return\n }\n invalidateEntry(getEntry(validateName(name)))\n },\n\n dehydrate(): DictDehydratedState {\n ensureActive()\n return {\n version: 1,\n entries: Object.freeze([...entries.values()]\n .filter(entry => entry.updatedAt.value > 0)\n .map(entry => Object.freeze({\n name: entry.name,\n items: entry.items.value,\n updatedAt: entry.updatedAt.value\n })))\n }\n },\n\n hydrate(snapshot): void {\n ensureActive()\n const restored = parseDehydratedState(snapshot)\n const nextData: Record<DictName, DictItems> = {}\n const restoredNames = new Set<DictName>()\n for (const item of restored.entries) {\n const entry = getEntry(item.name)\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = item.items\n entry.error.value = null\n entry.updatedAt.value = item.updatedAt\n nextData[item.name] = item.items\n restoredNames.add(item.name)\n }\n for (const [name, entry] of entries) {\n if (restoredNames.has(name)) continue\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = EMPTY_ITEMS\n entry.error.value = null\n entry.updatedAt.value = 0\n }\n data.value = Object.freeze(nextData)\n error.value = null\n refreshLoading()\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n for (const entry of entries.values()) {\n entry.controller?.abort()\n entry.items.dispose()\n entry.loading.dispose()\n entry.error.dispose()\n entry.updatedAt.dispose()\n }\n entries.clear()\n data.dispose()\n loading.dispose()\n error.dispose()\n }\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function getEntry(name: DictName): DictEntry {\n const existing = entries.get(name)\n if (existing) return existing\n const entry = createEntry(name, data.value[name] ?? EMPTY_ITEMS, 0)\n entries.set(name, entry)\n return entry\n }\n\n function createEntry(name: DictName, items: DictItems, updatedAt: number): DictEntry {\n const entry = {\n name,\n items: state(items),\n loading: state(false),\n error: state<Error | null>(null),\n updatedAt: state(updatedAt),\n controller: null,\n inFlight: null,\n revision: 0,\n load: (loadOptions?: { readonly force?: boolean }) => context.load(name, loadOptions),\n invalidate: () => context.invalidate(name)\n } as DictEntry\n return entry\n }\n\n function commit(entry: DictEntry, items: DictItems, updatedAt: number, replaceRequest = true): void {\n if (replaceRequest) {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n }\n entry.items.value = items\n entry.error.value = null\n entry.updatedAt.value = updatedAt\n data.value = Object.freeze({ ...data.value, [entry.name]: items })\n error.value = null\n refreshLoading()\n }\n\n function invalidateEntry(entry: DictEntry): void {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.updatedAt.value = 0\n refreshLoading()\n }\n\n function isFresh(entry: DictEntry): boolean {\n return entry.updatedAt.value > 0 && now() - entry.updatedAt.value < staleTime\n }\n\n function refreshLoading(): void {\n loading.value = [...entries.values()].some(entry => entry.loading.value)\n }\n\n function report(dictError: DictError, name: DictName): void {\n try { options.onError?.(dictError, name) } catch { /* observers cannot break dictionary state */ }\n }\n\n function ensureActive(): void {\n if (disposed) throw new DictError('DICT_CONTEXT_DISPOSED', 'Vobs Dict: 上下文已销毁')\n }\n}\n\nexport function dictPlugin(options: DictPluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/dict',\n version: '0.1.0',\n install(context) {\n const ownedDict = options.dict ? undefined : createDict(options)\n context.provide(DICT_KEY, options.dict ?? ownedDict!)\n return () => ownedDict?.dispose()\n }\n }\n}\n\nexport function useDict(): DictContext {\n const dict = inject(DICT_KEY)\n if (!dict) throw new DictError('DICT_CONTEXT_MISSING', 'Vobs Dict: 找不到上下文,请安装 dictPlugin')\n return dict\n}\n\nfunction validateName(name: string): DictName {\n if (typeof name !== 'string' || name.trim() === '') {\n throw new DictError('INVALID_DICT_NAME', 'Vobs Dict: 字典名必须是非空字符串')\n }\n return name\n}\n\nfunction validateStaleTime(value: number): number {\n if (!Number.isFinite(value) || value < 0) {\n throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: staleTime 必须是大于等于 0 的有限数字')\n }\n return value\n}\n\nfunction normalizeData(data: DictData): DictData {\n const normalized: Record<DictName, DictItems> = {}\n for (const [name, items] of Object.entries(data)) normalized[validateName(name)] = normalizeItems(items)\n return Object.freeze(normalized)\n}\n\nfunction normalizeItems(items: unknown): DictItems {\n if (!Array.isArray(items)) throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: 字典项必须是数组')\n return Object.freeze(items.map((item, index) => {\n if (!item || typeof item !== 'object'\n || (typeof (item as DictItem).value !== 'string' && typeof (item as DictItem).value !== 'number')\n || typeof (item as DictItem).label !== 'string') {\n throw new DictError('INVALID_DICT_ITEMS', `Vobs Dict: 第 ${index + 1} 个字典项必须包含 value 和 label`)\n }\n return Object.freeze({ ...item }) as DictItem\n }))\n}\n\nfunction parseDehydratedState(snapshot: unknown): DictDehydratedState {\n let value: unknown = snapshot\n if (typeof snapshot === 'string') {\n try { value = JSON.parse(snapshot) } catch {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态不是有效 JSON')\n }\n }\n if (!value || typeof value !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态格式无效')\n }\n const candidate = value as Partial<DictDehydratedState>\n if (candidate.version !== 1 || !Array.isArray(candidate.entries)) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态版本或 entries 无效')\n }\n const seen = new Set<string>()\n const entries = candidate.entries.map(entry => {\n if (!entry || typeof entry !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目无效')\n }\n const name = validateName((entry as Partial<DictDehydratedEntry>).name as string)\n const updatedAt = (entry as Partial<DictDehydratedEntry>).updatedAt\n if (seen.has(name) || typeof updatedAt !== 'number' || !Number.isFinite(updatedAt) || updatedAt < 0) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目字段无效')\n }\n seen.add(name)\n return Object.freeze({\n name,\n items: normalizeItems((entry as Partial<DictDehydratedEntry>).items),\n updatedAt\n })\n })\n return { version: 1, entries: Object.freeze(entries) }\n}\n\nfunction isAbortError(value: unknown): boolean {\n return Boolean(value) && typeof value === 'object' && (value as { name?: unknown }).name === 'AbortError'\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -1,216 +1,9 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
|
|
4
|
-
// packages/reactivity/src/debug.ts
|
|
5
|
-
var activeDebugHooks = null;
|
|
6
|
-
var signalNames = /* @__PURE__ */ new WeakMap();
|
|
7
|
-
function hasDebugHooks() {
|
|
8
|
-
return activeDebugHooks !== null;
|
|
9
|
-
}
|
|
10
|
-
__name(hasDebugHooks, "hasDebugHooks");
|
|
11
|
-
function setSignalDebugName(signal, name) {
|
|
12
|
-
signalNames.set(signal, name);
|
|
13
|
-
invokeDebug("signalNamed", signal, name);
|
|
14
|
-
}
|
|
15
|
-
__name(setSignalDebugName, "setSignalDebugName");
|
|
16
|
-
function invokeDebug(name, ...args) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
__name(invokeDebug, "invokeDebug");
|
|
20
|
-
|
|
21
|
-
// packages/reactivity/src/owner.ts
|
|
22
|
-
var currentOwner = null;
|
|
23
|
-
function getCurrentOwner() {
|
|
24
|
-
return currentOwner;
|
|
25
|
-
}
|
|
26
|
-
__name(getCurrentOwner, "getCurrentOwner");
|
|
27
|
-
function onDispose(cleanup) {
|
|
28
|
-
throw new Error("Vobs: onDispose \u5FC5\u987B\u5728 Owner \u4F5C\u7528\u57DF\u5185\u8C03\u7528");
|
|
29
|
-
}
|
|
30
|
-
__name(onDispose, "onDispose");
|
|
31
|
-
|
|
32
|
-
// packages/reactivity/src/signal.ts
|
|
33
|
-
var currentSubscriber = null;
|
|
34
|
-
function getCurrentSubscriber() {
|
|
35
|
-
return currentSubscriber;
|
|
36
|
-
}
|
|
37
|
-
__name(getCurrentSubscriber, "getCurrentSubscriber");
|
|
38
|
-
function trackDependency(dependency) {
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
__name(trackDependency, "trackDependency");
|
|
42
|
-
function state(initialValue, debugName) {
|
|
43
|
-
let value = initialValue;
|
|
44
|
-
let disposed = false;
|
|
45
|
-
const subscribers = /* @__PURE__ */ new Set();
|
|
46
|
-
const signalInstance = {
|
|
47
|
-
get value() {
|
|
48
|
-
return value;
|
|
49
|
-
},
|
|
50
|
-
set value(nextValue) {
|
|
51
|
-
if (disposed || Object.is(value, nextValue)) return;
|
|
52
|
-
value = nextValue;
|
|
53
|
-
for (const subscriber of [...subscribers]) subscriber.notify();
|
|
54
|
-
},
|
|
55
|
-
unsubscribe(subscriber) {
|
|
56
|
-
subscribers.delete(subscriber);
|
|
57
|
-
},
|
|
58
|
-
// 与 `.value =` 赋值同一条路径:判等短路、debug hook、notify 全部一致。
|
|
59
|
-
// 以闭包实现,可安全地作为回调直接传递(无 this 绑定问题)。
|
|
60
|
-
set(next) {
|
|
61
|
-
signalInstance.value = next;
|
|
62
|
-
},
|
|
63
|
-
dispose() {
|
|
64
|
-
if (disposed) return;
|
|
65
|
-
disposed = true;
|
|
66
|
-
subscribers.clear();
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
if (debugName?.trim()) setSignalDebugName(signalInstance, debugName.trim());
|
|
70
|
-
return signalInstance;
|
|
71
|
-
}
|
|
72
|
-
__name(state, "state");
|
|
73
|
-
|
|
74
|
-
// packages/reactivity/src/scheduler.ts
|
|
75
|
-
var _Scheduler = class _Scheduler {
|
|
76
|
-
constructor() {
|
|
77
|
-
this.dirtyEffects = /* @__PURE__ */ new Set();
|
|
78
|
-
this.lowPriorityEffects = /* @__PURE__ */ new Set();
|
|
79
|
-
// flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
|
|
80
|
-
this.normalBuffer = [];
|
|
81
|
-
this.lowBuffer = [];
|
|
82
|
-
this.flushing = false;
|
|
83
|
-
this.scheduled = false;
|
|
84
|
-
this.batchDepth = 0;
|
|
85
|
-
}
|
|
86
|
-
schedule(effect2) {
|
|
87
|
-
if (effect2.disposed) return;
|
|
88
|
-
this.dirtyEffects.add(effect2);
|
|
89
|
-
this.lowPriorityEffects.delete(effect2);
|
|
90
|
-
this.ensureScheduled();
|
|
91
|
-
}
|
|
92
|
-
/** Queue an effect behind normal updates while preserving deterministic order. */
|
|
93
|
-
scheduleLow(effect2) {
|
|
94
|
-
if (effect2.disposed) return;
|
|
95
|
-
if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
|
|
96
|
-
this.ensureScheduled();
|
|
97
|
-
}
|
|
98
|
-
ensureScheduled() {
|
|
99
|
-
if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
|
|
100
|
-
this.scheduled = true;
|
|
101
|
-
queueMicrotask(() => {
|
|
102
|
-
this.scheduled = false;
|
|
103
|
-
this.flush();
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
remove(effect2) {
|
|
108
|
-
this.dirtyEffects.delete(effect2);
|
|
109
|
-
this.lowPriorityEffects.delete(effect2);
|
|
110
|
-
}
|
|
111
|
-
batch(fn) {
|
|
112
|
-
this.batchDepth++;
|
|
113
|
-
try {
|
|
114
|
-
return fn();
|
|
115
|
-
} finally {
|
|
116
|
-
this.batchDepth--;
|
|
117
|
-
if (this.batchDepth === 0) this.flush();
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
flush() {
|
|
121
|
-
if (this.flushing || this.batchDepth > 0) return;
|
|
122
|
-
this.flushing = true;
|
|
123
|
-
let rounds = 0;
|
|
124
|
-
let firstError;
|
|
125
|
-
let hasError = false;
|
|
126
|
-
try {
|
|
127
|
-
while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
|
|
128
|
-
if (++rounds > 100) {
|
|
129
|
-
this.dirtyEffects.clear();
|
|
130
|
-
this.lowPriorityEffects.clear();
|
|
131
|
-
throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
|
|
132
|
-
}
|
|
133
|
-
this.collectRunnable(this.dirtyEffects, this.normalBuffer);
|
|
134
|
-
this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
|
|
135
|
-
sortEffects(this.normalBuffer);
|
|
136
|
-
sortEffects(this.lowBuffer);
|
|
137
|
-
for (const effect2 of this.normalBuffer) {
|
|
138
|
-
try {
|
|
139
|
-
effect2.run();
|
|
140
|
-
} catch (error) {
|
|
141
|
-
if (!hasError) {
|
|
142
|
-
firstError = error;
|
|
143
|
-
hasError = true;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
for (const effect2 of this.lowBuffer) {
|
|
148
|
-
try {
|
|
149
|
-
effect2.run();
|
|
150
|
-
} catch (error) {
|
|
151
|
-
if (!hasError) {
|
|
152
|
-
firstError = error;
|
|
153
|
-
hasError = true;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
this.normalBuffer.length = 0;
|
|
158
|
-
this.lowBuffer.length = 0;
|
|
159
|
-
}
|
|
160
|
-
} finally {
|
|
161
|
-
this.normalBuffer.length = 0;
|
|
162
|
-
this.lowBuffer.length = 0;
|
|
163
|
-
this.flushing = false;
|
|
164
|
-
}
|
|
165
|
-
if (hasError) throw firstError;
|
|
166
|
-
}
|
|
167
|
-
/** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
|
|
168
|
-
collectRunnable(source, target) {
|
|
169
|
-
for (const effect2 of source) {
|
|
170
|
-
if (!effect2.disposed) target.push(effect2);
|
|
171
|
-
}
|
|
172
|
-
source.clear();
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
__name(_Scheduler, "Scheduler");
|
|
176
|
-
function sortEffects(effects) {
|
|
177
|
-
if (effects.length > 1) {
|
|
178
|
-
effects.sort((a, b) => b.depth - a.depth || a.order - b.order);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
__name(sortEffects, "sortEffects");
|
|
182
|
-
|
|
183
|
-
// packages/runtime/src/hmr.ts
|
|
184
|
-
var globalTarget = globalThis;
|
|
185
|
-
var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
|
|
186
|
-
globalTarget.__VOBS_HMR__ = hmrGlobal;
|
|
187
|
-
|
|
188
|
-
// packages/vobs/src/context.ts
|
|
189
|
-
var ownerProviders = /* @__PURE__ */ new WeakMap();
|
|
190
|
-
function inject(key, fallback) {
|
|
191
|
-
const owner = getCurrentOwner();
|
|
192
|
-
const value = owner ? injectFromOwner(owner, key) : void 0;
|
|
193
|
-
return value === void 0 ? fallback : value;
|
|
194
|
-
}
|
|
195
|
-
__name(inject, "inject");
|
|
196
|
-
function injectFromOwner(owner, key) {
|
|
197
|
-
let current = owner;
|
|
198
|
-
while (current) {
|
|
199
|
-
const providers = ownerProviders.get(current);
|
|
200
|
-
if (providers?.has(key)) return providers.get(key);
|
|
201
|
-
current = current.parent;
|
|
202
|
-
}
|
|
203
|
-
return void 0;
|
|
204
|
-
}
|
|
205
|
-
__name(injectFromOwner, "injectFromOwner");
|
|
206
|
-
|
|
207
|
-
// packages/vobs/src/app.ts
|
|
208
|
-
function createInjectionKey(description) {
|
|
209
|
-
return Symbol(description);
|
|
210
|
-
}
|
|
211
|
-
__name(createInjectionKey, "createInjectionKey");
|
|
212
|
-
|
|
213
4
|
// packages/dict/src/index.ts
|
|
5
|
+
import { getCurrentOwner, onDispose, state } from "@vobs/reactivity";
|
|
6
|
+
import { createInjectionKey, inject } from "@vobs/vobs";
|
|
214
7
|
var _DictError = class _DictError extends Error {
|
|
215
8
|
constructor(code, message, cause) {
|
|
216
9
|
super(message);
|
|
@@ -368,6 +161,7 @@ function createDict(options = {}) {
|
|
|
368
161
|
error.dispose();
|
|
369
162
|
}
|
|
370
163
|
};
|
|
164
|
+
if (getCurrentOwner()) onDispose(context.dispose);
|
|
371
165
|
return context;
|
|
372
166
|
function getEntry(name) {
|
|
373
167
|
const existing = entries.get(name);
|
|
@@ -376,6 +170,7 @@ function createDict(options = {}) {
|
|
|
376
170
|
entries.set(name, entry);
|
|
377
171
|
return entry;
|
|
378
172
|
}
|
|
173
|
+
__name(getEntry, "getEntry");
|
|
379
174
|
function createEntry(name, items, updatedAt) {
|
|
380
175
|
const entry = {
|
|
381
176
|
name,
|
|
@@ -391,6 +186,7 @@ function createDict(options = {}) {
|
|
|
391
186
|
};
|
|
392
187
|
return entry;
|
|
393
188
|
}
|
|
189
|
+
__name(createEntry, "createEntry");
|
|
394
190
|
function commit(entry, items, updatedAt, replaceRequest = true) {
|
|
395
191
|
if (replaceRequest) {
|
|
396
192
|
entry.revision++;
|
|
@@ -405,6 +201,7 @@ function createDict(options = {}) {
|
|
|
405
201
|
error.value = null;
|
|
406
202
|
refreshLoading();
|
|
407
203
|
}
|
|
204
|
+
__name(commit, "commit");
|
|
408
205
|
function invalidateEntry(entry) {
|
|
409
206
|
entry.revision++;
|
|
410
207
|
entry.controller?.abort();
|
|
@@ -414,21 +211,26 @@ function createDict(options = {}) {
|
|
|
414
211
|
entry.updatedAt.value = 0;
|
|
415
212
|
refreshLoading();
|
|
416
213
|
}
|
|
214
|
+
__name(invalidateEntry, "invalidateEntry");
|
|
417
215
|
function isFresh(entry) {
|
|
418
216
|
return entry.updatedAt.value > 0 && now() - entry.updatedAt.value < staleTime;
|
|
419
217
|
}
|
|
218
|
+
__name(isFresh, "isFresh");
|
|
420
219
|
function refreshLoading() {
|
|
421
220
|
loading.value = [...entries.values()].some((entry) => entry.loading.value);
|
|
422
221
|
}
|
|
222
|
+
__name(refreshLoading, "refreshLoading");
|
|
423
223
|
function report(dictError, name) {
|
|
424
224
|
try {
|
|
425
225
|
options.onError?.(dictError, name);
|
|
426
226
|
} catch {
|
|
427
227
|
}
|
|
428
228
|
}
|
|
229
|
+
__name(report, "report");
|
|
429
230
|
function ensureActive() {
|
|
430
231
|
if (disposed) throw new DictError("DICT_CONTEXT_DISPOSED", "Vobs Dict: \u4E0A\u4E0B\u6587\u5DF2\u9500\u6BC1");
|
|
431
232
|
}
|
|
233
|
+
__name(ensureActive, "ensureActive");
|
|
432
234
|
}
|
|
433
235
|
__name(createDict, "createDict");
|
|
434
236
|
function dictPlugin(options = {}) {
|
|
@@ -519,7 +321,11 @@ function isAbortError(value) {
|
|
|
519
321
|
return Boolean(value) && typeof value === "object" && value.name === "AbortError";
|
|
520
322
|
}
|
|
521
323
|
__name(isAbortError, "isAbortError");
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
324
|
+
export {
|
|
325
|
+
DICT_KEY,
|
|
326
|
+
DictError,
|
|
327
|
+
createDict,
|
|
328
|
+
dictPlugin,
|
|
329
|
+
useDict
|
|
330
|
+
};
|
|
525
331
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../reactivity/src/debug.ts","../../reactivity/src/owner.ts","../../reactivity/src/signal.ts","../../reactivity/src/scheduler.ts","../../runtime/src/hmr.ts","../../vobs/src/context.ts","../../vobs/src/app.ts","../src/index.ts"],"names":["effect"],"mappings":"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","file":"index.js","sourcesContent":["import type { Effect } from './effect'\nimport type { Owner } from './owner'\nimport type { Dependency, ReadableSignal, Subscriber } from './signal'\n\nexport interface ReactivityDebugHooks {\n ownerCreated?(owner: Owner): void\n ownerNamed?(owner: Owner, name: string): void\n ownerDisposed?(owner: Owner): void\n signalCreated?(signal: ReadableSignal<unknown>, owner: Owner | null): void\n signalNamed?(signal: ReadableSignal<unknown>, name: string): void\n signalRead?(signal: ReadableSignal<unknown>, subscriber: Subscriber): void\n signalChanged?(signal: ReadableSignal<unknown>, previousValue: unknown, nextValue: unknown): void\n signalDisposed?(signal: ReadableSignal<unknown>): void\n dependencyTracked?(dependency: Dependency, subscriber: Subscriber): void\n dependencyUntracked?(dependency: Dependency, subscriber: Subscriber): void\n effectCreated?(effect: Effect, owner: Owner | null): void\n effectInvalidated?(effect: Effect): void\n effectRunStart?(effect: Effect): void\n effectRunEnd?(effect: Effect, error?: unknown, handled?: boolean): void\n effectDisposed?(effect: Effect): void\n memoCreated?(signal: ReadableSignal<unknown>, subscriber: Subscriber, owner: Owner | null): void\n memoInvalidated?(signal: ReadableSignal<unknown>): void\n flushStart?(): void\n flushEnd?(): void\n}\n\nlet activeDebugHooks: ReactivityDebugHooks | null = null\nconst signalNames = new WeakMap<object, string>()\n\nexport function setDebugHooks(hooks: ReactivityDebugHooks | null): ReactivityDebugHooks | null {\n const previous = activeDebugHooks\n activeDebugHooks = hooks\n return previous\n}\n\nexport function getDebugHooks(): ReactivityDebugHooks | null {\n return activeDebugHooks\n}\n\n/** 热路径守卫:无 hooks 时跳过 invokeDebug 调用,避免 rest 参数数组分配。 */\nexport function hasDebugHooks(): boolean {\n return activeDebugHooks !== null\n}\n\nexport function setSignalDebugName(signal: ReadableSignal<unknown>, name: string): void {\n signalNames.set(signal, name)\n invokeDebug('signalNamed', signal, name)\n}\n\nexport function getSignalDebugName(signal: ReadableSignal<unknown>): string | undefined {\n return signalNames.get(signal)\n}\n\nexport function invokeDebug<K extends keyof ReactivityDebugHooks>(\n name: K,\n ...args: Parameters<NonNullable<ReactivityDebugHooks[K]>>\n): void {\n const callback = activeDebugHooks?.[name] as ((...values: unknown[]) => void) | undefined\n if (!callback) return\n try {\n callback(...args)\n } catch {\n // Debug tooling must never change application behavior.\n }\n}\n","import { invokeDebug, hasDebugHooks } from './debug'\n\nexport interface Owner {\n readonly id: string\n readonly parent: Owner | null\n readonly children: readonly Owner[]\n readonly depth: number\n readonly disposed: boolean\n run<T>(fn: () => T): T\n addCleanup(cleanup: () => void): void\n onDispose(cleanup: () => void): void\n onError(handler: (error: unknown) => void): () => void\n handleError(error: unknown): boolean\n dispose(): void\n}\n\nlet currentOwner: Owner | null = null\nlet nextOwnerId = 1\nconst ownerNames = new WeakMap<Owner, string>()\n\nexport function createOwner(): Owner {\n const parent = currentOwner\n let disposed = parent?.disposed ?? false\n const children: Owner[] = []\n const cleanups: Array<() => void> = []\n const errorHandlers = new Set<(error: unknown) => void>()\n\n const owner: Owner = {\n id: `owner-${nextOwnerId++}`,\n parent,\n children,\n depth: (parent?.depth ?? -1) + 1,\n\n get disposed(): boolean {\n return disposed\n },\n\n run<T>(fn: () => T): T {\n if (disposed) throw new Error('Vobs: 已销毁的 Owner 不能继续运行')\n const previous = currentOwner\n currentOwner = owner\n try {\n return fn()\n } finally {\n currentOwner = previous\n }\n },\n\n addCleanup(cleanup: () => void): void {\n if (disposed) {\n cleanup()\n return\n }\n cleanups.push(cleanup)\n },\n\n onDispose(cleanup: () => void): void {\n owner.addCleanup(cleanup)\n },\n\n onError(handler: (error: unknown) => void): () => void {\n errorHandlers.add(handler)\n const remove = () => errorHandlers.delete(handler)\n owner.addCleanup(remove)\n return remove\n },\n\n handleError(error: unknown): boolean {\n for (const handler of [...errorHandlers].reverse()) {\n try {\n handler(error)\n return true\n } catch (handlerError) {\n return parent?.handleError(handlerError) ?? false\n }\n }\n return parent?.handleError(error) ?? false\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n for (const child of [...children]) child.dispose()\n children.length = 0\n\n let firstError: unknown\n for (let index = cleanups.length - 1; index >= 0; index--) {\n try {\n cleanups[index]()\n } catch (error) {\n firstError ??= error\n }\n }\n cleanups.length = 0\n\n if (parent) {\n const index = parent.children.indexOf(owner)\n if (index >= 0) (parent.children as Owner[]).splice(index, 1)\n }\n if (hasDebugHooks()) invokeDebug('ownerDisposed', owner)\n if (firstError) throw firstError\n }\n }\n\n if (parent && !parent.disposed) (parent.children as Owner[]).push(owner)\n if (hasDebugHooks()) invokeDebug('ownerCreated', owner)\n return owner\n}\n\nexport function setOwnerDebugName(owner: Owner, name: string): void {\n ownerNames.set(owner, name)\n if (hasDebugHooks()) invokeDebug('ownerNamed', owner, name)\n}\n\nexport function getOwnerDebugName(owner: Owner): string | undefined {\n return ownerNames.get(owner)\n}\n\nexport function getCurrentOwner(): Owner | null {\n return currentOwner\n}\n\n/** Re-enter an Owner for an explicitly captured asynchronous continuation. */\nexport function runWithOwner<T>(owner: Owner, fn: () => T): T {\n return owner.run(fn)\n}\n\nexport function onDispose(cleanup: () => void): void {\n const owner = getCurrentOwner()\n if (!owner) throw new Error('Vobs: onDispose 必须在 Owner 作用域内调用')\n owner.onDispose(cleanup)\n}\n","import { getCurrentOwner } from './owner'\nimport { invokeDebug, hasDebugHooks, setSignalDebugName } from './debug'\n\nexport interface Dependency {\n unsubscribe(subscriber: Subscriber): void\n}\n\nexport interface Subscriber {\n readonly dependencies: Set<Dependency>\n readonly disposed: boolean\n notify(): void\n}\n\n/** 只读信号:派生值(memo)与只读上下文的最小契约,只能订阅与读取。 */\nexport interface ReadableSignal<T> extends Dependency {\n readonly value: T\n dispose(): void\n}\n\n/** 可写信号:state() 的返回类型。`set` 与 `.value =` 赋值语义完全一致。 */\nexport interface Signal<T> extends ReadableSignal<T> {\n value: T\n set(next: T): void\n}\n\nlet currentSubscriber: Subscriber | null = null\n\nexport function getCurrentSubscriber(): Subscriber | null {\n return currentSubscriber\n}\n\nexport function setCurrentSubscriber(subscriber: Subscriber | null): void {\n currentSubscriber = subscriber\n}\n\nexport function untrack<T>(fn: () => T): T {\n const previous = currentSubscriber\n currentSubscriber = null\n try {\n return fn()\n } finally {\n currentSubscriber = previous\n }\n}\n\nexport function trackDependency(dependency: Dependency): void {\n if (!currentSubscriber || currentSubscriber.disposed) return\n const added = !currentSubscriber.dependencies.has(dependency)\n currentSubscriber.dependencies.add(dependency)\n if (added && hasDebugHooks()) invokeDebug('dependencyTracked', dependency, currentSubscriber)\n}\n\n/**\n * Create a reactive state signal.\n *\n * State uses identity (`Object.is`) change detection. Objects and arrays are\n * intentionally shallow: mutating a nested property in place does not notify\n * subscribers; assign a new object/array to `value` to publish the change.\n *\n * The optional debug name is metadata for inspection tools only. It does not\n * affect subscriptions, scheduling, serialization, or the signal contract.\n */\nexport function state<T>(initialValue: T, debugName?: string): Signal<T> {\n let value = initialValue\n let disposed = false\n const subscribers = new Set<Subscriber>()\n\n const signalInstance: Signal<T> = {\n get value(): T {\n const subscriber = getCurrentSubscriber()\n if (subscriber && !subscriber.disposed) {\n subscribers.add(subscriber)\n if (hasDebugHooks()) invokeDebug('signalRead', signalInstance as Signal<unknown>, subscriber)\n trackDependency(signalInstance)\n }\n return value\n },\n\n set value(nextValue: T) {\n if (disposed || Object.is(value, nextValue)) return\n const previousValue = value\n value = nextValue\n if (hasDebugHooks()) invokeDebug('signalChanged', signalInstance as Signal<unknown>, previousValue, nextValue)\n for (const subscriber of [...subscribers]) subscriber.notify()\n },\n\n unsubscribe(subscriber: Subscriber): void {\n subscribers.delete(subscriber)\n },\n\n // 与 `.value =` 赋值同一条路径:判等短路、debug hook、notify 全部一致。\n // 以闭包实现,可安全地作为回调直接传递(无 this 绑定问题)。\n set(next: T): void {\n signalInstance.value = next\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n subscribers.clear()\n if (hasDebugHooks()) invokeDebug('signalDisposed', signalInstance as Signal<unknown>)\n }\n }\n\n const owner = getCurrentOwner()\n owner?.addCleanup(signalInstance.dispose)\n if (hasDebugHooks()) invokeDebug('signalCreated', signalInstance as Signal<unknown>, owner)\n if (debugName?.trim()) setSignalDebugName(signalInstance as Signal<unknown>, debugName.trim())\n return signalInstance\n}\n","import type { Effect } from './effect'\nimport { hasDebugHooks, invokeDebug } from './debug'\n\nexport class Scheduler {\n private readonly dirtyEffects = new Set<Effect>()\n private readonly lowPriorityEffects = new Set<Effect>()\n // flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。\n private readonly normalBuffer: Effect[] = []\n private readonly lowBuffer: Effect[] = []\n private flushing = false\n private scheduled = false\n private batchDepth = 0\n\n schedule(effect: Effect): void {\n if (effect.disposed) return\n this.dirtyEffects.add(effect)\n this.lowPriorityEffects.delete(effect)\n this.ensureScheduled()\n }\n\n /** Queue an effect behind normal updates while preserving deterministic order. */\n scheduleLow(effect: Effect): void {\n if (effect.disposed) return\n if (!this.dirtyEffects.has(effect)) this.lowPriorityEffects.add(effect)\n this.ensureScheduled()\n }\n\n private ensureScheduled(): void {\n if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {\n this.scheduled = true\n queueMicrotask(() => {\n this.scheduled = false\n this.flush()\n })\n }\n }\n\n remove(effect: Effect): void {\n this.dirtyEffects.delete(effect)\n this.lowPriorityEffects.delete(effect)\n }\n\n batch<T>(fn: () => T): T {\n this.batchDepth++\n try {\n return fn()\n } finally {\n this.batchDepth--\n if (this.batchDepth === 0) this.flush()\n }\n }\n\n flush(): void {\n if (this.flushing || this.batchDepth > 0) return\n this.flushing = true\n const debugEnabled = hasDebugHooks()\n if (debugEnabled) invokeDebug('flushStart')\n let rounds = 0\n let firstError: unknown\n let hasError = false\n try {\n while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {\n if (++rounds > 100) {\n this.dirtyEffects.clear()\n this.lowPriorityEffects.clear()\n throw new Error('Vobs: 响应式更新超过 100 轮,可能存在循环依赖')\n }\n\n // normal 先、low 后,两组分别排序:与旧的合并排序语义一致\n // (旧比较器里 low 优先级本就高于 depth),但消除了比较器内的 Set 查找。\n this.collectRunnable(this.dirtyEffects, this.normalBuffer)\n this.collectRunnable(this.lowPriorityEffects, this.lowBuffer)\n sortEffects(this.normalBuffer)\n sortEffects(this.lowBuffer)\n for (const effect of this.normalBuffer) {\n try {\n effect.run()\n } catch (error) {\n // Isolate one failed effect from the rest of the flush. Re-throw\n // the first error after all runnable effects have had a chance.\n if (!hasError) {\n firstError = error\n hasError = true\n }\n }\n }\n for (const effect of this.lowBuffer) {\n try {\n effect.run()\n } catch (error) {\n if (!hasError) {\n firstError = error\n hasError = true\n }\n }\n }\n this.normalBuffer.length = 0\n this.lowBuffer.length = 0\n }\n } finally {\n this.normalBuffer.length = 0\n this.lowBuffer.length = 0\n this.flushing = false\n if (debugEnabled) invokeDebug('flushEnd')\n }\n if (hasError) throw firstError\n }\n\n /** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */\n private collectRunnable(source: Set<Effect>, target: Effect[]): void {\n for (const effect of source) {\n if (!effect.disposed) target.push(effect)\n }\n source.clear()\n }\n}\n\n/** depth 深的先跑(子 effect 先于父),同深度按创建顺序。 */\nfunction sortEffects(effects: Effect[]): void {\n if (effects.length > 1) {\n effects.sort((a, b) => b.depth - a.depth || a.order - b.order)\n }\n}\n\nexport const scheduler = new Scheduler()\n\nexport function batch<T>(fn: () => T): T {\n return scheduler.batch(fn)\n}\n\n/** Schedule a low-priority effect explicitly. */\nexport function scheduleLow(effect: Effect): void {\n effect.scheduleLow()\n}\n","import type { VobsNode } from './fragment'\n\nexport type HmrComponent<Props extends object = Record<string, unknown>> =\n (props: Props) => VobsNode\n\nexport interface HmrStateStore {\n get<T>(key: string, initial: T | (() => T)): T\n set<T>(key: string, value: T): void\n has(key: string): boolean\n delete(key: string): void\n clear(): void\n}\n\nexport interface HmrInstance {\n node: VobsNode\n parent: Node | null\n refresh(): void\n}\n\ninterface HmrModuleState {\n readonly components: Map<string, HmrComponent>\n readonly state: Map<string, unknown>\n readonly instances: Set<HmrInstance>\n}\n\ninterface HmrGlobal {\n modules: Map<string, HmrModuleState>\n}\n\nconst globalTarget = globalThis as typeof globalThis & { __VOBS_HMR__?: HmrGlobal }\nconst hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: new Map<string, HmrModuleState>() }\nglobalTarget.__VOBS_HMR__ = hmrGlobal\n\nexport function resolveComponent<Props extends object>(\n component: HmrComponent<Props>,\n moduleId: string,\n exportName: string\n): HmrComponent<Props> {\n const module = getModule(moduleId)\n const existing = module.components.get(exportName)\n if (existing) return existing as HmrComponent<Props>\n\n const proxy = ((props: Props) => {\n const current = (proxy as HmrComponent<Props> & { current: HmrComponent<Props> }).current\n return current(props)\n }) as HmrComponent<Props> & { current: HmrComponent<Props> }\n proxy.current = component\n Object.defineProperties(proxy, {\n displayName: { configurable: true, value: component.name || exportName },\n hmrKey: { configurable: false, value: `${moduleId}:${exportName}` }\n })\n module.components.set(exportName, proxy as HmrComponent)\n return proxy\n}\n\nexport function updateHmrModule(_moduleId: string, nextModule: Record<string, unknown>): void {\n const modules = [...hmrGlobal.modules.values()]\n for (const module of modules) {\n let changed = false\n for (const [name, proxy] of module.components) {\n const next = nextModule[name]\n if (typeof next !== 'function') continue\n const hmrProxy = proxy as HmrComponent & { current: HmrComponent; displayName?: string }\n hmrProxy.current = next as HmrComponent\n Object.defineProperty(hmrProxy, 'displayName', { configurable: true, value: next.name || name })\n changed = true\n }\n if (!changed) continue\n for (const instance of module.instances) {\n try {\n instance.refresh()\n } catch {\n // HMR failures remain application errors on the next normal render.\n }\n }\n }\n}\n\nexport function disposeHmrModule(_moduleId: string): void {\n // State and component proxies intentionally survive module disposal.\n}\n\nexport function createHmrStateStore(moduleId: string): HmrStateStore {\n const state = getModule(moduleId).state\n return {\n get<T>(key: string, initial: T | (() => T)): T {\n if (!state.has(key)) state.set(key, typeof initial === 'function' ? (initial as () => T)() : initial)\n return state.get(key) as T\n },\n set<T>(key: string, value: T): void {\n state.set(key, value)\n },\n has: key => state.has(key),\n delete: key => { state.delete(key) },\n clear: () => { state.clear() }\n }\n}\n\nexport function registerHmrInstance(moduleId: string, instance: HmrInstance): () => void {\n const instances = getModule(moduleId).instances\n instances.add(instance)\n return () => instances.delete(instance)\n}\n\nexport function markHmrInstanceMounted(node: VobsNode, parent: Node): void {\n const instance = hmrInstances.get(node as object)\n if (instance) instance.parent = parent\n}\n\nfunction getModule(moduleId: string): HmrModuleState {\n let module = hmrGlobal.modules.get(moduleId)\n if (!module) {\n module = { components: new Map(), state: new Map(), instances: new Set() }\n hmrGlobal.modules.set(moduleId, module)\n }\n return module\n}\n\nconst hmrInstances = new WeakMap<object, HmrInstance>()\n\nexport function associateHmrInstance(node: VobsNode, instance: HmrInstance): void {\n hmrInstances.set(node as object, instance)\n}\n","import { getCurrentOwner, type Owner } from '@vobs/reactivity'\nimport type { InjectionKey, ProvideOptions } from './app'\n\nconst ownerProviders = new WeakMap<Owner, Map<InjectionKey<unknown>, unknown>>()\n\nexport function provide<T>(key: InjectionKey<T>, value: T, options: ProvideOptions = {}): void {\n const owner = getCurrentOwner()\n if (!owner) throw new Error('Vobs: provide 必须在组件或 Owner 作用域内调用')\n provideToOwner(owner, key, value, options)\n}\n\nexport function inject<T>(key: InjectionKey<T>): T | undefined\nexport function inject<T>(key: InjectionKey<T>, fallback: T): T\nexport function inject<T>(key: InjectionKey<T>, fallback?: T): T | undefined {\n const owner = getCurrentOwner()\n const value = owner ? injectFromOwner(owner, key) : undefined\n return value === undefined ? fallback : value\n}\n\nexport function injectRequired<T>(key: InjectionKey<T>, description?: string): T {\n const value = inject(key)\n if (value === undefined) {\n throw new Error(`Vobs: 找不到必需注入项${description ? ` ${description}` : ''}`)\n }\n return value\n}\n\nexport function provideToOwner<T>(\n owner: Owner,\n key: InjectionKey<T>,\n value: T,\n options: ProvideOptions = {}\n): void {\n let providers = ownerProviders.get(owner)\n if (!providers) {\n providers = new Map<InjectionKey<unknown>, unknown>()\n ownerProviders.set(owner, providers)\n owner.onDispose(() => ownerProviders.delete(owner))\n }\n if (providers.has(key) && !options.override) {\n throw new Error(`Vobs: 注入项 ${String(key)} 已存在;如需覆盖请传入 override: true`)\n }\n providers.set(key, value)\n}\n\nexport function injectFromOwner<T>(owner: Owner, key: InjectionKey<T>): T | undefined {\n let current: Owner | null = owner\n while (current) {\n const providers = ownerProviders.get(current)\n if (providers?.has(key)) return providers.get(key) as T\n current = current.parent\n }\n return undefined\n}\n","import { createOwner, scheduler, setOwnerDebugName, type Owner } from '@vobs/reactivity'\nimport { createDOMRenderer } from '@vobs/dom'\nimport { insertBefore as insertRuntimeNode, setRenderer, type VobsFragment, type VobsRenderer } from '@vobs/runtime'\nimport { injectFromOwner, provideToOwner } from './context'\n\nexport type InjectionKey<T> = symbol & {\n readonly __vobsType?: T\n}\n\nexport interface ProvideOptions {\n override?: boolean\n}\n\nexport interface VobsPlugin {\n name: string\n version?: string\n requires?: readonly VobsPlugin[]\n optional?: readonly VobsPlugin[]\n install?: (ctx: VobsContext) => void | (() => void)\n}\n\nexport interface VobsContext {\n readonly app: VobsApp\n provide<T>(key: InjectionKey<T>, value: T, options?: ProvideOptions): void\n inject<T>(key: InjectionKey<T>): T | undefined\n injectRequired<T>(key: InjectionKey<T>, description?: string): T\n onDestroy(cleanup: () => void): void\n onError(handler: (error: unknown) => void): () => void\n}\n\nexport interface VobsConfig<\n NodeType = Node,\n TextNode extends NodeType = NodeType,\n ElementNode extends NodeType = NodeType,\n CommentNode extends NodeType = NodeType\n> {\n render: () => NodeType | VobsFragment | Node | null | undefined\n renderer?: VobsRenderer<NodeType, TextNode, ElementNode, CommentNode>\n plugins?: VobsPlugin[]\n /** Optional application-level error observer. Observers are isolated from the app. */\n onError?: (error: unknown) => void\n}\n\nexport interface VobsApp<NodeType = Node> {\n readonly mounted: boolean\n readonly destroyed: boolean\n use(plugin: VobsPlugin): VobsApp<NodeType>\n mount(target: string | NodeType): void\n hydrate(target: string | NodeType): void\n update(): void\n destroy(): void\n}\n\nexport function createInjectionKey<T>(description: string): InjectionKey<T> {\n return Symbol(description) as InjectionKey<T>\n}\n\nexport function createVobs(\n config: VobsConfig<Node, Text, Element, Comment>\n): VobsApp<Node>\nexport function createVobs<\n NodeType = Node,\n TextNode extends NodeType = NodeType,\n ElementNode extends NodeType = NodeType,\n CommentNode extends NodeType = NodeType\n>(\n config: VobsConfig<NodeType, TextNode, ElementNode, CommentNode> & {\n renderer: VobsRenderer<NodeType, TextNode, ElementNode, CommentNode>\n }\n): VobsApp<NodeType>\nexport function createVobs(\n config: VobsConfig<any, any, any, any>\n): VobsApp<any> {\n if (!config.render) throw new Error('createVobs: render 不能为空')\n\n const renderer = config.renderer ?? createDOMRenderer()\n const rootOwner: Owner = createOwner()\n setOwnerDebugName(rootOwner, 'App')\n const cleanups: Array<() => void> = []\n const errorHandlers = new Set<(error: unknown) => void>()\n const installed = new Set<string>()\n const installing = new Set<string>()\n let mounted = false\n let destroyed = false\n let container: any = null\n let app!: VobsApp<any>\n\n if (config.onError) {\n errorHandlers.add(config.onError)\n cleanups.push(() => errorHandlers.delete(config.onError!))\n }\n\n const context: VobsContext = {\n get app(): VobsApp<any> {\n return app\n },\n\n provide<T>(key: InjectionKey<T>, value: T, options: ProvideOptions = {}): void {\n provideToOwner(rootOwner, key, value, options)\n },\n\n inject<T>(key: InjectionKey<T>): T | undefined {\n return injectFromOwner(rootOwner, key)\n },\n\n injectRequired<T>(key: InjectionKey<T>, description?: string): T {\n const value = injectFromOwner(rootOwner, key)\n if (value === undefined) {\n throw new Error(`Vobs: 找不到必需注入项${description ? ` ${description}` : ''}`)\n }\n return value\n },\n\n onDestroy(cleanup: () => void): void {\n cleanups.push(cleanup)\n },\n\n onError(handler: (error: unknown) => void): () => void {\n errorHandlers.add(handler)\n const remove = () => errorHandlers.delete(handler)\n cleanups.push(remove)\n return remove\n }\n }\n\n function notifyError(error: unknown): void {\n for (const handler of [...errorHandlers]) {\n try {\n handler(error)\n } catch {\n // 错误处理器不能覆盖触发它的原始错误。\n }\n }\n }\n\n function installPlugin(plugin: VobsPlugin): void {\n if (installed.has(plugin.name)) return\n if (installing.has(plugin.name)) {\n throw new Error(`Vobs: 插件依赖存在循环:${plugin.name}`)\n }\n\n installing.add(plugin.name)\n try {\n for (const dependency of plugin.requires ?? []) installPlugin(dependency)\n const cleanup = plugin.install?.(context)\n if (cleanup) cleanups.push(cleanup)\n installed.add(plugin.name)\n } finally {\n installing.delete(plugin.name)\n }\n }\n\n function cleanup(clearContainer = true): unknown {\n let firstError: unknown\n for (let index = cleanups.length - 1; index >= 0; index--) {\n try {\n cleanups[index]()\n } catch (error) {\n firstError ??= error\n }\n }\n cleanups.length = 0\n\n try {\n rootOwner.dispose()\n } catch (error) {\n firstError ??= error\n }\n\n if (container && clearContainer) {\n try {\n renderer.clear(container)\n } catch (error) {\n firstError ??= error\n }\n }\n return firstError\n }\n\n function start(target: string | any, hydrating: boolean): void {\n if (destroyed) throw new Error('Vobs: 已销毁的应用不能挂载')\n if (mounted) return\n\n container = typeof target === 'string' ? document.querySelector(target) : target\n if (!container) throw new Error(`mount: 目标不存在: ${target}`)\n if (hydrating && !renderer.beginHydration) {\n throw new Error('Vobs: 当前渲染器不支持 Hydration')\n }\n\n setRenderer(renderer)\n try {\n if (hydrating) renderer.beginHydration?.()\n const rootNode = rootOwner.run(config.render)\n if (!hydrating) renderer.clear(container)\n if (rootNode) insertRuntimeNode(container, rootNode as any, null)\n if (hydrating) renderer.completeHydration?.()\n mounted = true\n } catch (error) {\n notifyError(error)\n const cleanupError = cleanup(!hydrating)\n destroyed = true\n throw cleanupError ?? error\n }\n }\n\n app = {\n get mounted(): boolean {\n return mounted\n },\n\n get destroyed(): boolean {\n return destroyed\n },\n\n use(plugin: VobsPlugin): VobsApp<any> {\n if (destroyed) throw new Error('Vobs: 已销毁的应用不能安装插件')\n installPlugin(plugin)\n return app\n },\n\n mount(target: string | any): void {\n start(target, false)\n },\n\n hydrate(target: string | any): void {\n start(target, true)\n },\n\n update(): void {\n if (destroyed) throw new Error('Vobs: 已销毁的应用不能更新')\n try {\n scheduler.flush()\n } catch (error) {\n notifyError(error)\n throw error\n }\n },\n\n destroy(): void {\n if (destroyed) return\n try {\n const cleanupError = cleanup()\n if (cleanupError) {\n notifyError(cleanupError)\n throw cleanupError\n }\n } finally {\n mounted = false\n destroyed = true\n }\n }\n }\n\n try {\n for (const plugin of config.plugins ?? []) app.use(plugin)\n } catch (error) {\n notifyError(error)\n cleanup()\n destroyed = true\n throw error\n }\n\n return app\n}\n","import { getCurrentOwner, onDispose, state, type Signal } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type DictName = string\nexport type DictValue = string | number\n\nexport interface DictItem {\n readonly value: DictValue\n readonly label: string\n readonly disabled?: boolean\n readonly [key: string]: unknown\n}\n\nexport type DictItems = readonly DictItem[]\nexport type DictData = Readonly<Record<DictName, DictItems>>\nexport type DictLoader = (name: DictName, signal: AbortSignal) => DictItems | PromiseLike<DictItems>\n\nexport interface DictQuery {\n readonly name: DictName\n readonly items: Signal<DictItems>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly updatedAt: Signal<number>\n load(options?: { readonly force?: boolean }): Promise<DictItems>\n invalidate(): void\n}\n\nexport interface DictDehydratedEntry {\n readonly name: DictName\n readonly items: DictItems\n readonly updatedAt: number\n}\n\nexport interface DictDehydratedState {\n readonly version: 1\n readonly entries: readonly DictDehydratedEntry[]\n}\n\nexport interface DictOptions {\n readonly data?: DictData\n readonly loader?: DictLoader\n readonly staleTime?: number\n readonly now?: () => number\n readonly onError?: (error: DictError, name: DictName) => void\n}\n\nexport interface DictPluginOptions extends DictOptions {\n readonly dict?: DictContext\n}\n\nexport interface DictContext {\n readonly data: Signal<DictData>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly staleTime: number\n get(name: DictName): DictItems\n find(name: DictName, value: DictValue): DictItem | undefined\n label(name: DictName, value: DictValue, fallback?: string): string\n query(name: DictName): DictQuery\n load(name: DictName, options?: { readonly force?: boolean }): Promise<DictItems>\n set(name: DictName, items: DictItems): void\n invalidate(name?: DictName): void\n dehydrate(): DictDehydratedState\n hydrate(snapshot: unknown): void\n dispose(): void\n}\n\nexport type DictErrorCode =\n | 'DICT_CONTEXT_MISSING'\n | 'DICT_CONTEXT_DISPOSED'\n | 'INVALID_DICT_NAME'\n | 'INVALID_DICT_ITEMS'\n | 'DICT_LOADER_MISSING'\n | 'DICT_LOAD_FAILED'\n | 'INVALID_DEHYDRATED_STATE'\n\nexport class DictError extends Error {\n readonly code: DictErrorCode\n readonly cause: unknown\n\n constructor(code: DictErrorCode, message: string, cause?: unknown) {\n super(message)\n this.name = 'DictError'\n this.code = code\n this.cause = cause\n }\n}\n\nexport const DICT_KEY: InjectionKey<DictContext> = createInjectionKey<DictContext>('vobs.dict')\n\nconst EMPTY_ITEMS: DictItems = Object.freeze([])\n\ninterface DictEntry extends DictQuery {\n controller: AbortController | null\n inFlight: Promise<DictItems> | null\n revision: number\n}\n\nexport function createDict(options: DictOptions = {}): DictContext {\n const staleTime = validateStaleTime(options.staleTime ?? 5 * 60 * 1000)\n const now = options.now ?? Date.now\n const initial = normalizeData(options.data ?? {})\n const data = state<DictData>(initial)\n const loading = state(false)\n const error = state<Error | null>(null)\n const entries = new Map<DictName, DictEntry>()\n let disposed = false\n\n for (const [name, items] of Object.entries(initial)) {\n const entry = createEntry(name, items, now())\n entries.set(name, entry)\n }\n\n const context: DictContext = {\n data,\n loading,\n error,\n staleTime,\n\n get(name): DictItems {\n ensureActive()\n return data.value[validateName(name)] ?? EMPTY_ITEMS\n },\n\n find(name, value): DictItem | undefined {\n ensureActive()\n return context.get(name).find(item => item.value === value)\n },\n\n label(name, value, fallback): string {\n ensureActive()\n return context.find(name, value)?.label ?? fallback ?? String(value)\n },\n\n query(name): DictQuery {\n ensureActive()\n return getEntry(validateName(name))\n },\n\n load(name, loadOptions = {}): Promise<DictItems> {\n ensureActive()\n const entry = getEntry(validateName(name))\n if (!loadOptions.force && isFresh(entry)) return Promise.resolve(entry.items.value)\n if (entry.inFlight) return entry.inFlight\n if (!options.loader) {\n const loadError = new DictError('DICT_LOADER_MISSING', `Vobs Dict: ${entry.name} 未配置 loader`)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n return Promise.reject(loadError)\n }\n\n const revision = ++entry.revision\n const controller = new AbortController()\n entry.controller = controller\n entry.loading.value = true\n refreshLoading()\n const request = Promise.resolve()\n .then(() => options.loader!(entry.name, controller.signal))\n .then(items => {\n if (disposed || revision !== entry.revision) return entry.items.value\n const normalized = normalizeItems(items)\n commit(entry, normalized, now(), false)\n return normalized\n })\n .catch(reason => {\n if (disposed || revision !== entry.revision || isAbortError(reason)) return entry.items.value\n const loadError = reason instanceof DictError\n ? reason\n : new DictError('DICT_LOAD_FAILED', `Vobs Dict: ${entry.name} 加载失败`, reason)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n throw loadError\n })\n .finally(() => {\n if (revision !== entry.revision) return\n entry.inFlight = null\n entry.controller = null\n entry.loading.value = false\n refreshLoading()\n })\n entry.inFlight = request\n return request\n },\n\n set(name, items): void {\n ensureActive()\n commit(getEntry(validateName(name)), normalizeItems(items), now())\n },\n\n invalidate(name): void {\n ensureActive()\n if (name === undefined) {\n for (const entry of entries.values()) invalidateEntry(entry)\n return\n }\n invalidateEntry(getEntry(validateName(name)))\n },\n\n dehydrate(): DictDehydratedState {\n ensureActive()\n return {\n version: 1,\n entries: Object.freeze([...entries.values()]\n .filter(entry => entry.updatedAt.value > 0)\n .map(entry => Object.freeze({\n name: entry.name,\n items: entry.items.value,\n updatedAt: entry.updatedAt.value\n })))\n }\n },\n\n hydrate(snapshot): void {\n ensureActive()\n const restored = parseDehydratedState(snapshot)\n const nextData: Record<DictName, DictItems> = {}\n const restoredNames = new Set<DictName>()\n for (const item of restored.entries) {\n const entry = getEntry(item.name)\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = item.items\n entry.error.value = null\n entry.updatedAt.value = item.updatedAt\n nextData[item.name] = item.items\n restoredNames.add(item.name)\n }\n for (const [name, entry] of entries) {\n if (restoredNames.has(name)) continue\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = EMPTY_ITEMS\n entry.error.value = null\n entry.updatedAt.value = 0\n }\n data.value = Object.freeze(nextData)\n error.value = null\n refreshLoading()\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n for (const entry of entries.values()) {\n entry.controller?.abort()\n entry.items.dispose()\n entry.loading.dispose()\n entry.error.dispose()\n entry.updatedAt.dispose()\n }\n entries.clear()\n data.dispose()\n loading.dispose()\n error.dispose()\n }\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function getEntry(name: DictName): DictEntry {\n const existing = entries.get(name)\n if (existing) return existing\n const entry = createEntry(name, data.value[name] ?? EMPTY_ITEMS, 0)\n entries.set(name, entry)\n return entry\n }\n\n function createEntry(name: DictName, items: DictItems, updatedAt: number): DictEntry {\n const entry = {\n name,\n items: state(items),\n loading: state(false),\n error: state<Error | null>(null),\n updatedAt: state(updatedAt),\n controller: null,\n inFlight: null,\n revision: 0,\n load: (loadOptions?: { readonly force?: boolean }) => context.load(name, loadOptions),\n invalidate: () => context.invalidate(name)\n } as DictEntry\n return entry\n }\n\n function commit(entry: DictEntry, items: DictItems, updatedAt: number, replaceRequest = true): void {\n if (replaceRequest) {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n }\n entry.items.value = items\n entry.error.value = null\n entry.updatedAt.value = updatedAt\n data.value = Object.freeze({ ...data.value, [entry.name]: items })\n error.value = null\n refreshLoading()\n }\n\n function invalidateEntry(entry: DictEntry): void {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.updatedAt.value = 0\n refreshLoading()\n }\n\n function isFresh(entry: DictEntry): boolean {\n return entry.updatedAt.value > 0 && now() - entry.updatedAt.value < staleTime\n }\n\n function refreshLoading(): void {\n loading.value = [...entries.values()].some(entry => entry.loading.value)\n }\n\n function report(dictError: DictError, name: DictName): void {\n try { options.onError?.(dictError, name) } catch { /* observers cannot break dictionary state */ }\n }\n\n function ensureActive(): void {\n if (disposed) throw new DictError('DICT_CONTEXT_DISPOSED', 'Vobs Dict: 上下文已销毁')\n }\n}\n\nexport function dictPlugin(options: DictPluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/dict',\n version: '0.1.0',\n install(context) {\n const ownedDict = options.dict ? undefined : createDict(options)\n context.provide(DICT_KEY, options.dict ?? ownedDict!)\n return () => ownedDict?.dispose()\n }\n }\n}\n\nexport function useDict(): DictContext {\n const dict = inject(DICT_KEY)\n if (!dict) throw new DictError('DICT_CONTEXT_MISSING', 'Vobs Dict: 找不到上下文,请安装 dictPlugin')\n return dict\n}\n\nfunction validateName(name: string): DictName {\n if (typeof name !== 'string' || name.trim() === '') {\n throw new DictError('INVALID_DICT_NAME', 'Vobs Dict: 字典名必须是非空字符串')\n }\n return name\n}\n\nfunction validateStaleTime(value: number): number {\n if (!Number.isFinite(value) || value < 0) {\n throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: staleTime 必须是大于等于 0 的有限数字')\n }\n return value\n}\n\nfunction normalizeData(data: DictData): DictData {\n const normalized: Record<DictName, DictItems> = {}\n for (const [name, items] of Object.entries(data)) normalized[validateName(name)] = normalizeItems(items)\n return Object.freeze(normalized)\n}\n\nfunction normalizeItems(items: unknown): DictItems {\n if (!Array.isArray(items)) throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: 字典项必须是数组')\n return Object.freeze(items.map((item, index) => {\n if (!item || typeof item !== 'object'\n || (typeof (item as DictItem).value !== 'string' && typeof (item as DictItem).value !== 'number')\n || typeof (item as DictItem).label !== 'string') {\n throw new DictError('INVALID_DICT_ITEMS', `Vobs Dict: 第 ${index + 1} 个字典项必须包含 value 和 label`)\n }\n return Object.freeze({ ...item }) as DictItem\n }))\n}\n\nfunction parseDehydratedState(snapshot: unknown): DictDehydratedState {\n let value: unknown = snapshot\n if (typeof snapshot === 'string') {\n try { value = JSON.parse(snapshot) } catch {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态不是有效 JSON')\n }\n }\n if (!value || typeof value !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态格式无效')\n }\n const candidate = value as Partial<DictDehydratedState>\n if (candidate.version !== 1 || !Array.isArray(candidate.entries)) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态版本或 entries 无效')\n }\n const seen = new Set<string>()\n const entries = candidate.entries.map(entry => {\n if (!entry || typeof entry !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目无效')\n }\n const name = validateName((entry as Partial<DictDehydratedEntry>).name as string)\n const updatedAt = (entry as Partial<DictDehydratedEntry>).updatedAt\n if (seen.has(name) || typeof updatedAt !== 'number' || !Number.isFinite(updatedAt) || updatedAt < 0) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目字段无效')\n }\n seen.add(name)\n return Object.freeze({\n name,\n items: normalizeItems((entry as Partial<DictDehydratedEntry>).items),\n updatedAt\n })\n })\n return { version: 1, entries: Object.freeze(entries) }\n}\n\nfunction isAbortError(value: unknown): boolean {\n return Boolean(value) && typeof value === 'object' && (value as { name?: unknown }).name === 'AbortError'\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getCurrentOwner, onDispose, state, type Signal } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type DictName = string\nexport type DictValue = string | number\n\nexport interface DictItem {\n readonly value: DictValue\n readonly label: string\n readonly disabled?: boolean\n readonly [key: string]: unknown\n}\n\nexport type DictItems = readonly DictItem[]\nexport type DictData = Readonly<Record<DictName, DictItems>>\nexport type DictLoader = (name: DictName, signal: AbortSignal) => DictItems | PromiseLike<DictItems>\n\nexport interface DictQuery {\n readonly name: DictName\n readonly items: Signal<DictItems>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly updatedAt: Signal<number>\n load(options?: { readonly force?: boolean }): Promise<DictItems>\n invalidate(): void\n}\n\nexport interface DictDehydratedEntry {\n readonly name: DictName\n readonly items: DictItems\n readonly updatedAt: number\n}\n\nexport interface DictDehydratedState {\n readonly version: 1\n readonly entries: readonly DictDehydratedEntry[]\n}\n\nexport interface DictOptions {\n readonly data?: DictData\n readonly loader?: DictLoader\n readonly staleTime?: number\n readonly now?: () => number\n readonly onError?: (error: DictError, name: DictName) => void\n}\n\nexport interface DictPluginOptions extends DictOptions {\n readonly dict?: DictContext\n}\n\nexport interface DictContext {\n readonly data: Signal<DictData>\n readonly loading: Signal<boolean>\n readonly error: Signal<Error | null>\n readonly staleTime: number\n get(name: DictName): DictItems\n find(name: DictName, value: DictValue): DictItem | undefined\n label(name: DictName, value: DictValue, fallback?: string): string\n query(name: DictName): DictQuery\n load(name: DictName, options?: { readonly force?: boolean }): Promise<DictItems>\n set(name: DictName, items: DictItems): void\n invalidate(name?: DictName): void\n dehydrate(): DictDehydratedState\n hydrate(snapshot: unknown): void\n dispose(): void\n}\n\nexport type DictErrorCode =\n | 'DICT_CONTEXT_MISSING'\n | 'DICT_CONTEXT_DISPOSED'\n | 'INVALID_DICT_NAME'\n | 'INVALID_DICT_ITEMS'\n | 'DICT_LOADER_MISSING'\n | 'DICT_LOAD_FAILED'\n | 'INVALID_DEHYDRATED_STATE'\n\nexport class DictError extends Error {\n readonly code: DictErrorCode\n readonly cause: unknown\n\n constructor(code: DictErrorCode, message: string, cause?: unknown) {\n super(message)\n this.name = 'DictError'\n this.code = code\n this.cause = cause\n }\n}\n\nexport const DICT_KEY: InjectionKey<DictContext> = createInjectionKey<DictContext>('vobs.dict')\n\nconst EMPTY_ITEMS: DictItems = Object.freeze([])\n\ninterface DictEntry extends DictQuery {\n controller: AbortController | null\n inFlight: Promise<DictItems> | null\n revision: number\n}\n\nexport function createDict(options: DictOptions = {}): DictContext {\n const staleTime = validateStaleTime(options.staleTime ?? 5 * 60 * 1000)\n const now = options.now ?? Date.now\n const initial = normalizeData(options.data ?? {})\n const data = state<DictData>(initial)\n const loading = state(false)\n const error = state<Error | null>(null)\n const entries = new Map<DictName, DictEntry>()\n let disposed = false\n\n for (const [name, items] of Object.entries(initial)) {\n const entry = createEntry(name, items, now())\n entries.set(name, entry)\n }\n\n const context: DictContext = {\n data,\n loading,\n error,\n staleTime,\n\n get(name): DictItems {\n ensureActive()\n return data.value[validateName(name)] ?? EMPTY_ITEMS\n },\n\n find(name, value): DictItem | undefined {\n ensureActive()\n return context.get(name).find(item => item.value === value)\n },\n\n label(name, value, fallback): string {\n ensureActive()\n return context.find(name, value)?.label ?? fallback ?? String(value)\n },\n\n query(name): DictQuery {\n ensureActive()\n return getEntry(validateName(name))\n },\n\n load(name, loadOptions = {}): Promise<DictItems> {\n ensureActive()\n const entry = getEntry(validateName(name))\n if (!loadOptions.force && isFresh(entry)) return Promise.resolve(entry.items.value)\n if (entry.inFlight) return entry.inFlight\n if (!options.loader) {\n const loadError = new DictError('DICT_LOADER_MISSING', `Vobs Dict: ${entry.name} 未配置 loader`)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n return Promise.reject(loadError)\n }\n\n const revision = ++entry.revision\n const controller = new AbortController()\n entry.controller = controller\n entry.loading.value = true\n refreshLoading()\n const request = Promise.resolve()\n .then(() => options.loader!(entry.name, controller.signal))\n .then(items => {\n if (disposed || revision !== entry.revision) return entry.items.value\n const normalized = normalizeItems(items)\n commit(entry, normalized, now(), false)\n return normalized\n })\n .catch(reason => {\n if (disposed || revision !== entry.revision || isAbortError(reason)) return entry.items.value\n const loadError = reason instanceof DictError\n ? reason\n : new DictError('DICT_LOAD_FAILED', `Vobs Dict: ${entry.name} 加载失败`, reason)\n entry.error.value = loadError\n error.value = loadError\n report(loadError, entry.name)\n throw loadError\n })\n .finally(() => {\n if (revision !== entry.revision) return\n entry.inFlight = null\n entry.controller = null\n entry.loading.value = false\n refreshLoading()\n })\n entry.inFlight = request\n return request\n },\n\n set(name, items): void {\n ensureActive()\n commit(getEntry(validateName(name)), normalizeItems(items), now())\n },\n\n invalidate(name): void {\n ensureActive()\n if (name === undefined) {\n for (const entry of entries.values()) invalidateEntry(entry)\n return\n }\n invalidateEntry(getEntry(validateName(name)))\n },\n\n dehydrate(): DictDehydratedState {\n ensureActive()\n return {\n version: 1,\n entries: Object.freeze([...entries.values()]\n .filter(entry => entry.updatedAt.value > 0)\n .map(entry => Object.freeze({\n name: entry.name,\n items: entry.items.value,\n updatedAt: entry.updatedAt.value\n })))\n }\n },\n\n hydrate(snapshot): void {\n ensureActive()\n const restored = parseDehydratedState(snapshot)\n const nextData: Record<DictName, DictItems> = {}\n const restoredNames = new Set<DictName>()\n for (const item of restored.entries) {\n const entry = getEntry(item.name)\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = item.items\n entry.error.value = null\n entry.updatedAt.value = item.updatedAt\n nextData[item.name] = item.items\n restoredNames.add(item.name)\n }\n for (const [name, entry] of entries) {\n if (restoredNames.has(name)) continue\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.items.value = EMPTY_ITEMS\n entry.error.value = null\n entry.updatedAt.value = 0\n }\n data.value = Object.freeze(nextData)\n error.value = null\n refreshLoading()\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n for (const entry of entries.values()) {\n entry.controller?.abort()\n entry.items.dispose()\n entry.loading.dispose()\n entry.error.dispose()\n entry.updatedAt.dispose()\n }\n entries.clear()\n data.dispose()\n loading.dispose()\n error.dispose()\n }\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function getEntry(name: DictName): DictEntry {\n const existing = entries.get(name)\n if (existing) return existing\n const entry = createEntry(name, data.value[name] ?? EMPTY_ITEMS, 0)\n entries.set(name, entry)\n return entry\n }\n\n function createEntry(name: DictName, items: DictItems, updatedAt: number): DictEntry {\n const entry = {\n name,\n items: state(items),\n loading: state(false),\n error: state<Error | null>(null),\n updatedAt: state(updatedAt),\n controller: null,\n inFlight: null,\n revision: 0,\n load: (loadOptions?: { readonly force?: boolean }) => context.load(name, loadOptions),\n invalidate: () => context.invalidate(name)\n } as DictEntry\n return entry\n }\n\n function commit(entry: DictEntry, items: DictItems, updatedAt: number, replaceRequest = true): void {\n if (replaceRequest) {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n }\n entry.items.value = items\n entry.error.value = null\n entry.updatedAt.value = updatedAt\n data.value = Object.freeze({ ...data.value, [entry.name]: items })\n error.value = null\n refreshLoading()\n }\n\n function invalidateEntry(entry: DictEntry): void {\n entry.revision++\n entry.controller?.abort()\n entry.controller = null\n entry.inFlight = null\n entry.loading.value = false\n entry.updatedAt.value = 0\n refreshLoading()\n }\n\n function isFresh(entry: DictEntry): boolean {\n return entry.updatedAt.value > 0 && now() - entry.updatedAt.value < staleTime\n }\n\n function refreshLoading(): void {\n loading.value = [...entries.values()].some(entry => entry.loading.value)\n }\n\n function report(dictError: DictError, name: DictName): void {\n try { options.onError?.(dictError, name) } catch { /* observers cannot break dictionary state */ }\n }\n\n function ensureActive(): void {\n if (disposed) throw new DictError('DICT_CONTEXT_DISPOSED', 'Vobs Dict: 上下文已销毁')\n }\n}\n\nexport function dictPlugin(options: DictPluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/dict',\n version: '0.1.0',\n install(context) {\n const ownedDict = options.dict ? undefined : createDict(options)\n context.provide(DICT_KEY, options.dict ?? ownedDict!)\n return () => ownedDict?.dispose()\n }\n }\n}\n\nexport function useDict(): DictContext {\n const dict = inject(DICT_KEY)\n if (!dict) throw new DictError('DICT_CONTEXT_MISSING', 'Vobs Dict: 找不到上下文,请安装 dictPlugin')\n return dict\n}\n\nfunction validateName(name: string): DictName {\n if (typeof name !== 'string' || name.trim() === '') {\n throw new DictError('INVALID_DICT_NAME', 'Vobs Dict: 字典名必须是非空字符串')\n }\n return name\n}\n\nfunction validateStaleTime(value: number): number {\n if (!Number.isFinite(value) || value < 0) {\n throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: staleTime 必须是大于等于 0 的有限数字')\n }\n return value\n}\n\nfunction normalizeData(data: DictData): DictData {\n const normalized: Record<DictName, DictItems> = {}\n for (const [name, items] of Object.entries(data)) normalized[validateName(name)] = normalizeItems(items)\n return Object.freeze(normalized)\n}\n\nfunction normalizeItems(items: unknown): DictItems {\n if (!Array.isArray(items)) throw new DictError('INVALID_DICT_ITEMS', 'Vobs Dict: 字典项必须是数组')\n return Object.freeze(items.map((item, index) => {\n if (!item || typeof item !== 'object'\n || (typeof (item as DictItem).value !== 'string' && typeof (item as DictItem).value !== 'number')\n || typeof (item as DictItem).label !== 'string') {\n throw new DictError('INVALID_DICT_ITEMS', `Vobs Dict: 第 ${index + 1} 个字典项必须包含 value 和 label`)\n }\n return Object.freeze({ ...item }) as DictItem\n }))\n}\n\nfunction parseDehydratedState(snapshot: unknown): DictDehydratedState {\n let value: unknown = snapshot\n if (typeof snapshot === 'string') {\n try { value = JSON.parse(snapshot) } catch {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态不是有效 JSON')\n }\n }\n if (!value || typeof value !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态格式无效')\n }\n const candidate = value as Partial<DictDehydratedState>\n if (candidate.version !== 1 || !Array.isArray(candidate.entries)) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态版本或 entries 无效')\n }\n const seen = new Set<string>()\n const entries = candidate.entries.map(entry => {\n if (!entry || typeof entry !== 'object') {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目无效')\n }\n const name = validateName((entry as Partial<DictDehydratedEntry>).name as string)\n const updatedAt = (entry as Partial<DictDehydratedEntry>).updatedAt\n if (seen.has(name) || typeof updatedAt !== 'number' || !Number.isFinite(updatedAt) || updatedAt < 0) {\n throw new DictError('INVALID_DEHYDRATED_STATE', 'Vobs Dict: 初始状态条目字段无效')\n }\n seen.add(name)\n return Object.freeze({\n name,\n items: normalizeItems((entry as Partial<DictDehydratedEntry>).items),\n updatedAt\n })\n })\n return { version: 1, entries: Object.freeze(entries) }\n}\n\nfunction isAbortError(value: unknown): boolean {\n return Boolean(value) && typeof value === 'object' && (value as { name?: unknown }).name === 'AbortError'\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"type": "git",
|
|
12
12
|
"url": "git+https://github.com/vobsjs/vobs.git"
|
|
13
13
|
},
|
|
14
|
-
"version": "1.2.
|
|
14
|
+
"version": "1.2.2",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"./source/*": "./src/*"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@vobs/reactivity": "1.2.
|
|
39
|
-
"@vobs/vobs": "1.2.
|
|
38
|
+
"@vobs/reactivity": "1.2.2",
|
|
39
|
+
"@vobs/vobs": "1.2.2"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"test": "vitest --environment jsdom"
|