@vobs/storage 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 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -164
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,170 +1,38 @@
|
|
|
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
|
-
function hasDebugHooks() {
|
|
9
|
-
return activeDebugHooks !== null;
|
|
10
|
-
}
|
|
11
|
-
__name(hasDebugHooks, "hasDebugHooks");
|
|
12
|
-
function invokeDebug(name, ...args) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
__name(invokeDebug, "invokeDebug");
|
|
16
|
-
|
|
17
|
-
// packages/reactivity/src/owner.ts
|
|
18
|
-
var currentOwner = null;
|
|
19
|
-
function getCurrentOwner() {
|
|
20
|
-
return currentOwner;
|
|
21
|
-
}
|
|
22
|
-
__name(getCurrentOwner, "getCurrentOwner");
|
|
23
|
-
function onDispose(cleanup) {
|
|
24
|
-
throw new Error("Vobs: onDispose \u5FC5\u987B\u5728 Owner \u4F5C\u7528\u57DF\u5185\u8C03\u7528");
|
|
25
|
-
}
|
|
26
|
-
__name(onDispose, "onDispose");
|
|
27
|
-
|
|
28
|
-
// packages/reactivity/src/scheduler.ts
|
|
29
|
-
var _Scheduler = class _Scheduler {
|
|
30
|
-
constructor() {
|
|
31
|
-
this.dirtyEffects = /* @__PURE__ */ new Set();
|
|
32
|
-
this.lowPriorityEffects = /* @__PURE__ */ new Set();
|
|
33
|
-
// flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
|
|
34
|
-
this.normalBuffer = [];
|
|
35
|
-
this.lowBuffer = [];
|
|
36
|
-
this.flushing = false;
|
|
37
|
-
this.scheduled = false;
|
|
38
|
-
this.batchDepth = 0;
|
|
39
|
-
}
|
|
40
|
-
schedule(effect2) {
|
|
41
|
-
if (effect2.disposed) return;
|
|
42
|
-
this.dirtyEffects.add(effect2);
|
|
43
|
-
this.lowPriorityEffects.delete(effect2);
|
|
44
|
-
this.ensureScheduled();
|
|
45
|
-
}
|
|
46
|
-
/** Queue an effect behind normal updates while preserving deterministic order. */
|
|
47
|
-
scheduleLow(effect2) {
|
|
48
|
-
if (effect2.disposed) return;
|
|
49
|
-
if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
|
|
50
|
-
this.ensureScheduled();
|
|
51
|
-
}
|
|
52
|
-
ensureScheduled() {
|
|
53
|
-
if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
|
|
54
|
-
this.scheduled = true;
|
|
55
|
-
queueMicrotask(() => {
|
|
56
|
-
this.scheduled = false;
|
|
57
|
-
this.flush();
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
remove(effect2) {
|
|
62
|
-
this.dirtyEffects.delete(effect2);
|
|
63
|
-
this.lowPriorityEffects.delete(effect2);
|
|
64
|
-
}
|
|
65
|
-
batch(fn) {
|
|
66
|
-
this.batchDepth++;
|
|
67
|
-
try {
|
|
68
|
-
return fn();
|
|
69
|
-
} finally {
|
|
70
|
-
this.batchDepth--;
|
|
71
|
-
if (this.batchDepth === 0) this.flush();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
flush() {
|
|
75
|
-
if (this.flushing || this.batchDepth > 0) return;
|
|
76
|
-
this.flushing = true;
|
|
77
|
-
let rounds = 0;
|
|
78
|
-
let firstError;
|
|
79
|
-
let hasError = false;
|
|
80
|
-
try {
|
|
81
|
-
while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
|
|
82
|
-
if (++rounds > 100) {
|
|
83
|
-
this.dirtyEffects.clear();
|
|
84
|
-
this.lowPriorityEffects.clear();
|
|
85
|
-
throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
|
|
86
|
-
}
|
|
87
|
-
this.collectRunnable(this.dirtyEffects, this.normalBuffer);
|
|
88
|
-
this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
|
|
89
|
-
sortEffects(this.normalBuffer);
|
|
90
|
-
sortEffects(this.lowBuffer);
|
|
91
|
-
for (const effect2 of this.normalBuffer) {
|
|
92
|
-
try {
|
|
93
|
-
effect2.run();
|
|
94
|
-
} catch (error) {
|
|
95
|
-
if (!hasError) {
|
|
96
|
-
firstError = error;
|
|
97
|
-
hasError = true;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
for (const effect2 of this.lowBuffer) {
|
|
102
|
-
try {
|
|
103
|
-
effect2.run();
|
|
104
|
-
} catch (error) {
|
|
105
|
-
if (!hasError) {
|
|
106
|
-
firstError = error;
|
|
107
|
-
hasError = true;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
this.normalBuffer.length = 0;
|
|
112
|
-
this.lowBuffer.length = 0;
|
|
113
|
-
}
|
|
114
|
-
} finally {
|
|
115
|
-
this.normalBuffer.length = 0;
|
|
116
|
-
this.lowBuffer.length = 0;
|
|
117
|
-
this.flushing = false;
|
|
118
|
-
}
|
|
119
|
-
if (hasError) throw firstError;
|
|
120
|
-
}
|
|
121
|
-
/** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
|
|
122
|
-
collectRunnable(source, target) {
|
|
123
|
-
for (const effect2 of source) {
|
|
124
|
-
if (!effect2.disposed) target.push(effect2);
|
|
125
|
-
}
|
|
126
|
-
source.clear();
|
|
127
|
-
}
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
128
11
|
};
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
__name(sortEffects, "sortEffects");
|
|
136
|
-
|
|
137
|
-
// packages/runtime/src/hmr.ts
|
|
138
|
-
var globalTarget = globalThis;
|
|
139
|
-
var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
|
|
140
|
-
globalTarget.__VOBS_HMR__ = hmrGlobal;
|
|
141
|
-
|
|
142
|
-
// packages/vobs/src/context.ts
|
|
143
|
-
var ownerProviders = /* @__PURE__ */ new WeakMap();
|
|
144
|
-
function inject(key, fallback) {
|
|
145
|
-
const owner = getCurrentOwner();
|
|
146
|
-
const value = owner ? injectFromOwner(owner, key) : void 0;
|
|
147
|
-
return value === void 0 ? fallback : value;
|
|
148
|
-
}
|
|
149
|
-
__name(inject, "inject");
|
|
150
|
-
function injectFromOwner(owner, key) {
|
|
151
|
-
let current = owner;
|
|
152
|
-
while (current) {
|
|
153
|
-
const providers = ownerProviders.get(current);
|
|
154
|
-
if (providers?.has(key)) return providers.get(key);
|
|
155
|
-
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 });
|
|
156
17
|
}
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
// packages/vobs/src/app.ts
|
|
162
|
-
function createInjectionKey(description) {
|
|
163
|
-
return Symbol(description);
|
|
164
|
-
}
|
|
165
|
-
__name(createInjectionKey, "createInjectionKey");
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
166
21
|
|
|
167
22
|
// packages/storage/src/index.ts
|
|
23
|
+
var src_exports = {};
|
|
24
|
+
__export(src_exports, {
|
|
25
|
+
STORAGE_KEY: () => STORAGE_KEY,
|
|
26
|
+
StorageError: () => StorageError,
|
|
27
|
+
createMemoryStorage: () => createMemoryStorage,
|
|
28
|
+
createStorage: () => createStorage,
|
|
29
|
+
memoryStorage: () => memoryStorage,
|
|
30
|
+
storagePlugin: () => storagePlugin,
|
|
31
|
+
useStorage: () => useStorage
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(src_exports);
|
|
34
|
+
var import_reactivity = require("@vobs/reactivity");
|
|
35
|
+
var import_vobs = require("@vobs/vobs");
|
|
168
36
|
var _StorageError = class _StorageError extends Error {
|
|
169
37
|
constructor(code, message, key, cause) {
|
|
170
38
|
super(message);
|
|
@@ -176,7 +44,7 @@ var _StorageError = class _StorageError extends Error {
|
|
|
176
44
|
};
|
|
177
45
|
__name(_StorageError, "StorageError");
|
|
178
46
|
var StorageError = _StorageError;
|
|
179
|
-
var STORAGE_KEY = createInjectionKey("vobs.storage");
|
|
47
|
+
var STORAGE_KEY = (0, import_vobs.createInjectionKey)("vobs.storage");
|
|
180
48
|
function createMemoryStorage() {
|
|
181
49
|
const values = /* @__PURE__ */ new Map();
|
|
182
50
|
return {
|
|
@@ -290,13 +158,16 @@ function createStorage(options = {}) {
|
|
|
290
158
|
window.addEventListener("storage", onStorage);
|
|
291
159
|
stopBrowserListener = /* @__PURE__ */ __name(() => window.removeEventListener("storage", onStorage), "stopBrowserListener");
|
|
292
160
|
}
|
|
161
|
+
if ((0, import_reactivity.getCurrentOwner)()) (0, import_reactivity.onDispose)(context.dispose);
|
|
293
162
|
return context;
|
|
294
163
|
function read(key) {
|
|
295
164
|
return withBackend(key, () => backend.getItem(toPhysicalKey(key)));
|
|
296
165
|
}
|
|
166
|
+
__name(read, "read");
|
|
297
167
|
function write(key, value) {
|
|
298
168
|
withBackend(key, () => backend.setItem(toPhysicalKey(key), value));
|
|
299
169
|
}
|
|
170
|
+
__name(write, "write");
|
|
300
171
|
function decode(key, raw) {
|
|
301
172
|
let parsed;
|
|
302
173
|
try {
|
|
@@ -322,6 +193,7 @@ function createStorage(options = {}) {
|
|
|
322
193
|
return null;
|
|
323
194
|
}
|
|
324
195
|
}
|
|
196
|
+
__name(decode, "decode");
|
|
325
197
|
function decodeExternal(key, raw) {
|
|
326
198
|
try {
|
|
327
199
|
const parsed = JSON.parse(raw);
|
|
@@ -331,6 +203,7 @@ function createStorage(options = {}) {
|
|
|
331
203
|
return null;
|
|
332
204
|
}
|
|
333
205
|
}
|
|
206
|
+
__name(decodeExternal, "decodeExternal");
|
|
334
207
|
function handleCorrupt(key, cause) {
|
|
335
208
|
const storageError = new StorageError(
|
|
336
209
|
"CORRUPT_DATA",
|
|
@@ -341,6 +214,7 @@ function createStorage(options = {}) {
|
|
|
341
214
|
report(storageError);
|
|
342
215
|
withBackend(key, () => backend.removeItem(toPhysicalKey(key)));
|
|
343
216
|
}
|
|
217
|
+
__name(handleCorrupt, "handleCorrupt");
|
|
344
218
|
function withBackend(key, operation) {
|
|
345
219
|
try {
|
|
346
220
|
return operation();
|
|
@@ -367,6 +241,7 @@ function createStorage(options = {}) {
|
|
|
367
241
|
return operation();
|
|
368
242
|
}
|
|
369
243
|
}
|
|
244
|
+
__name(withBackend, "withBackend");
|
|
370
245
|
function listPhysicalKeys() {
|
|
371
246
|
const keys = [];
|
|
372
247
|
for (let index = 0; index < backend.length; index++) {
|
|
@@ -375,6 +250,7 @@ function createStorage(options = {}) {
|
|
|
375
250
|
}
|
|
376
251
|
return keys;
|
|
377
252
|
}
|
|
253
|
+
__name(listPhysicalKeys, "listPhysicalKeys");
|
|
378
254
|
function emit(change) {
|
|
379
255
|
for (const listener of [...listeners]) {
|
|
380
256
|
try {
|
|
@@ -383,18 +259,22 @@ function createStorage(options = {}) {
|
|
|
383
259
|
}
|
|
384
260
|
}
|
|
385
261
|
}
|
|
262
|
+
__name(emit, "emit");
|
|
386
263
|
function report(error) {
|
|
387
264
|
try {
|
|
388
265
|
options.onError?.(error);
|
|
389
266
|
} catch {
|
|
390
267
|
}
|
|
391
268
|
}
|
|
269
|
+
__name(report, "report");
|
|
392
270
|
function ensureActive() {
|
|
393
271
|
if (disposed) throw new Error("Vobs Storage: \u5DF2\u9500\u6BC1\u7684\u4E0A\u4E0B\u6587\u4E0D\u80FD\u7EE7\u7EED\u4F7F\u7528");
|
|
394
272
|
}
|
|
273
|
+
__name(ensureActive, "ensureActive");
|
|
395
274
|
function toPhysicalKey(key) {
|
|
396
275
|
return `${prefix}${key}`;
|
|
397
276
|
}
|
|
277
|
+
__name(toPhysicalKey, "toPhysicalKey");
|
|
398
278
|
}
|
|
399
279
|
__name(createStorage, "createStorage");
|
|
400
280
|
function storagePlugin(options = {}) {
|
|
@@ -410,7 +290,7 @@ function storagePlugin(options = {}) {
|
|
|
410
290
|
}
|
|
411
291
|
__name(storagePlugin, "storagePlugin");
|
|
412
292
|
function useStorage() {
|
|
413
|
-
const storage = inject(STORAGE_KEY);
|
|
293
|
+
const storage = (0, import_vobs.inject)(STORAGE_KEY);
|
|
414
294
|
if (!storage) throw new StorageError("STORAGE_UNAVAILABLE", "Vobs Storage: \u627E\u4E0D\u5230\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5B89\u88C5 storagePlugin");
|
|
415
295
|
return storage;
|
|
416
296
|
}
|
|
@@ -448,13 +328,14 @@ function validateVersion(version) {
|
|
|
448
328
|
return version;
|
|
449
329
|
}
|
|
450
330
|
__name(validateVersion, "validateVersion");
|
|
451
|
-
|
|
452
|
-
exports
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
331
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
332
|
+
0 && (module.exports = {
|
|
333
|
+
STORAGE_KEY,
|
|
334
|
+
StorageError,
|
|
335
|
+
createMemoryStorage,
|
|
336
|
+
createStorage,
|
|
337
|
+
memoryStorage,
|
|
338
|
+
storagePlugin,
|
|
339
|
+
useStorage
|
|
340
|
+
});
|
|
460
341
|
//# 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/scheduler.ts","../../runtime/src/hmr.ts","../../vobs/src/context.ts","../../vobs/src/app.ts","../src/index.ts"],"names":["effect","storageError"],"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 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 } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type StorageType = 'local' | 'session' | 'memory'\nexport type StorageKind = StorageType | 'custom'\n\nexport interface StorageLike {\n readonly length: number\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n key(index: number): string | null\n}\n\nexport type StorageMigration = (\n value: unknown,\n fromVersion: number,\n toVersion: number\n) => unknown\n\nexport interface StorageOptions {\n readonly storage?: StorageLike | StorageType\n readonly fallback?: StorageLike\n readonly prefix?: string\n readonly version?: number\n readonly migrate?: StorageMigration\n readonly onError?: (error: StorageError) => void\n}\n\nexport interface StorageChange {\n readonly key: string\n readonly value: unknown | null\n readonly source: 'local' | 'external'\n}\n\nexport interface StorageContext {\n readonly kind: StorageKind\n readonly persistent: boolean\n readonly prefix: string\n readonly version: number\n get<T>(key: string): T | null\n set<T>(key: string, value: T): void\n remove(key: string): void\n clear(): void\n has(key: string): boolean\n keys(): readonly string[]\n subscribe(listener: (change: StorageChange) => void): () => void\n dispose(): void\n}\n\nexport type StorageErrorCode =\n | 'STORAGE_UNAVAILABLE'\n | 'CORRUPT_DATA'\n | 'SERIALIZATION_FAILED'\n | 'MIGRATION_FAILED'\n\nexport class StorageError extends Error {\n readonly code: StorageErrorCode\n readonly key: string | undefined\n readonly cause: unknown\n\n constructor(code: StorageErrorCode, message: string, key?: string, cause?: unknown) {\n super(message)\n this.name = 'StorageError'\n this.code = code\n this.key = key\n this.cause = cause\n }\n}\n\nexport const STORAGE_KEY: InjectionKey<StorageContext> = createInjectionKey<StorageContext>('vobs.storage')\n\nexport interface StoragePluginOptions extends StorageOptions {\n readonly context?: StorageContext\n}\n\ninterface Envelope {\n readonly __vobsStorage: true\n readonly version: number\n readonly value: unknown\n}\n\nexport function createMemoryStorage(): StorageLike {\n const values = new Map<string, string>()\n return {\n get length(): number {\n return values.size\n },\n getItem(key): string | null {\n return values.get(key) ?? null\n },\n setItem(key, value): void {\n values.set(key, value)\n },\n removeItem(key): void {\n values.delete(key)\n },\n key(index): string | null {\n return [...values.keys()][index] ?? null\n }\n }\n}\n\nexport const memoryStorage = createMemoryStorage()\n\nexport function createStorage(options: StorageOptions = {}): StorageContext {\n const prefix = options.prefix ?? 'vobs:'\n const version = validateVersion(options.version ?? 1)\n const fallback = options.fallback ?? createMemoryStorage()\n const selected = resolveStorage(options.storage)\n let backend = selected.backend ?? fallback\n let kind: StorageKind = selected.kind\n let disposed = false\n let stopBrowserListener: (() => void) | undefined\n const listeners = new Set<(change: StorageChange) => void>()\n\n const context: StorageContext = {\n get kind(): StorageKind {\n return kind\n },\n\n get persistent(): boolean {\n return kind !== 'memory'\n },\n\n prefix,\n version,\n\n get<T>(key: string): T | null {\n ensureActive()\n const normalizedKey = validateKey(key)\n const raw = read(normalizedKey)\n if (raw === null) return null\n return decode<T>(normalizedKey, raw)\n },\n\n set<T>(key: string, value: T): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n let raw: string\n try {\n raw = JSON.stringify({ __vobsStorage: true, version, value } satisfies Envelope)\n } catch (error) {\n const storageError = new StorageError(\n 'SERIALIZATION_FAILED',\n `Vobs Storage: 无法序列化键 ${normalizedKey}`,\n normalizedKey,\n error\n )\n report(storageError)\n throw storageError\n }\n write(normalizedKey, raw)\n emit({ key: normalizedKey, value, source: 'local' })\n },\n\n remove(key: string): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n withBackend(normalizedKey, () => backend.removeItem(toPhysicalKey(normalizedKey)))\n emit({ key: normalizedKey, value: null, source: 'local' })\n },\n\n clear(): void {\n ensureActive()\n const physicalKeys = listPhysicalKeys()\n for (const physicalKey of physicalKeys) {\n withBackend(physicalKey, () => backend.removeItem(physicalKey))\n }\n for (const physicalKey of physicalKeys) {\n emit({ key: physicalKey.slice(prefix.length), value: null, source: 'local' })\n }\n },\n\n has(key: string): boolean {\n return context.get(key) !== null\n },\n\n keys(): readonly string[] {\n ensureActive()\n return listPhysicalKeys().map(key => key.slice(prefix.length))\n },\n\n subscribe(listener): () => void {\n ensureActive()\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n stopBrowserListener?.()\n stopBrowserListener = undefined\n listeners.clear()\n }\n }\n\n if (selected.browserStorage && typeof window !== 'undefined') {\n const onStorage = (event: StorageEvent): void => {\n if (event.storageArea && event.storageArea !== backend) return\n if (!event.key || !event.key.startsWith(prefix)) return\n const key = event.key.slice(prefix.length)\n emit({ key, value: event.newValue === null ? null : decodeExternal(key, event.newValue), source: 'external' })\n }\n window.addEventListener('storage', onStorage)\n stopBrowserListener = () => window.removeEventListener('storage', onStorage)\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function read(key: string): string | null {\n return withBackend(key, () => backend.getItem(toPhysicalKey(key)))\n }\n\n function write(key: string, value: string): void {\n withBackend(key, () => backend.setItem(toPhysicalKey(key), value))\n }\n\n function decode<T>(key: string, raw: string): T | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n\n const envelope = isEnvelope(parsed) ? parsed : { version: 0, value: parsed }\n if (envelope.version >= version || !options.migrate) return envelope.value as T | null\n\n try {\n const migrated = options.migrate(envelope.value, envelope.version, version)\n write(key, JSON.stringify({ __vobsStorage: true, version, value: migrated } satisfies Envelope))\n return migrated as T | null\n } catch (error) {\n const storageError = new StorageError(\n 'MIGRATION_FAILED',\n `Vobs Storage: 键 ${key} 迁移失败`,\n key,\n error\n )\n report(storageError)\n return null\n }\n }\n\n function decodeExternal(key: string, raw: string): unknown | null {\n try {\n const parsed = JSON.parse(raw)\n return isEnvelope(parsed) ? parsed.value : parsed\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n }\n\n function handleCorrupt(key: string, cause: unknown): void {\n const storageError = new StorageError(\n 'CORRUPT_DATA',\n `Vobs Storage: 键 ${key} 的数据已损坏`,\n key,\n cause\n )\n report(storageError)\n withBackend(key, () => backend.removeItem(toPhysicalKey(key)))\n }\n\n function withBackend<T>(key: string, operation: () => T): T {\n try {\n return operation()\n } catch (error) {\n if (backend === fallback) {\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用',\n key,\n error\n )\n report(storageError)\n throw storageError\n }\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用,已切换到内存 fallback',\n key,\n error\n )\n report(storageError)\n backend = fallback\n kind = 'memory'\n return operation()\n }\n }\n\n function listPhysicalKeys(): string[] {\n const keys: string[] = []\n for (let index = 0; index < backend.length; index++) {\n const key = backend.key(index)\n if (key?.startsWith(prefix)) keys.push(key)\n }\n return keys\n }\n\n function emit(change: StorageChange): void {\n for (const listener of [...listeners]) {\n try {\n listener(change)\n } catch {\n // 订阅者错误不能阻止其他订阅者接收变化。\n }\n }\n }\n\n function report(error: StorageError): void {\n try {\n options.onError?.(error)\n } catch {\n // 错误回调不能覆盖存储操作的原始结果。\n }\n }\n\n function ensureActive(): void {\n if (disposed) throw new Error('Vobs Storage: 已销毁的上下文不能继续使用')\n }\n\n function toPhysicalKey(key: string): string {\n return `${prefix}${key}`\n }\n}\n\nexport function storagePlugin(options: StoragePluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/storage',\n version: '0.1.0',\n install(context) {\n const ownedStorage = options.context ? undefined : createStorage(options)\n context.provide(STORAGE_KEY, options.context ?? ownedStorage!)\n return () => ownedStorage?.dispose()\n }\n }\n}\n\nexport function useStorage(): StorageContext {\n const storage = inject(STORAGE_KEY)\n if (!storage) throw new StorageError('STORAGE_UNAVAILABLE', 'Vobs Storage: 找不到上下文,请安装 storagePlugin')\n return storage\n}\n\nfunction resolveStorage(input: StorageLike | StorageType | undefined): {\n backend: StorageLike | undefined\n kind: StorageKind\n browserStorage: boolean\n} {\n if (input && typeof input !== 'string') return { backend: input, kind: 'custom', browserStorage: false }\n const type = input ?? 'local'\n if (type === 'memory') return { backend: memoryStorage, kind: 'memory', browserStorage: false }\n const backend = getBrowserStorage(type)\n return { backend, kind: backend ? type : 'memory', browserStorage: Boolean(backend) }\n}\n\nfunction getBrowserStorage(type: Exclude<StorageType, 'memory'>): StorageLike | undefined {\n if (typeof window === 'undefined') return undefined\n try {\n return type === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return undefined\n }\n}\n\nfunction isEnvelope(value: unknown): value is Envelope {\n return Boolean(value)\n && typeof value === 'object'\n && value !== null\n && (value as { __vobsStorage?: unknown }).__vobsStorage === true\n && Number.isInteger((value as { version?: unknown }).version)\n && 'value' in value\n}\n\nfunction validateKey(key: string): string {\n if (typeof key !== 'string' || !key.trim()) throw new Error('Vobs Storage: key 不能为空')\n return key\n}\n\nfunction validateVersion(version: number): number {\n if (!Number.isInteger(version) || version < 0) {\n throw new Error('Vobs Storage: version 必须是大于等于 0 的整数')\n }\n return version\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getCurrentOwner, onDispose } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type StorageType = 'local' | 'session' | 'memory'\nexport type StorageKind = StorageType | 'custom'\n\nexport interface StorageLike {\n readonly length: number\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n key(index: number): string | null\n}\n\nexport type StorageMigration = (\n value: unknown,\n fromVersion: number,\n toVersion: number\n) => unknown\n\nexport interface StorageOptions {\n readonly storage?: StorageLike | StorageType\n readonly fallback?: StorageLike\n readonly prefix?: string\n readonly version?: number\n readonly migrate?: StorageMigration\n readonly onError?: (error: StorageError) => void\n}\n\nexport interface StorageChange {\n readonly key: string\n readonly value: unknown | null\n readonly source: 'local' | 'external'\n}\n\nexport interface StorageContext {\n readonly kind: StorageKind\n readonly persistent: boolean\n readonly prefix: string\n readonly version: number\n get<T>(key: string): T | null\n set<T>(key: string, value: T): void\n remove(key: string): void\n clear(): void\n has(key: string): boolean\n keys(): readonly string[]\n subscribe(listener: (change: StorageChange) => void): () => void\n dispose(): void\n}\n\nexport type StorageErrorCode =\n | 'STORAGE_UNAVAILABLE'\n | 'CORRUPT_DATA'\n | 'SERIALIZATION_FAILED'\n | 'MIGRATION_FAILED'\n\nexport class StorageError extends Error {\n readonly code: StorageErrorCode\n readonly key: string | undefined\n readonly cause: unknown\n\n constructor(code: StorageErrorCode, message: string, key?: string, cause?: unknown) {\n super(message)\n this.name = 'StorageError'\n this.code = code\n this.key = key\n this.cause = cause\n }\n}\n\nexport const STORAGE_KEY: InjectionKey<StorageContext> = createInjectionKey<StorageContext>('vobs.storage')\n\nexport interface StoragePluginOptions extends StorageOptions {\n readonly context?: StorageContext\n}\n\ninterface Envelope {\n readonly __vobsStorage: true\n readonly version: number\n readonly value: unknown\n}\n\nexport function createMemoryStorage(): StorageLike {\n const values = new Map<string, string>()\n return {\n get length(): number {\n return values.size\n },\n getItem(key): string | null {\n return values.get(key) ?? null\n },\n setItem(key, value): void {\n values.set(key, value)\n },\n removeItem(key): void {\n values.delete(key)\n },\n key(index): string | null {\n return [...values.keys()][index] ?? null\n }\n }\n}\n\nexport const memoryStorage = createMemoryStorage()\n\nexport function createStorage(options: StorageOptions = {}): StorageContext {\n const prefix = options.prefix ?? 'vobs:'\n const version = validateVersion(options.version ?? 1)\n const fallback = options.fallback ?? createMemoryStorage()\n const selected = resolveStorage(options.storage)\n let backend = selected.backend ?? fallback\n let kind: StorageKind = selected.kind\n let disposed = false\n let stopBrowserListener: (() => void) | undefined\n const listeners = new Set<(change: StorageChange) => void>()\n\n const context: StorageContext = {\n get kind(): StorageKind {\n return kind\n },\n\n get persistent(): boolean {\n return kind !== 'memory'\n },\n\n prefix,\n version,\n\n get<T>(key: string): T | null {\n ensureActive()\n const normalizedKey = validateKey(key)\n const raw = read(normalizedKey)\n if (raw === null) return null\n return decode<T>(normalizedKey, raw)\n },\n\n set<T>(key: string, value: T): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n let raw: string\n try {\n raw = JSON.stringify({ __vobsStorage: true, version, value } satisfies Envelope)\n } catch (error) {\n const storageError = new StorageError(\n 'SERIALIZATION_FAILED',\n `Vobs Storage: 无法序列化键 ${normalizedKey}`,\n normalizedKey,\n error\n )\n report(storageError)\n throw storageError\n }\n write(normalizedKey, raw)\n emit({ key: normalizedKey, value, source: 'local' })\n },\n\n remove(key: string): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n withBackend(normalizedKey, () => backend.removeItem(toPhysicalKey(normalizedKey)))\n emit({ key: normalizedKey, value: null, source: 'local' })\n },\n\n clear(): void {\n ensureActive()\n const physicalKeys = listPhysicalKeys()\n for (const physicalKey of physicalKeys) {\n withBackend(physicalKey, () => backend.removeItem(physicalKey))\n }\n for (const physicalKey of physicalKeys) {\n emit({ key: physicalKey.slice(prefix.length), value: null, source: 'local' })\n }\n },\n\n has(key: string): boolean {\n return context.get(key) !== null\n },\n\n keys(): readonly string[] {\n ensureActive()\n return listPhysicalKeys().map(key => key.slice(prefix.length))\n },\n\n subscribe(listener): () => void {\n ensureActive()\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n stopBrowserListener?.()\n stopBrowserListener = undefined\n listeners.clear()\n }\n }\n\n if (selected.browserStorage && typeof window !== 'undefined') {\n const onStorage = (event: StorageEvent): void => {\n if (event.storageArea && event.storageArea !== backend) return\n if (!event.key || !event.key.startsWith(prefix)) return\n const key = event.key.slice(prefix.length)\n emit({ key, value: event.newValue === null ? null : decodeExternal(key, event.newValue), source: 'external' })\n }\n window.addEventListener('storage', onStorage)\n stopBrowserListener = () => window.removeEventListener('storage', onStorage)\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function read(key: string): string | null {\n return withBackend(key, () => backend.getItem(toPhysicalKey(key)))\n }\n\n function write(key: string, value: string): void {\n withBackend(key, () => backend.setItem(toPhysicalKey(key), value))\n }\n\n function decode<T>(key: string, raw: string): T | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n\n const envelope = isEnvelope(parsed) ? parsed : { version: 0, value: parsed }\n if (envelope.version >= version || !options.migrate) return envelope.value as T | null\n\n try {\n const migrated = options.migrate(envelope.value, envelope.version, version)\n write(key, JSON.stringify({ __vobsStorage: true, version, value: migrated } satisfies Envelope))\n return migrated as T | null\n } catch (error) {\n const storageError = new StorageError(\n 'MIGRATION_FAILED',\n `Vobs Storage: 键 ${key} 迁移失败`,\n key,\n error\n )\n report(storageError)\n return null\n }\n }\n\n function decodeExternal(key: string, raw: string): unknown | null {\n try {\n const parsed = JSON.parse(raw)\n return isEnvelope(parsed) ? parsed.value : parsed\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n }\n\n function handleCorrupt(key: string, cause: unknown): void {\n const storageError = new StorageError(\n 'CORRUPT_DATA',\n `Vobs Storage: 键 ${key} 的数据已损坏`,\n key,\n cause\n )\n report(storageError)\n withBackend(key, () => backend.removeItem(toPhysicalKey(key)))\n }\n\n function withBackend<T>(key: string, operation: () => T): T {\n try {\n return operation()\n } catch (error) {\n if (backend === fallback) {\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用',\n key,\n error\n )\n report(storageError)\n throw storageError\n }\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用,已切换到内存 fallback',\n key,\n error\n )\n report(storageError)\n backend = fallback\n kind = 'memory'\n return operation()\n }\n }\n\n function listPhysicalKeys(): string[] {\n const keys: string[] = []\n for (let index = 0; index < backend.length; index++) {\n const key = backend.key(index)\n if (key?.startsWith(prefix)) keys.push(key)\n }\n return keys\n }\n\n function emit(change: StorageChange): void {\n for (const listener of [...listeners]) {\n try {\n listener(change)\n } catch {\n // 订阅者错误不能阻止其他订阅者接收变化。\n }\n }\n }\n\n function report(error: StorageError): void {\n try {\n options.onError?.(error)\n } catch {\n // 错误回调不能覆盖存储操作的原始结果。\n }\n }\n\n function ensureActive(): void {\n if (disposed) throw new Error('Vobs Storage: 已销毁的上下文不能继续使用')\n }\n\n function toPhysicalKey(key: string): string {\n return `${prefix}${key}`\n }\n}\n\nexport function storagePlugin(options: StoragePluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/storage',\n version: '0.1.0',\n install(context) {\n const ownedStorage = options.context ? undefined : createStorage(options)\n context.provide(STORAGE_KEY, options.context ?? ownedStorage!)\n return () => ownedStorage?.dispose()\n }\n }\n}\n\nexport function useStorage(): StorageContext {\n const storage = inject(STORAGE_KEY)\n if (!storage) throw new StorageError('STORAGE_UNAVAILABLE', 'Vobs Storage: 找不到上下文,请安装 storagePlugin')\n return storage\n}\n\nfunction resolveStorage(input: StorageLike | StorageType | undefined): {\n backend: StorageLike | undefined\n kind: StorageKind\n browserStorage: boolean\n} {\n if (input && typeof input !== 'string') return { backend: input, kind: 'custom', browserStorage: false }\n const type = input ?? 'local'\n if (type === 'memory') return { backend: memoryStorage, kind: 'memory', browserStorage: false }\n const backend = getBrowserStorage(type)\n return { backend, kind: backend ? type : 'memory', browserStorage: Boolean(backend) }\n}\n\nfunction getBrowserStorage(type: Exclude<StorageType, 'memory'>): StorageLike | undefined {\n if (typeof window === 'undefined') return undefined\n try {\n return type === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return undefined\n }\n}\n\nfunction isEnvelope(value: unknown): value is Envelope {\n return Boolean(value)\n && typeof value === 'object'\n && value !== null\n && (value as { __vobsStorage?: unknown }).__vobsStorage === true\n && Number.isInteger((value as { version?: unknown }).version)\n && 'value' in value\n}\n\nfunction validateKey(key: string): string {\n if (typeof key !== 'string' || !key.trim()) throw new Error('Vobs Storage: key 不能为空')\n return key\n}\n\nfunction validateVersion(version: number): number {\n if (!Number.isInteger(version) || version < 0) {\n throw new Error('Vobs Storage: version 必须是大于等于 0 的整数')\n }\n return version\n}\n"],"mappings":"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","names":["storageError"]}
|
package/dist/index.js
CHANGED
|
@@ -1,168 +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
|
-
function hasDebugHooks() {
|
|
7
|
-
return activeDebugHooks !== null;
|
|
8
|
-
}
|
|
9
|
-
__name(hasDebugHooks, "hasDebugHooks");
|
|
10
|
-
function invokeDebug(name, ...args) {
|
|
11
|
-
return;
|
|
12
|
-
}
|
|
13
|
-
__name(invokeDebug, "invokeDebug");
|
|
14
|
-
|
|
15
|
-
// packages/reactivity/src/owner.ts
|
|
16
|
-
var currentOwner = null;
|
|
17
|
-
function getCurrentOwner() {
|
|
18
|
-
return currentOwner;
|
|
19
|
-
}
|
|
20
|
-
__name(getCurrentOwner, "getCurrentOwner");
|
|
21
|
-
function onDispose(cleanup) {
|
|
22
|
-
throw new Error("Vobs: onDispose \u5FC5\u987B\u5728 Owner \u4F5C\u7528\u57DF\u5185\u8C03\u7528");
|
|
23
|
-
}
|
|
24
|
-
__name(onDispose, "onDispose");
|
|
25
|
-
|
|
26
|
-
// packages/reactivity/src/scheduler.ts
|
|
27
|
-
var _Scheduler = class _Scheduler {
|
|
28
|
-
constructor() {
|
|
29
|
-
this.dirtyEffects = /* @__PURE__ */ new Set();
|
|
30
|
-
this.lowPriorityEffects = /* @__PURE__ */ new Set();
|
|
31
|
-
// flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
|
|
32
|
-
this.normalBuffer = [];
|
|
33
|
-
this.lowBuffer = [];
|
|
34
|
-
this.flushing = false;
|
|
35
|
-
this.scheduled = false;
|
|
36
|
-
this.batchDepth = 0;
|
|
37
|
-
}
|
|
38
|
-
schedule(effect2) {
|
|
39
|
-
if (effect2.disposed) return;
|
|
40
|
-
this.dirtyEffects.add(effect2);
|
|
41
|
-
this.lowPriorityEffects.delete(effect2);
|
|
42
|
-
this.ensureScheduled();
|
|
43
|
-
}
|
|
44
|
-
/** Queue an effect behind normal updates while preserving deterministic order. */
|
|
45
|
-
scheduleLow(effect2) {
|
|
46
|
-
if (effect2.disposed) return;
|
|
47
|
-
if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
|
|
48
|
-
this.ensureScheduled();
|
|
49
|
-
}
|
|
50
|
-
ensureScheduled() {
|
|
51
|
-
if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
|
|
52
|
-
this.scheduled = true;
|
|
53
|
-
queueMicrotask(() => {
|
|
54
|
-
this.scheduled = false;
|
|
55
|
-
this.flush();
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
remove(effect2) {
|
|
60
|
-
this.dirtyEffects.delete(effect2);
|
|
61
|
-
this.lowPriorityEffects.delete(effect2);
|
|
62
|
-
}
|
|
63
|
-
batch(fn) {
|
|
64
|
-
this.batchDepth++;
|
|
65
|
-
try {
|
|
66
|
-
return fn();
|
|
67
|
-
} finally {
|
|
68
|
-
this.batchDepth--;
|
|
69
|
-
if (this.batchDepth === 0) this.flush();
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
flush() {
|
|
73
|
-
if (this.flushing || this.batchDepth > 0) return;
|
|
74
|
-
this.flushing = true;
|
|
75
|
-
let rounds = 0;
|
|
76
|
-
let firstError;
|
|
77
|
-
let hasError = false;
|
|
78
|
-
try {
|
|
79
|
-
while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
|
|
80
|
-
if (++rounds > 100) {
|
|
81
|
-
this.dirtyEffects.clear();
|
|
82
|
-
this.lowPriorityEffects.clear();
|
|
83
|
-
throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
|
|
84
|
-
}
|
|
85
|
-
this.collectRunnable(this.dirtyEffects, this.normalBuffer);
|
|
86
|
-
this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
|
|
87
|
-
sortEffects(this.normalBuffer);
|
|
88
|
-
sortEffects(this.lowBuffer);
|
|
89
|
-
for (const effect2 of this.normalBuffer) {
|
|
90
|
-
try {
|
|
91
|
-
effect2.run();
|
|
92
|
-
} catch (error) {
|
|
93
|
-
if (!hasError) {
|
|
94
|
-
firstError = error;
|
|
95
|
-
hasError = true;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
for (const effect2 of this.lowBuffer) {
|
|
100
|
-
try {
|
|
101
|
-
effect2.run();
|
|
102
|
-
} catch (error) {
|
|
103
|
-
if (!hasError) {
|
|
104
|
-
firstError = error;
|
|
105
|
-
hasError = true;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
this.normalBuffer.length = 0;
|
|
110
|
-
this.lowBuffer.length = 0;
|
|
111
|
-
}
|
|
112
|
-
} finally {
|
|
113
|
-
this.normalBuffer.length = 0;
|
|
114
|
-
this.lowBuffer.length = 0;
|
|
115
|
-
this.flushing = false;
|
|
116
|
-
}
|
|
117
|
-
if (hasError) throw firstError;
|
|
118
|
-
}
|
|
119
|
-
/** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
|
|
120
|
-
collectRunnable(source, target) {
|
|
121
|
-
for (const effect2 of source) {
|
|
122
|
-
if (!effect2.disposed) target.push(effect2);
|
|
123
|
-
}
|
|
124
|
-
source.clear();
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
__name(_Scheduler, "Scheduler");
|
|
128
|
-
function sortEffects(effects) {
|
|
129
|
-
if (effects.length > 1) {
|
|
130
|
-
effects.sort((a, b) => b.depth - a.depth || a.order - b.order);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
__name(sortEffects, "sortEffects");
|
|
134
|
-
|
|
135
|
-
// packages/runtime/src/hmr.ts
|
|
136
|
-
var globalTarget = globalThis;
|
|
137
|
-
var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
|
|
138
|
-
globalTarget.__VOBS_HMR__ = hmrGlobal;
|
|
139
|
-
|
|
140
|
-
// packages/vobs/src/context.ts
|
|
141
|
-
var ownerProviders = /* @__PURE__ */ new WeakMap();
|
|
142
|
-
function inject(key, fallback) {
|
|
143
|
-
const owner = getCurrentOwner();
|
|
144
|
-
const value = owner ? injectFromOwner(owner, key) : void 0;
|
|
145
|
-
return value === void 0 ? fallback : value;
|
|
146
|
-
}
|
|
147
|
-
__name(inject, "inject");
|
|
148
|
-
function injectFromOwner(owner, key) {
|
|
149
|
-
let current = owner;
|
|
150
|
-
while (current) {
|
|
151
|
-
const providers = ownerProviders.get(current);
|
|
152
|
-
if (providers?.has(key)) return providers.get(key);
|
|
153
|
-
current = current.parent;
|
|
154
|
-
}
|
|
155
|
-
return void 0;
|
|
156
|
-
}
|
|
157
|
-
__name(injectFromOwner, "injectFromOwner");
|
|
158
|
-
|
|
159
|
-
// packages/vobs/src/app.ts
|
|
160
|
-
function createInjectionKey(description) {
|
|
161
|
-
return Symbol(description);
|
|
162
|
-
}
|
|
163
|
-
__name(createInjectionKey, "createInjectionKey");
|
|
164
|
-
|
|
165
4
|
// packages/storage/src/index.ts
|
|
5
|
+
import { getCurrentOwner, onDispose } from "@vobs/reactivity";
|
|
6
|
+
import { createInjectionKey, inject } from "@vobs/vobs";
|
|
166
7
|
var _StorageError = class _StorageError extends Error {
|
|
167
8
|
constructor(code, message, key, cause) {
|
|
168
9
|
super(message);
|
|
@@ -288,13 +129,16 @@ function createStorage(options = {}) {
|
|
|
288
129
|
window.addEventListener("storage", onStorage);
|
|
289
130
|
stopBrowserListener = /* @__PURE__ */ __name(() => window.removeEventListener("storage", onStorage), "stopBrowserListener");
|
|
290
131
|
}
|
|
132
|
+
if (getCurrentOwner()) onDispose(context.dispose);
|
|
291
133
|
return context;
|
|
292
134
|
function read(key) {
|
|
293
135
|
return withBackend(key, () => backend.getItem(toPhysicalKey(key)));
|
|
294
136
|
}
|
|
137
|
+
__name(read, "read");
|
|
295
138
|
function write(key, value) {
|
|
296
139
|
withBackend(key, () => backend.setItem(toPhysicalKey(key), value));
|
|
297
140
|
}
|
|
141
|
+
__name(write, "write");
|
|
298
142
|
function decode(key, raw) {
|
|
299
143
|
let parsed;
|
|
300
144
|
try {
|
|
@@ -320,6 +164,7 @@ function createStorage(options = {}) {
|
|
|
320
164
|
return null;
|
|
321
165
|
}
|
|
322
166
|
}
|
|
167
|
+
__name(decode, "decode");
|
|
323
168
|
function decodeExternal(key, raw) {
|
|
324
169
|
try {
|
|
325
170
|
const parsed = JSON.parse(raw);
|
|
@@ -329,6 +174,7 @@ function createStorage(options = {}) {
|
|
|
329
174
|
return null;
|
|
330
175
|
}
|
|
331
176
|
}
|
|
177
|
+
__name(decodeExternal, "decodeExternal");
|
|
332
178
|
function handleCorrupt(key, cause) {
|
|
333
179
|
const storageError = new StorageError(
|
|
334
180
|
"CORRUPT_DATA",
|
|
@@ -339,6 +185,7 @@ function createStorage(options = {}) {
|
|
|
339
185
|
report(storageError);
|
|
340
186
|
withBackend(key, () => backend.removeItem(toPhysicalKey(key)));
|
|
341
187
|
}
|
|
188
|
+
__name(handleCorrupt, "handleCorrupt");
|
|
342
189
|
function withBackend(key, operation) {
|
|
343
190
|
try {
|
|
344
191
|
return operation();
|
|
@@ -365,6 +212,7 @@ function createStorage(options = {}) {
|
|
|
365
212
|
return operation();
|
|
366
213
|
}
|
|
367
214
|
}
|
|
215
|
+
__name(withBackend, "withBackend");
|
|
368
216
|
function listPhysicalKeys() {
|
|
369
217
|
const keys = [];
|
|
370
218
|
for (let index = 0; index < backend.length; index++) {
|
|
@@ -373,6 +221,7 @@ function createStorage(options = {}) {
|
|
|
373
221
|
}
|
|
374
222
|
return keys;
|
|
375
223
|
}
|
|
224
|
+
__name(listPhysicalKeys, "listPhysicalKeys");
|
|
376
225
|
function emit(change) {
|
|
377
226
|
for (const listener of [...listeners]) {
|
|
378
227
|
try {
|
|
@@ -381,18 +230,22 @@ function createStorage(options = {}) {
|
|
|
381
230
|
}
|
|
382
231
|
}
|
|
383
232
|
}
|
|
233
|
+
__name(emit, "emit");
|
|
384
234
|
function report(error) {
|
|
385
235
|
try {
|
|
386
236
|
options.onError?.(error);
|
|
387
237
|
} catch {
|
|
388
238
|
}
|
|
389
239
|
}
|
|
240
|
+
__name(report, "report");
|
|
390
241
|
function ensureActive() {
|
|
391
242
|
if (disposed) throw new Error("Vobs Storage: \u5DF2\u9500\u6BC1\u7684\u4E0A\u4E0B\u6587\u4E0D\u80FD\u7EE7\u7EED\u4F7F\u7528");
|
|
392
243
|
}
|
|
244
|
+
__name(ensureActive, "ensureActive");
|
|
393
245
|
function toPhysicalKey(key) {
|
|
394
246
|
return `${prefix}${key}`;
|
|
395
247
|
}
|
|
248
|
+
__name(toPhysicalKey, "toPhysicalKey");
|
|
396
249
|
}
|
|
397
250
|
__name(createStorage, "createStorage");
|
|
398
251
|
function storagePlugin(options = {}) {
|
|
@@ -446,7 +299,13 @@ function validateVersion(version) {
|
|
|
446
299
|
return version;
|
|
447
300
|
}
|
|
448
301
|
__name(validateVersion, "validateVersion");
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
302
|
+
export {
|
|
303
|
+
STORAGE_KEY,
|
|
304
|
+
StorageError,
|
|
305
|
+
createMemoryStorage,
|
|
306
|
+
createStorage,
|
|
307
|
+
memoryStorage,
|
|
308
|
+
storagePlugin,
|
|
309
|
+
useStorage
|
|
310
|
+
};
|
|
452
311
|
//# 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/scheduler.ts","../../runtime/src/hmr.ts","../../vobs/src/context.ts","../../vobs/src/app.ts","../src/index.ts"],"names":["effect","storageError"],"mappings":";;;;AA0BA,IAAI,gBAAA,GAAgD,IAAA;AAc7C,SAAS,aAAA,GAAyB;AACvC,EAAA,OAAO,gBAAA,KAAqB,IAAA;AAC9B;AAFgB,MAAA,CAAA,aAAA,EAAA,eAAA,CAAA;AAaT,SAAS,WAAA,CACd,SACG,IAAA,EACG;AAEN,EAAe;AAMjB;AAXgB,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;;;ACrChB,IAAI,YAAA,GAA6B,IAAA;AAsG1B,SAAS,eAAA,GAAgC;AAC9C,EAAA,OAAO,YAAA;AACT;AAFgB,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA;AAST,SAAS,UAAU,OAAA,EAA2B;AAEnD,EAAY,MAAM,IAAI,MAAM,+EAAkC,CAAA;AAEhE;AAJgB,MAAA,CAAA,SAAA,EAAA,WAAA,CAAA;;;AC5HT,IAAM,UAAA,GAAN,MAAM,UAAA,CAAU;AAAA,EAAhB,WAAA,GAAA;AACL,IAAA,IAAA,CAAiB,YAAA,uBAAmB,GAAA,EAAY;AAChD,IAAA,IAAA,CAAiB,kBAAA,uBAAyB,GAAA,EAAY;AAEtD;AAAA,IAAA,IAAA,CAAiB,eAAyB,EAAC;AAC3C,IAAA,IAAA,CAAiB,YAAsB,EAAC;AACxC,IAAA,IAAA,CAAQ,QAAA,GAAW,KAAA;AACnB,IAAA,IAAA,CAAQ,SAAA,GAAY,KAAA;AACpB,IAAA,IAAA,CAAQ,UAAA,GAAa,CAAA;AAAA,EAAA;AAAA,EAErB,SAASA,OAAAA,EAAsB;AAC7B,IAAA,IAAIA,QAAO,QAAA,EAAU;AACrB,IAAA,IAAA,CAAK,YAAA,CAAa,IAAIA,OAAM,CAAA;AAC5B,IAAA,IAAA,CAAK,kBAAA,CAAmB,OAAOA,OAAM,CAAA;AACrC,IAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,EACvB;AAAA;AAAA,EAGA,YAAYA,OAAAA,EAAsB;AAChC,IAAA,IAAIA,QAAO,QAAA,EAAU;AACrB,IAAA,IAAI,CAAC,KAAK,YAAA,CAAa,GAAA,CAAIA,OAAM,CAAA,EAAG,IAAA,CAAK,kBAAA,CAAmB,GAAA,CAAIA,OAAM,CAAA;AACtE,IAAA,IAAA,CAAK,eAAA,EAAgB;AAAA,EACvB;AAAA,EAEQ,eAAA,GAAwB;AAC9B,IAAA,IAAI,IAAA,CAAK,eAAe,CAAA,IAAK,CAAC,KAAK,QAAA,IAAY,CAAC,KAAK,SAAA,EAAW;AAC9D,MAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AACjB,MAAA,cAAA,CAAe,MAAM;AACnB,QAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AACjB,QAAA,IAAA,CAAK,KAAA,EAAM;AAAA,MACb,CAAC,CAAA;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAOA,OAAAA,EAAsB;AAC3B,IAAA,IAAA,CAAK,YAAA,CAAa,OAAOA,OAAM,CAAA;AAC/B,IAAA,IAAA,CAAK,kBAAA,CAAmB,OAAOA,OAAM,CAAA;AAAA,EACvC;AAAA,EAEA,MAAS,EAAA,EAAgB;AACvB,IAAA,IAAA,CAAK,UAAA,EAAA;AACL,IAAA,IAAI;AACF,MAAA,OAAO,EAAA,EAAG;AAAA,IACZ,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,UAAA,EAAA;AACL,MAAA,IAAI,IAAA,CAAK,UAAA,KAAe,CAAA,EAAG,IAAA,CAAK,KAAA,EAAM;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAI,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,UAAA,GAAa,CAAA,EAAG;AAC1C,IAAA,IAAA,CAAK,QAAA,GAAW,IAAA;AAGhB,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,IAAI,UAAA;AACJ,IAAA,IAAI,QAAA,GAAW,KAAA;AACf,IAAA,IAAI;AACF,MAAA,OAAO,KAAK,YAAA,CAAa,IAAA,GAAO,KAAK,IAAA,CAAK,kBAAA,CAAmB,OAAO,CAAA,EAAG;AACrE,QAAA,IAAI,EAAE,SAAS,GAAA,EAAK;AAClB,UAAA,IAAA,CAAK,aAAa,KAAA,EAAM;AACxB,UAAA,IAAA,CAAK,mBAAmB,KAAA,EAAM;AAC9B,UAAA,MAAM,IAAI,MAAM,mHAA8B,CAAA;AAAA,QAChD;AAIA,QAAA,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,YAAA,EAAc,IAAA,CAAK,YAAY,CAAA;AACzD,QAAA,IAAA,CAAK,eAAA,CAAgB,IAAA,CAAK,kBAAA,EAAoB,IAAA,CAAK,SAAS,CAAA;AAC5D,QAAA,WAAA,CAAY,KAAK,YAAY,CAAA;AAC7B,QAAA,WAAA,CAAY,KAAK,SAAS,CAAA;AAC1B,QAAA,KAAA,MAAWA,OAAAA,IAAU,KAAK,YAAA,EAAc;AACtC,UAAA,IAAI;AACF,YAAAA,QAAO,GAAA,EAAI;AAAA,UACb,SAAS,KAAA,EAAO;AAGd,YAAA,IAAI,CAAC,QAAA,EAAU;AACb,cAAA,UAAA,GAAa,KAAA;AACb,cAAA,QAAA,GAAW,IAAA;AAAA,YACb;AAAA,UACF;AAAA,QACF;AACA,QAAA,KAAA,MAAWA,OAAAA,IAAU,KAAK,SAAA,EAAW;AACnC,UAAA,IAAI;AACF,YAAAA,QAAO,GAAA,EAAI;AAAA,UACb,SAAS,KAAA,EAAO;AACd,YAAA,IAAI,CAAC,QAAA,EAAU;AACb,cAAA,UAAA,GAAa,KAAA;AACb,cAAA,QAAA,GAAW,IAAA;AAAA,YACb;AAAA,UACF;AAAA,QACF;AACA,QAAA,IAAA,CAAK,aAAa,MAAA,GAAS,CAAA;AAC3B,QAAA,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA;AAAA,MAC1B;AAAA,IACF,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,aAAa,MAAA,GAAS,CAAA;AAC3B,MAAA,IAAA,CAAK,UAAU,MAAA,GAAS,CAAA;AACxB,MAAA,IAAA,CAAK,QAAA,GAAW,KAAA;AACwB,IAC1C;AACA,IAAA,IAAI,UAAU,MAAM,UAAA;AAAA,EACtB;AAAA;AAAA,EAGQ,eAAA,CAAgB,QAAqB,MAAA,EAAwB;AACnE,IAAA,KAAA,MAAWA,WAAU,MAAA,EAAQ;AAC3B,MAAA,IAAI,CAACA,OAAAA,CAAO,QAAA,EAAU,MAAA,CAAO,KAAKA,OAAM,CAAA;AAAA,IAC1C;AACA,IAAA,MAAA,CAAO,KAAA,EAAM;AAAA,EACf;AACF,CAAA;AAhHuB,MAAA,CAAA,UAAA,EAAA,WAAA,CAAA;AAmHvB,SAAS,YAAY,OAAA,EAAyB;AAC5C,EAAA,IAAI,OAAA,CAAQ,SAAS,CAAA,EAAG;AACtB,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAA,IAAS,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAA;AAAA,EAC/D;AACF;AAJS,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;;;ACzFT,IAAM,YAAA,GAAe,UAAA;AACrB,IAAM,YAAY,YAAA,CAAa,YAAA,IAAgB,EAAE,OAAA,kBAAS,IAAI,KAA4B,EAAE;AAC5F,YAAA,CAAa,YAAA,GAAe,SAAA;;;AC5B5B,IAAM,cAAA,uBAAqB,OAAA,EAAoD;AAUxE,SAAS,MAAA,CAAU,KAAsB,QAAA,EAA6B;AAC3E,EAAA,MAAM,QAAQ,eAAA,EAAgB;AAC9B,EAAA,MAAM,KAAA,GAAQ,KAAA,GAAQ,eAAA,CAAgB,KAAA,EAAO,GAAG,CAAA,GAAI,MAAA;AACpD,EAAA,OAAO,KAAA,KAAU,SAAY,QAAA,GAAW,KAAA;AAC1C;AAJgB,MAAA,CAAA,MAAA,EAAA,QAAA,CAAA;AAgCT,SAAS,eAAA,CAAmB,OAAc,GAAA,EAAqC;AACpF,EAAA,IAAI,OAAA,GAAwB,KAAA;AAC5B,EAAA,OAAO,OAAA,EAAS;AACd,IAAA,MAAM,SAAA,GAAY,cAAA,CAAe,GAAA,CAAI,OAAO,CAAA;AAC5C,IAAA,IAAI,WAAW,GAAA,CAAI,GAAG,GAAG,OAAO,SAAA,CAAU,IAAI,GAAG,CAAA;AACjD,IAAA,OAAA,GAAU,OAAA,CAAQ,MAAA;AAAA,EACpB;AACA,EAAA,OAAO,MAAA;AACT;AARgB,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA;;;ACQT,SAAS,mBAAsB,WAAA,EAAsC;AAC1E,EAAA,OAAO,OAAO,WAAW,CAAA;AAC3B;AAFgB,MAAA,CAAA,kBAAA,EAAA,oBAAA,CAAA;;;ACGT,IAAM,aAAA,GAAN,MAAM,aAAA,SAAqB,KAAA,CAAM;AAAA,EAKtC,WAAA,CAAY,IAAA,EAAwB,OAAA,EAAiB,GAAA,EAAc,KAAA,EAAiB;AAClF,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAAA,EACf;AACF,CAAA;AAZwC,MAAA,CAAA,aAAA,EAAA,cAAA,CAAA;AAAjC,IAAM,YAAA,GAAN;AAcA,IAAM,WAAA,GAA4C,mBAAmC,cAAc;AAYnG,SAAS,mBAAA,GAAmC;AACjD,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,EAAA,OAAO;AAAA,IACL,IAAI,MAAA,GAAiB;AACnB,MAAA,OAAO,MAAA,CAAO,IAAA;AAAA,IAChB,CAAA;AAAA,IACA,QAAQ,GAAA,EAAoB;AAC1B,MAAA,OAAO,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA;AAAA,IAC5B,CAAA;AAAA,IACA,OAAA,CAAQ,KAAK,KAAA,EAAa;AACxB,MAAA,MAAA,CAAO,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,IACvB,CAAA;AAAA,IACA,WAAW,GAAA,EAAW;AACpB,MAAA,MAAA,CAAO,OAAO,GAAG,CAAA;AAAA,IACnB,CAAA;AAAA,IACA,IAAI,KAAA,EAAsB;AACxB,MAAA,OAAO,CAAC,GAAG,MAAA,CAAO,MAAM,CAAA,CAAE,KAAK,CAAA,IAAK,IAAA;AAAA,IACtC;AAAA,GACF;AACF;AAnBgB,MAAA,CAAA,mBAAA,EAAA,qBAAA,CAAA;AAqBT,IAAM,gBAAgB,mBAAA;AAEtB,SAAS,aAAA,CAAc,OAAA,GAA0B,EAAC,EAAmB;AAC1E,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,OAAA;AACjC,EAAA,MAAM,OAAA,GAAU,eAAA,CAAgB,OAAA,CAAQ,OAAA,IAAW,CAAC,CAAA;AACpD,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,QAAA,IAAY,mBAAA,EAAoB;AACzD,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,OAAA,CAAQ,OAAO,CAAA;AAC/C,EAAA,IAAI,OAAA,GAAU,SAAS,OAAA,IAAW,QAAA;AAClC,EAAA,IAAI,OAAoB,QAAA,CAAS,IAAA;AACjC,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,mBAAA;AACJ,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAqC;AAE3D,EAAA,MAAM,OAAA,GAA0B;AAAA,IAC9B,IAAI,IAAA,GAAoB;AACtB,MAAA,OAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,IAAI,UAAA,GAAsB;AACxB,MAAA,OAAO,IAAA,KAAS,QAAA;AAAA,IAClB,CAAA;AAAA,IAEA,MAAA;AAAA,IACA,OAAA;AAAA,IAEA,IAAO,GAAA,EAAuB;AAC5B,MAAA,YAAA,EAAa;AACb,MAAA,MAAM,aAAA,GAAgB,YAAY,GAAG,CAAA;AACrC,MAAA,MAAM,GAAA,GAAM,KAAK,aAAa,CAAA;AAC9B,MAAA,IAAI,GAAA,KAAQ,MAAM,OAAO,IAAA;AACzB,MAAA,OAAO,MAAA,CAAU,eAAe,GAAG,CAAA;AAAA,IACrC,CAAA;AAAA,IAEA,GAAA,CAAO,KAAa,KAAA,EAAgB;AAClC,MAAA,YAAA,EAAa;AACb,MAAA,MAAM,aAAA,GAAgB,YAAY,GAAG,CAAA;AACrC,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI;AACF,QAAA,GAAA,GAAM,KAAK,SAAA,CAAU,EAAE,eAAe,IAAA,EAAM,OAAA,EAAS,OAA0B,CAAA;AAAA,MACjF,SAAS,KAAA,EAAO;AACd,QAAA,MAAM,eAAe,IAAI,YAAA;AAAA,UACvB,sBAAA;AAAA,UACA,sDAAwB,aAAa,CAAA,CAAA;AAAA,UACrC,aAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,MAAA,CAAO,YAAY,CAAA;AACnB,QAAA,MAAM,YAAA;AAAA,MACR;AACA,MAAA,KAAA,CAAM,eAAe,GAAG,CAAA;AACxB,MAAA,IAAA,CAAK,EAAE,GAAA,EAAK,aAAA,EAAe,KAAA,EAAO,MAAA,EAAQ,SAAS,CAAA;AAAA,IACrD,CAAA;AAAA,IAEA,OAAO,GAAA,EAAmB;AACxB,MAAA,YAAA,EAAa;AACb,MAAA,MAAM,aAAA,GAAgB,YAAY,GAAG,CAAA;AACrC,MAAA,WAAA,CAAY,eAAe,MAAM,OAAA,CAAQ,WAAW,aAAA,CAAc,aAAa,CAAC,CAAC,CAAA;AACjF,MAAA,IAAA,CAAK,EAAE,GAAA,EAAK,aAAA,EAAe,OAAO,IAAA,EAAM,MAAA,EAAQ,SAAS,CAAA;AAAA,IAC3D,CAAA;AAAA,IAEA,KAAA,GAAc;AACZ,MAAA,YAAA,EAAa;AACb,MAAA,MAAM,eAAe,gBAAA,EAAiB;AACtC,MAAA,KAAA,MAAW,eAAe,YAAA,EAAc;AACtC,QAAA,WAAA,CAAY,WAAA,EAAa,MAAM,OAAA,CAAQ,UAAA,CAAW,WAAW,CAAC,CAAA;AAAA,MAChE;AACA,MAAA,KAAA,MAAW,eAAe,YAAA,EAAc;AACtC,QAAA,IAAA,CAAK,EAAE,GAAA,EAAK,WAAA,CAAY,KAAA,CAAM,MAAA,CAAO,MAAM,CAAA,EAAG,KAAA,EAAO,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,CAAA;AAAA,MAC9E;AAAA,IACF,CAAA;AAAA,IAEA,IAAI,GAAA,EAAsB;AACxB,MAAA,OAAO,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,KAAM,IAAA;AAAA,IAC9B,CAAA;AAAA,IAEA,IAAA,GAA0B;AACxB,MAAA,YAAA,EAAa;AACb,MAAA,OAAO,gBAAA,GAAmB,GAAA,CAAI,CAAA,GAAA,KAAO,IAAI,KAAA,CAAM,MAAA,CAAO,MAAM,CAAC,CAAA;AAAA,IAC/D,CAAA;AAAA,IAEA,UAAU,QAAA,EAAsB;AAC9B,MAAA,YAAA,EAAa;AACb,MAAA,SAAA,CAAU,IAAI,QAAQ,CAAA;AACtB,MAAA,OAAO,MAAM,SAAA,CAAU,MAAA,CAAO,QAAQ,CAAA;AAAA,IACxC,CAAA;AAAA,IAEA,OAAA,GAAgB;AACd,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,mBAAA,IAAsB;AACtB,MAAA,mBAAA,GAAsB,MAAA;AACtB,MAAA,SAAA,CAAU,KAAA,EAAM;AAAA,IAClB;AAAA,GACF;AAEA,EAAA,IAAI,QAAA,CAAS,cAAA,IAAkB,OAAO,MAAA,KAAW,WAAA,EAAa;AAC5D,IAAA,MAAM,SAAA,2BAAa,KAAA,KAA8B;AAC/C,MAAA,IAAI,KAAA,CAAM,WAAA,IAAe,KAAA,CAAM,WAAA,KAAgB,OAAA,EAAS;AACxD,MAAA,IAAI,CAAC,MAAM,GAAA,IAAO,CAAC,MAAM,GAAA,CAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AACjD,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,GAAA,CAAI,KAAA,CAAM,OAAO,MAAM,CAAA;AACzC,MAAA,IAAA,CAAK,EAAE,GAAA,EAAK,KAAA,EAAO,KAAA,CAAM,aAAa,IAAA,GAAO,IAAA,GAAO,cAAA,CAAe,GAAA,EAAK,KAAA,CAAM,QAAQ,CAAA,EAAG,MAAA,EAAQ,YAAY,CAAA;AAAA,IAC/G,CAAA,EALkB,WAAA,CAAA;AAMlB,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAC5C,IAAA,mBAAA,mBAAsB,MAAA,CAAA,MAAM,MAAA,CAAO,mBAAA,CAAoB,SAAA,EAAW,SAAS,CAAA,EAArD,qBAAA,CAAA;AAAA,EACxB;AAGA,EAAA,OAAO,OAAA;AAEP,EAAA,SAAS,KAAK,GAAA,EAA4B;AACxC,IAAA,OAAO,WAAA,CAAY,KAAK,MAAM,OAAA,CAAQ,QAAQ,aAAA,CAAc,GAAG,CAAC,CAAC,CAAA;AAAA,EACnE;AAEA,EAAA,SAAS,KAAA,CAAM,KAAa,KAAA,EAAqB;AAC/C,IAAA,WAAA,CAAY,GAAA,EAAK,MAAM,OAAA,CAAQ,OAAA,CAAQ,cAAc,GAAG,CAAA,EAAG,KAAK,CAAC,CAAA;AAAA,EACnE;AAEA,EAAA,SAAS,MAAA,CAAU,KAAa,GAAA,EAAuB;AACrD,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IACzB,SAAS,KAAA,EAAO;AACd,MAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AACxB,MAAA,OAAO,IAAA;AAAA,IACT;AAEA,IAAA,MAAM,QAAA,GAAW,WAAW,MAAM,CAAA,GAAI,SAAS,EAAE,OAAA,EAAS,CAAA,EAAG,KAAA,EAAO,MAAA,EAAO;AAC3E,IAAA,IAAI,SAAS,OAAA,IAAW,OAAA,IAAW,CAAC,OAAA,CAAQ,OAAA,SAAgB,QAAA,CAAS,KAAA;AAErE,IAAA,IAAI;AACF,MAAA,MAAM,WAAW,OAAA,CAAQ,OAAA,CAAQ,SAAS,KAAA,EAAO,QAAA,CAAS,SAAS,OAAO,CAAA;AAC1E,MAAA,KAAA,CAAM,GAAA,EAAK,IAAA,CAAK,SAAA,CAAU,EAAE,aAAA,EAAe,MAAM,OAAA,EAAS,KAAA,EAAO,QAAA,EAA6B,CAAC,CAAA;AAC/F,MAAA,OAAO,QAAA;AAAA,IACT,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,eAAe,IAAI,YAAA;AAAA,QACvB,kBAAA;AAAA,QACA,wBAAmB,GAAG,CAAA,yBAAA,CAAA;AAAA,QACtB,GAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAA,CAAO,YAAY,CAAA;AACnB,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,SAAS,cAAA,CAAe,KAAa,GAAA,EAA6B;AAChE,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAA;AAC7B,MAAA,OAAO,UAAA,CAAW,MAAM,CAAA,GAAI,MAAA,CAAO,KAAA,GAAQ,MAAA;AAAA,IAC7C,SAAS,KAAA,EAAO;AACd,MAAA,aAAA,CAAc,KAAK,KAAK,CAAA;AACxB,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,SAAS,aAAA,CAAc,KAAa,KAAA,EAAsB;AACxD,IAAA,MAAM,eAAe,IAAI,YAAA;AAAA,MACvB,cAAA;AAAA,MACA,wBAAmB,GAAG,CAAA,qCAAA,CAAA;AAAA,MACtB,GAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,MAAA,CAAO,YAAY,CAAA;AACnB,IAAA,WAAA,CAAY,KAAK,MAAM,OAAA,CAAQ,WAAW,aAAA,CAAc,GAAG,CAAC,CAAC,CAAA;AAAA,EAC/D;AAEA,EAAA,SAAS,WAAA,CAAe,KAAa,SAAA,EAAuB;AAC1D,IAAA,IAAI;AACF,MAAA,OAAO,SAAA,EAAU;AAAA,IACnB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,YAAY,QAAA,EAAU;AACxB,QAAA,MAAMC,gBAAe,IAAI,YAAA;AAAA,UACvB,qBAAA;AAAA,UACA,8CAAA;AAAA,UACA,GAAA;AAAA,UACA;AAAA,SACF;AACA,QAAA,MAAA,CAAOA,aAAY,CAAA;AACnB,QAAA,MAAMA,aAAAA;AAAA,MACR;AACA,MAAA,MAAM,eAAe,IAAI,YAAA;AAAA,QACvB,qBAAA;AAAA,QACA,iGAAA;AAAA,QACA,GAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA,MAAA,CAAO,YAAY,CAAA;AACnB,MAAA,OAAA,GAAU,QAAA;AACV,MAAA,IAAA,GAAO,QAAA;AACP,MAAA,OAAO,SAAA,EAAU;AAAA,IACnB;AAAA,EACF;AAEA,EAAA,SAAS,gBAAA,GAA6B;AACpC,IAAA,MAAM,OAAiB,EAAC;AACxB,IAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,OAAA,CAAQ,QAAQ,KAAA,EAAA,EAAS;AACnD,MAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA;AAC7B,MAAA,IAAI,KAAK,UAAA,CAAW,MAAM,CAAA,EAAG,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,IAC5C;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,SAAS,KAAK,MAAA,EAA6B;AACzC,IAAA,KAAA,MAAW,QAAA,IAAY,CAAC,GAAG,SAAS,CAAA,EAAG;AACrC,MAAA,IAAI;AACF,QAAA,QAAA,CAAS,MAAM,CAAA;AAAA,MACjB,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,SAAS,OAAO,KAAA,EAA2B;AACzC,IAAA,IAAI;AACF,MAAA,OAAA,CAAQ,UAAU,KAAK,CAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,SAAS,YAAA,GAAqB;AAC5B,IAAA,IAAI,QAAA,EAAU,MAAM,IAAI,KAAA,CAAM,8FAA6B,CAAA;AAAA,EAC7D;AAEA,EAAA,SAAS,cAAc,GAAA,EAAqB;AAC1C,IAAA,OAAO,CAAA,EAAG,MAAM,CAAA,EAAG,GAAG,CAAA,CAAA;AAAA,EACxB;AACF;AAjOgB,MAAA,CAAA,aAAA,EAAA,eAAA,CAAA;AAmOT,SAAS,aAAA,CAAc,OAAA,GAAgC,EAAC,EAAe;AAC5E,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,eAAA;AAAA,IACN,OAAA,EAAS,OAAA;AAAA,IACT,QAAQ,OAAA,EAAS;AACf,MAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,GAAU,MAAA,GAAY,cAAc,OAAO,CAAA;AACxE,MAAA,OAAA,CAAQ,OAAA,CAAQ,WAAA,EAAa,OAAA,CAAQ,OAAA,IAAW,YAAa,CAAA;AAC7D,MAAA,OAAO,MAAM,cAAc,OAAA,EAAQ;AAAA,IACrC;AAAA,GACF;AACF;AAVgB,MAAA,CAAA,aAAA,EAAA,eAAA,CAAA;AAYT,SAAS,UAAA,GAA6B;AAC3C,EAAA,MAAM,OAAA,GAAU,OAAO,WAAW,CAAA;AAClC,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,YAAA,CAAa,uBAAuB,0FAAwC,CAAA;AACpG,EAAA,OAAO,OAAA;AACT;AAJgB,MAAA,CAAA,UAAA,EAAA,YAAA,CAAA;AAMhB,SAAS,eAAe,KAAA,EAItB;AACA,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,IAAA,EAAM,QAAA,EAAU,cAAA,EAAgB,KAAA,EAAM;AACvG,EAAA,MAAM,OAAO,KAAA,IAAS,OAAA;AACtB,EAAA,IAAI,IAAA,KAAS,UAAU,OAAO,EAAE,SAAS,aAAA,EAAe,IAAA,EAAM,QAAA,EAAU,cAAA,EAAgB,KAAA,EAAM;AAC9F,EAAA,MAAM,OAAA,GAAU,kBAAkB,IAAI,CAAA;AACtC,EAAA,OAAO,EAAE,SAAS,IAAA,EAAM,OAAA,GAAU,OAAO,QAAA,EAAU,cAAA,EAAgB,OAAA,CAAQ,OAAO,CAAA,EAAE;AACtF;AAVS,MAAA,CAAA,cAAA,EAAA,gBAAA,CAAA;AAYT,SAAS,kBAAkB,IAAA,EAA+D;AACxF,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,MAAA;AAC1C,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,KAAS,OAAA,GAAU,MAAA,CAAO,YAAA,GAAe,MAAA,CAAO,cAAA;AAAA,EACzD,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;AAPS,MAAA,CAAA,iBAAA,EAAA,mBAAA,CAAA;AAST,SAAS,WAAW,KAAA,EAAmC;AACrD,EAAA,OAAO,QAAQ,KAAK,CAAA,IACf,OAAO,KAAA,KAAU,YACjB,KAAA,KAAU,IAAA,IACT,KAAA,CAAsC,aAAA,KAAkB,QACzD,MAAA,CAAO,SAAA,CAAW,KAAA,CAAgC,OAAO,KACzD,OAAA,IAAW,KAAA;AAClB;AAPS,MAAA,CAAA,UAAA,EAAA,YAAA,CAAA;AAST,SAAS,YAAY,GAAA,EAAqB;AACxC,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,CAAC,GAAA,CAAI,MAAK,EAAG,MAAM,IAAI,KAAA,CAAM,4CAAwB,CAAA;AACpF,EAAA,OAAO,GAAA;AACT;AAHS,MAAA,CAAA,WAAA,EAAA,aAAA,CAAA;AAKT,SAAS,gBAAgB,OAAA,EAAyB;AAChD,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,CAAU,OAAO,CAAA,IAAK,UAAU,CAAA,EAAG;AAC7C,IAAA,MAAM,IAAI,MAAM,uFAAqC,CAAA;AAAA,EACvD;AACA,EAAA,OAAO,OAAA;AACT;AALS,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA","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 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 } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type StorageType = 'local' | 'session' | 'memory'\nexport type StorageKind = StorageType | 'custom'\n\nexport interface StorageLike {\n readonly length: number\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n key(index: number): string | null\n}\n\nexport type StorageMigration = (\n value: unknown,\n fromVersion: number,\n toVersion: number\n) => unknown\n\nexport interface StorageOptions {\n readonly storage?: StorageLike | StorageType\n readonly fallback?: StorageLike\n readonly prefix?: string\n readonly version?: number\n readonly migrate?: StorageMigration\n readonly onError?: (error: StorageError) => void\n}\n\nexport interface StorageChange {\n readonly key: string\n readonly value: unknown | null\n readonly source: 'local' | 'external'\n}\n\nexport interface StorageContext {\n readonly kind: StorageKind\n readonly persistent: boolean\n readonly prefix: string\n readonly version: number\n get<T>(key: string): T | null\n set<T>(key: string, value: T): void\n remove(key: string): void\n clear(): void\n has(key: string): boolean\n keys(): readonly string[]\n subscribe(listener: (change: StorageChange) => void): () => void\n dispose(): void\n}\n\nexport type StorageErrorCode =\n | 'STORAGE_UNAVAILABLE'\n | 'CORRUPT_DATA'\n | 'SERIALIZATION_FAILED'\n | 'MIGRATION_FAILED'\n\nexport class StorageError extends Error {\n readonly code: StorageErrorCode\n readonly key: string | undefined\n readonly cause: unknown\n\n constructor(code: StorageErrorCode, message: string, key?: string, cause?: unknown) {\n super(message)\n this.name = 'StorageError'\n this.code = code\n this.key = key\n this.cause = cause\n }\n}\n\nexport const STORAGE_KEY: InjectionKey<StorageContext> = createInjectionKey<StorageContext>('vobs.storage')\n\nexport interface StoragePluginOptions extends StorageOptions {\n readonly context?: StorageContext\n}\n\ninterface Envelope {\n readonly __vobsStorage: true\n readonly version: number\n readonly value: unknown\n}\n\nexport function createMemoryStorage(): StorageLike {\n const values = new Map<string, string>()\n return {\n get length(): number {\n return values.size\n },\n getItem(key): string | null {\n return values.get(key) ?? null\n },\n setItem(key, value): void {\n values.set(key, value)\n },\n removeItem(key): void {\n values.delete(key)\n },\n key(index): string | null {\n return [...values.keys()][index] ?? null\n }\n }\n}\n\nexport const memoryStorage = createMemoryStorage()\n\nexport function createStorage(options: StorageOptions = {}): StorageContext {\n const prefix = options.prefix ?? 'vobs:'\n const version = validateVersion(options.version ?? 1)\n const fallback = options.fallback ?? createMemoryStorage()\n const selected = resolveStorage(options.storage)\n let backend = selected.backend ?? fallback\n let kind: StorageKind = selected.kind\n let disposed = false\n let stopBrowserListener: (() => void) | undefined\n const listeners = new Set<(change: StorageChange) => void>()\n\n const context: StorageContext = {\n get kind(): StorageKind {\n return kind\n },\n\n get persistent(): boolean {\n return kind !== 'memory'\n },\n\n prefix,\n version,\n\n get<T>(key: string): T | null {\n ensureActive()\n const normalizedKey = validateKey(key)\n const raw = read(normalizedKey)\n if (raw === null) return null\n return decode<T>(normalizedKey, raw)\n },\n\n set<T>(key: string, value: T): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n let raw: string\n try {\n raw = JSON.stringify({ __vobsStorage: true, version, value } satisfies Envelope)\n } catch (error) {\n const storageError = new StorageError(\n 'SERIALIZATION_FAILED',\n `Vobs Storage: 无法序列化键 ${normalizedKey}`,\n normalizedKey,\n error\n )\n report(storageError)\n throw storageError\n }\n write(normalizedKey, raw)\n emit({ key: normalizedKey, value, source: 'local' })\n },\n\n remove(key: string): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n withBackend(normalizedKey, () => backend.removeItem(toPhysicalKey(normalizedKey)))\n emit({ key: normalizedKey, value: null, source: 'local' })\n },\n\n clear(): void {\n ensureActive()\n const physicalKeys = listPhysicalKeys()\n for (const physicalKey of physicalKeys) {\n withBackend(physicalKey, () => backend.removeItem(physicalKey))\n }\n for (const physicalKey of physicalKeys) {\n emit({ key: physicalKey.slice(prefix.length), value: null, source: 'local' })\n }\n },\n\n has(key: string): boolean {\n return context.get(key) !== null\n },\n\n keys(): readonly string[] {\n ensureActive()\n return listPhysicalKeys().map(key => key.slice(prefix.length))\n },\n\n subscribe(listener): () => void {\n ensureActive()\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n stopBrowserListener?.()\n stopBrowserListener = undefined\n listeners.clear()\n }\n }\n\n if (selected.browserStorage && typeof window !== 'undefined') {\n const onStorage = (event: StorageEvent): void => {\n if (event.storageArea && event.storageArea !== backend) return\n if (!event.key || !event.key.startsWith(prefix)) return\n const key = event.key.slice(prefix.length)\n emit({ key, value: event.newValue === null ? null : decodeExternal(key, event.newValue), source: 'external' })\n }\n window.addEventListener('storage', onStorage)\n stopBrowserListener = () => window.removeEventListener('storage', onStorage)\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function read(key: string): string | null {\n return withBackend(key, () => backend.getItem(toPhysicalKey(key)))\n }\n\n function write(key: string, value: string): void {\n withBackend(key, () => backend.setItem(toPhysicalKey(key), value))\n }\n\n function decode<T>(key: string, raw: string): T | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n\n const envelope = isEnvelope(parsed) ? parsed : { version: 0, value: parsed }\n if (envelope.version >= version || !options.migrate) return envelope.value as T | null\n\n try {\n const migrated = options.migrate(envelope.value, envelope.version, version)\n write(key, JSON.stringify({ __vobsStorage: true, version, value: migrated } satisfies Envelope))\n return migrated as T | null\n } catch (error) {\n const storageError = new StorageError(\n 'MIGRATION_FAILED',\n `Vobs Storage: 键 ${key} 迁移失败`,\n key,\n error\n )\n report(storageError)\n return null\n }\n }\n\n function decodeExternal(key: string, raw: string): unknown | null {\n try {\n const parsed = JSON.parse(raw)\n return isEnvelope(parsed) ? parsed.value : parsed\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n }\n\n function handleCorrupt(key: string, cause: unknown): void {\n const storageError = new StorageError(\n 'CORRUPT_DATA',\n `Vobs Storage: 键 ${key} 的数据已损坏`,\n key,\n cause\n )\n report(storageError)\n withBackend(key, () => backend.removeItem(toPhysicalKey(key)))\n }\n\n function withBackend<T>(key: string, operation: () => T): T {\n try {\n return operation()\n } catch (error) {\n if (backend === fallback) {\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用',\n key,\n error\n )\n report(storageError)\n throw storageError\n }\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用,已切换到内存 fallback',\n key,\n error\n )\n report(storageError)\n backend = fallback\n kind = 'memory'\n return operation()\n }\n }\n\n function listPhysicalKeys(): string[] {\n const keys: string[] = []\n for (let index = 0; index < backend.length; index++) {\n const key = backend.key(index)\n if (key?.startsWith(prefix)) keys.push(key)\n }\n return keys\n }\n\n function emit(change: StorageChange): void {\n for (const listener of [...listeners]) {\n try {\n listener(change)\n } catch {\n // 订阅者错误不能阻止其他订阅者接收变化。\n }\n }\n }\n\n function report(error: StorageError): void {\n try {\n options.onError?.(error)\n } catch {\n // 错误回调不能覆盖存储操作的原始结果。\n }\n }\n\n function ensureActive(): void {\n if (disposed) throw new Error('Vobs Storage: 已销毁的上下文不能继续使用')\n }\n\n function toPhysicalKey(key: string): string {\n return `${prefix}${key}`\n }\n}\n\nexport function storagePlugin(options: StoragePluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/storage',\n version: '0.1.0',\n install(context) {\n const ownedStorage = options.context ? undefined : createStorage(options)\n context.provide(STORAGE_KEY, options.context ?? ownedStorage!)\n return () => ownedStorage?.dispose()\n }\n }\n}\n\nexport function useStorage(): StorageContext {\n const storage = inject(STORAGE_KEY)\n if (!storage) throw new StorageError('STORAGE_UNAVAILABLE', 'Vobs Storage: 找不到上下文,请安装 storagePlugin')\n return storage\n}\n\nfunction resolveStorage(input: StorageLike | StorageType | undefined): {\n backend: StorageLike | undefined\n kind: StorageKind\n browserStorage: boolean\n} {\n if (input && typeof input !== 'string') return { backend: input, kind: 'custom', browserStorage: false }\n const type = input ?? 'local'\n if (type === 'memory') return { backend: memoryStorage, kind: 'memory', browserStorage: false }\n const backend = getBrowserStorage(type)\n return { backend, kind: backend ? type : 'memory', browserStorage: Boolean(backend) }\n}\n\nfunction getBrowserStorage(type: Exclude<StorageType, 'memory'>): StorageLike | undefined {\n if (typeof window === 'undefined') return undefined\n try {\n return type === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return undefined\n }\n}\n\nfunction isEnvelope(value: unknown): value is Envelope {\n return Boolean(value)\n && typeof value === 'object'\n && value !== null\n && (value as { __vobsStorage?: unknown }).__vobsStorage === true\n && Number.isInteger((value as { version?: unknown }).version)\n && 'value' in value\n}\n\nfunction validateKey(key: string): string {\n if (typeof key !== 'string' || !key.trim()) throw new Error('Vobs Storage: key 不能为空')\n return key\n}\n\nfunction validateVersion(version: number): number {\n if (!Number.isInteger(version) || version < 0) {\n throw new Error('Vobs Storage: version 必须是大于等于 0 的整数')\n }\n return version\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { getCurrentOwner, onDispose } from '@vobs/reactivity'\nimport { createInjectionKey, inject, type InjectionKey, type VobsPlugin } from '@vobs/vobs'\n\nexport type StorageType = 'local' | 'session' | 'memory'\nexport type StorageKind = StorageType | 'custom'\n\nexport interface StorageLike {\n readonly length: number\n getItem(key: string): string | null\n setItem(key: string, value: string): void\n removeItem(key: string): void\n key(index: number): string | null\n}\n\nexport type StorageMigration = (\n value: unknown,\n fromVersion: number,\n toVersion: number\n) => unknown\n\nexport interface StorageOptions {\n readonly storage?: StorageLike | StorageType\n readonly fallback?: StorageLike\n readonly prefix?: string\n readonly version?: number\n readonly migrate?: StorageMigration\n readonly onError?: (error: StorageError) => void\n}\n\nexport interface StorageChange {\n readonly key: string\n readonly value: unknown | null\n readonly source: 'local' | 'external'\n}\n\nexport interface StorageContext {\n readonly kind: StorageKind\n readonly persistent: boolean\n readonly prefix: string\n readonly version: number\n get<T>(key: string): T | null\n set<T>(key: string, value: T): void\n remove(key: string): void\n clear(): void\n has(key: string): boolean\n keys(): readonly string[]\n subscribe(listener: (change: StorageChange) => void): () => void\n dispose(): void\n}\n\nexport type StorageErrorCode =\n | 'STORAGE_UNAVAILABLE'\n | 'CORRUPT_DATA'\n | 'SERIALIZATION_FAILED'\n | 'MIGRATION_FAILED'\n\nexport class StorageError extends Error {\n readonly code: StorageErrorCode\n readonly key: string | undefined\n readonly cause: unknown\n\n constructor(code: StorageErrorCode, message: string, key?: string, cause?: unknown) {\n super(message)\n this.name = 'StorageError'\n this.code = code\n this.key = key\n this.cause = cause\n }\n}\n\nexport const STORAGE_KEY: InjectionKey<StorageContext> = createInjectionKey<StorageContext>('vobs.storage')\n\nexport interface StoragePluginOptions extends StorageOptions {\n readonly context?: StorageContext\n}\n\ninterface Envelope {\n readonly __vobsStorage: true\n readonly version: number\n readonly value: unknown\n}\n\nexport function createMemoryStorage(): StorageLike {\n const values = new Map<string, string>()\n return {\n get length(): number {\n return values.size\n },\n getItem(key): string | null {\n return values.get(key) ?? null\n },\n setItem(key, value): void {\n values.set(key, value)\n },\n removeItem(key): void {\n values.delete(key)\n },\n key(index): string | null {\n return [...values.keys()][index] ?? null\n }\n }\n}\n\nexport const memoryStorage = createMemoryStorage()\n\nexport function createStorage(options: StorageOptions = {}): StorageContext {\n const prefix = options.prefix ?? 'vobs:'\n const version = validateVersion(options.version ?? 1)\n const fallback = options.fallback ?? createMemoryStorage()\n const selected = resolveStorage(options.storage)\n let backend = selected.backend ?? fallback\n let kind: StorageKind = selected.kind\n let disposed = false\n let stopBrowserListener: (() => void) | undefined\n const listeners = new Set<(change: StorageChange) => void>()\n\n const context: StorageContext = {\n get kind(): StorageKind {\n return kind\n },\n\n get persistent(): boolean {\n return kind !== 'memory'\n },\n\n prefix,\n version,\n\n get<T>(key: string): T | null {\n ensureActive()\n const normalizedKey = validateKey(key)\n const raw = read(normalizedKey)\n if (raw === null) return null\n return decode<T>(normalizedKey, raw)\n },\n\n set<T>(key: string, value: T): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n let raw: string\n try {\n raw = JSON.stringify({ __vobsStorage: true, version, value } satisfies Envelope)\n } catch (error) {\n const storageError = new StorageError(\n 'SERIALIZATION_FAILED',\n `Vobs Storage: 无法序列化键 ${normalizedKey}`,\n normalizedKey,\n error\n )\n report(storageError)\n throw storageError\n }\n write(normalizedKey, raw)\n emit({ key: normalizedKey, value, source: 'local' })\n },\n\n remove(key: string): void {\n ensureActive()\n const normalizedKey = validateKey(key)\n withBackend(normalizedKey, () => backend.removeItem(toPhysicalKey(normalizedKey)))\n emit({ key: normalizedKey, value: null, source: 'local' })\n },\n\n clear(): void {\n ensureActive()\n const physicalKeys = listPhysicalKeys()\n for (const physicalKey of physicalKeys) {\n withBackend(physicalKey, () => backend.removeItem(physicalKey))\n }\n for (const physicalKey of physicalKeys) {\n emit({ key: physicalKey.slice(prefix.length), value: null, source: 'local' })\n }\n },\n\n has(key: string): boolean {\n return context.get(key) !== null\n },\n\n keys(): readonly string[] {\n ensureActive()\n return listPhysicalKeys().map(key => key.slice(prefix.length))\n },\n\n subscribe(listener): () => void {\n ensureActive()\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n\n dispose(): void {\n if (disposed) return\n disposed = true\n stopBrowserListener?.()\n stopBrowserListener = undefined\n listeners.clear()\n }\n }\n\n if (selected.browserStorage && typeof window !== 'undefined') {\n const onStorage = (event: StorageEvent): void => {\n if (event.storageArea && event.storageArea !== backend) return\n if (!event.key || !event.key.startsWith(prefix)) return\n const key = event.key.slice(prefix.length)\n emit({ key, value: event.newValue === null ? null : decodeExternal(key, event.newValue), source: 'external' })\n }\n window.addEventListener('storage', onStorage)\n stopBrowserListener = () => window.removeEventListener('storage', onStorage)\n }\n\n if (getCurrentOwner()) onDispose(context.dispose)\n return context\n\n function read(key: string): string | null {\n return withBackend(key, () => backend.getItem(toPhysicalKey(key)))\n }\n\n function write(key: string, value: string): void {\n withBackend(key, () => backend.setItem(toPhysicalKey(key), value))\n }\n\n function decode<T>(key: string, raw: string): T | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n\n const envelope = isEnvelope(parsed) ? parsed : { version: 0, value: parsed }\n if (envelope.version >= version || !options.migrate) return envelope.value as T | null\n\n try {\n const migrated = options.migrate(envelope.value, envelope.version, version)\n write(key, JSON.stringify({ __vobsStorage: true, version, value: migrated } satisfies Envelope))\n return migrated as T | null\n } catch (error) {\n const storageError = new StorageError(\n 'MIGRATION_FAILED',\n `Vobs Storage: 键 ${key} 迁移失败`,\n key,\n error\n )\n report(storageError)\n return null\n }\n }\n\n function decodeExternal(key: string, raw: string): unknown | null {\n try {\n const parsed = JSON.parse(raw)\n return isEnvelope(parsed) ? parsed.value : parsed\n } catch (error) {\n handleCorrupt(key, error)\n return null\n }\n }\n\n function handleCorrupt(key: string, cause: unknown): void {\n const storageError = new StorageError(\n 'CORRUPT_DATA',\n `Vobs Storage: 键 ${key} 的数据已损坏`,\n key,\n cause\n )\n report(storageError)\n withBackend(key, () => backend.removeItem(toPhysicalKey(key)))\n }\n\n function withBackend<T>(key: string, operation: () => T): T {\n try {\n return operation()\n } catch (error) {\n if (backend === fallback) {\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用',\n key,\n error\n )\n report(storageError)\n throw storageError\n }\n const storageError = new StorageError(\n 'STORAGE_UNAVAILABLE',\n 'Vobs Storage: 存储不可用,已切换到内存 fallback',\n key,\n error\n )\n report(storageError)\n backend = fallback\n kind = 'memory'\n return operation()\n }\n }\n\n function listPhysicalKeys(): string[] {\n const keys: string[] = []\n for (let index = 0; index < backend.length; index++) {\n const key = backend.key(index)\n if (key?.startsWith(prefix)) keys.push(key)\n }\n return keys\n }\n\n function emit(change: StorageChange): void {\n for (const listener of [...listeners]) {\n try {\n listener(change)\n } catch {\n // 订阅者错误不能阻止其他订阅者接收变化。\n }\n }\n }\n\n function report(error: StorageError): void {\n try {\n options.onError?.(error)\n } catch {\n // 错误回调不能覆盖存储操作的原始结果。\n }\n }\n\n function ensureActive(): void {\n if (disposed) throw new Error('Vobs Storage: 已销毁的上下文不能继续使用')\n }\n\n function toPhysicalKey(key: string): string {\n return `${prefix}${key}`\n }\n}\n\nexport function storagePlugin(options: StoragePluginOptions = {}): VobsPlugin {\n return {\n name: '@vobs/storage',\n version: '0.1.0',\n install(context) {\n const ownedStorage = options.context ? undefined : createStorage(options)\n context.provide(STORAGE_KEY, options.context ?? ownedStorage!)\n return () => ownedStorage?.dispose()\n }\n }\n}\n\nexport function useStorage(): StorageContext {\n const storage = inject(STORAGE_KEY)\n if (!storage) throw new StorageError('STORAGE_UNAVAILABLE', 'Vobs Storage: 找不到上下文,请安装 storagePlugin')\n return storage\n}\n\nfunction resolveStorage(input: StorageLike | StorageType | undefined): {\n backend: StorageLike | undefined\n kind: StorageKind\n browserStorage: boolean\n} {\n if (input && typeof input !== 'string') return { backend: input, kind: 'custom', browserStorage: false }\n const type = input ?? 'local'\n if (type === 'memory') return { backend: memoryStorage, kind: 'memory', browserStorage: false }\n const backend = getBrowserStorage(type)\n return { backend, kind: backend ? type : 'memory', browserStorage: Boolean(backend) }\n}\n\nfunction getBrowserStorage(type: Exclude<StorageType, 'memory'>): StorageLike | undefined {\n if (typeof window === 'undefined') return undefined\n try {\n return type === 'local' ? window.localStorage : window.sessionStorage\n } catch {\n return undefined\n }\n}\n\nfunction isEnvelope(value: unknown): value is Envelope {\n return Boolean(value)\n && typeof value === 'object'\n && value !== null\n && (value as { __vobsStorage?: unknown }).__vobsStorage === true\n && Number.isInteger((value as { version?: unknown }).version)\n && 'value' in value\n}\n\nfunction validateKey(key: string): string {\n if (typeof key !== 'string' || !key.trim()) throw new Error('Vobs Storage: key 不能为空')\n return key\n}\n\nfunction validateVersion(version: number): number {\n if (!Number.isInteger(version) || version < 0) {\n throw new Error('Vobs Storage: version 必须是大于等于 0 的整数')\n }\n return version\n}\n"],"mappings":"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","names":["storageError"]}
|
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
|
},
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"./source/*": "./src/*"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@vobs/reactivity": "1.2.
|
|
37
|
-
"@vobs/vobs": "1.2.
|
|
36
|
+
"@vobs/reactivity": "1.2.2",
|
|
37
|
+
"@vobs/vobs": "1.2.2"
|
|
38
38
|
}
|
|
39
39
|
}
|