@vobs/resource 1.1.0 → 1.2.1
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/boundary.cjs +708 -0
- package/dist/boundary.cjs.map +1 -0
- package/dist/boundary.d.cts +25 -0
- package/dist/boundary.d.ts +25 -0
- package/dist/boundary.js +705 -0
- package/dist/boundary.js.map +1 -0
- package/dist/index.cjs +1239 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1229 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.cjs +885 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +23 -0
- package/dist/plugin.d.ts +23 -0
- package/dist/plugin.js +881 -0
- package/dist/plugin.js.map +1 -0
- package/dist/resource.cjs +832 -0
- package/dist/resource.cjs.map +1 -0
- package/dist/resource.d.cts +67 -0
- package/dist/resource.d.ts +67 -0
- package/dist/resource.js +827 -0
- package/dist/resource.js.map +1 -0
- package/package.json +27 -8
package/dist/index.js
ADDED
|
@@ -0,0 +1,1229 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
|
|
4
|
+
// packages/reactivity/src/debug.ts
|
|
5
|
+
var activeDebugHooks = null;
|
|
6
|
+
var signalNames = /* @__PURE__ */ new WeakMap();
|
|
7
|
+
function hasDebugHooks() {
|
|
8
|
+
return activeDebugHooks !== null;
|
|
9
|
+
}
|
|
10
|
+
__name(hasDebugHooks, "hasDebugHooks");
|
|
11
|
+
function setSignalDebugName(signal, name) {
|
|
12
|
+
signalNames.set(signal, name);
|
|
13
|
+
invokeDebug("signalNamed", signal, name);
|
|
14
|
+
}
|
|
15
|
+
__name(setSignalDebugName, "setSignalDebugName");
|
|
16
|
+
function invokeDebug(name, ...args) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
__name(invokeDebug, "invokeDebug");
|
|
20
|
+
|
|
21
|
+
// packages/reactivity/src/owner.ts
|
|
22
|
+
var currentOwner = null;
|
|
23
|
+
var nextOwnerId = 1;
|
|
24
|
+
var ownerNames = /* @__PURE__ */ new WeakMap();
|
|
25
|
+
function createOwner() {
|
|
26
|
+
const parent = currentOwner;
|
|
27
|
+
let disposed = parent?.disposed ?? false;
|
|
28
|
+
const children = [];
|
|
29
|
+
const cleanups = [];
|
|
30
|
+
const errorHandlers = /* @__PURE__ */ new Set();
|
|
31
|
+
const owner = {
|
|
32
|
+
id: `owner-${nextOwnerId++}`,
|
|
33
|
+
parent,
|
|
34
|
+
children,
|
|
35
|
+
depth: (parent?.depth ?? -1) + 1,
|
|
36
|
+
get disposed() {
|
|
37
|
+
return disposed;
|
|
38
|
+
},
|
|
39
|
+
run(fn) {
|
|
40
|
+
if (disposed) throw new Error("Vobs: \u5DF2\u9500\u6BC1\u7684 Owner \u4E0D\u80FD\u7EE7\u7EED\u8FD0\u884C");
|
|
41
|
+
const previous = currentOwner;
|
|
42
|
+
currentOwner = owner;
|
|
43
|
+
try {
|
|
44
|
+
return fn();
|
|
45
|
+
} finally {
|
|
46
|
+
currentOwner = previous;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
addCleanup(cleanup) {
|
|
50
|
+
if (disposed) {
|
|
51
|
+
cleanup();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
cleanups.push(cleanup);
|
|
55
|
+
},
|
|
56
|
+
onDispose(cleanup) {
|
|
57
|
+
owner.addCleanup(cleanup);
|
|
58
|
+
},
|
|
59
|
+
onError(handler) {
|
|
60
|
+
errorHandlers.add(handler);
|
|
61
|
+
const remove = /* @__PURE__ */ __name(() => errorHandlers.delete(handler), "remove");
|
|
62
|
+
owner.addCleanup(remove);
|
|
63
|
+
return remove;
|
|
64
|
+
},
|
|
65
|
+
handleError(error) {
|
|
66
|
+
for (const handler of [...errorHandlers].reverse()) {
|
|
67
|
+
try {
|
|
68
|
+
handler(error);
|
|
69
|
+
return true;
|
|
70
|
+
} catch (handlerError) {
|
|
71
|
+
return parent?.handleError(handlerError) ?? false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return parent?.handleError(error) ?? false;
|
|
75
|
+
},
|
|
76
|
+
dispose() {
|
|
77
|
+
if (disposed) return;
|
|
78
|
+
disposed = true;
|
|
79
|
+
for (const child of [...children]) child.dispose();
|
|
80
|
+
children.length = 0;
|
|
81
|
+
let firstError;
|
|
82
|
+
for (let index = cleanups.length - 1; index >= 0; index--) {
|
|
83
|
+
try {
|
|
84
|
+
cleanups[index]();
|
|
85
|
+
} catch (error) {
|
|
86
|
+
firstError ?? (firstError = error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
cleanups.length = 0;
|
|
90
|
+
if (parent) {
|
|
91
|
+
const index = parent.children.indexOf(owner);
|
|
92
|
+
if (index >= 0) parent.children.splice(index, 1);
|
|
93
|
+
}
|
|
94
|
+
if (firstError) throw firstError;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
if (parent && !parent.disposed) parent.children.push(owner);
|
|
98
|
+
return owner;
|
|
99
|
+
}
|
|
100
|
+
__name(createOwner, "createOwner");
|
|
101
|
+
function setOwnerDebugName(owner, name) {
|
|
102
|
+
ownerNames.set(owner, name);
|
|
103
|
+
}
|
|
104
|
+
__name(setOwnerDebugName, "setOwnerDebugName");
|
|
105
|
+
function getCurrentOwner() {
|
|
106
|
+
return currentOwner;
|
|
107
|
+
}
|
|
108
|
+
__name(getCurrentOwner, "getCurrentOwner");
|
|
109
|
+
|
|
110
|
+
// packages/reactivity/src/signal.ts
|
|
111
|
+
var currentSubscriber = null;
|
|
112
|
+
function getCurrentSubscriber() {
|
|
113
|
+
return currentSubscriber;
|
|
114
|
+
}
|
|
115
|
+
__name(getCurrentSubscriber, "getCurrentSubscriber");
|
|
116
|
+
function setCurrentSubscriber(subscriber) {
|
|
117
|
+
currentSubscriber = subscriber;
|
|
118
|
+
}
|
|
119
|
+
__name(setCurrentSubscriber, "setCurrentSubscriber");
|
|
120
|
+
function trackDependency(dependency) {
|
|
121
|
+
if (!currentSubscriber || currentSubscriber.disposed) return;
|
|
122
|
+
!currentSubscriber.dependencies.has(dependency);
|
|
123
|
+
currentSubscriber.dependencies.add(dependency);
|
|
124
|
+
}
|
|
125
|
+
__name(trackDependency, "trackDependency");
|
|
126
|
+
function state(initialValue, debugName) {
|
|
127
|
+
let value = initialValue;
|
|
128
|
+
let disposed = false;
|
|
129
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
130
|
+
const signalInstance = {
|
|
131
|
+
get value() {
|
|
132
|
+
const subscriber = getCurrentSubscriber();
|
|
133
|
+
if (subscriber && !subscriber.disposed) {
|
|
134
|
+
subscribers.add(subscriber);
|
|
135
|
+
trackDependency(signalInstance);
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
},
|
|
139
|
+
set value(nextValue) {
|
|
140
|
+
if (disposed || Object.is(value, nextValue)) return;
|
|
141
|
+
value = nextValue;
|
|
142
|
+
for (const subscriber of [...subscribers]) subscriber.notify();
|
|
143
|
+
},
|
|
144
|
+
unsubscribe(subscriber) {
|
|
145
|
+
subscribers.delete(subscriber);
|
|
146
|
+
},
|
|
147
|
+
// 与 `.value =` 赋值同一条路径:判等短路、debug hook、notify 全部一致。
|
|
148
|
+
// 以闭包实现,可安全地作为回调直接传递(无 this 绑定问题)。
|
|
149
|
+
set(next) {
|
|
150
|
+
signalInstance.value = next;
|
|
151
|
+
},
|
|
152
|
+
dispose() {
|
|
153
|
+
if (disposed) return;
|
|
154
|
+
disposed = true;
|
|
155
|
+
subscribers.clear();
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
const owner = getCurrentOwner();
|
|
159
|
+
owner?.addCleanup(signalInstance.dispose);
|
|
160
|
+
if (debugName?.trim()) setSignalDebugName(signalInstance, debugName.trim());
|
|
161
|
+
return signalInstance;
|
|
162
|
+
}
|
|
163
|
+
__name(state, "state");
|
|
164
|
+
|
|
165
|
+
// packages/reactivity/src/scheduler.ts
|
|
166
|
+
var _Scheduler = class _Scheduler {
|
|
167
|
+
constructor() {
|
|
168
|
+
this.dirtyEffects = /* @__PURE__ */ new Set();
|
|
169
|
+
this.lowPriorityEffects = /* @__PURE__ */ new Set();
|
|
170
|
+
// flush 不可重入(flushing 标志保证),缓冲数组可在轮次间安全复用,避免每轮分配。
|
|
171
|
+
this.normalBuffer = [];
|
|
172
|
+
this.lowBuffer = [];
|
|
173
|
+
this.flushing = false;
|
|
174
|
+
this.scheduled = false;
|
|
175
|
+
this.batchDepth = 0;
|
|
176
|
+
}
|
|
177
|
+
schedule(effect2) {
|
|
178
|
+
if (effect2.disposed) return;
|
|
179
|
+
this.dirtyEffects.add(effect2);
|
|
180
|
+
this.lowPriorityEffects.delete(effect2);
|
|
181
|
+
this.ensureScheduled();
|
|
182
|
+
}
|
|
183
|
+
/** Queue an effect behind normal updates while preserving deterministic order. */
|
|
184
|
+
scheduleLow(effect2) {
|
|
185
|
+
if (effect2.disposed) return;
|
|
186
|
+
if (!this.dirtyEffects.has(effect2)) this.lowPriorityEffects.add(effect2);
|
|
187
|
+
this.ensureScheduled();
|
|
188
|
+
}
|
|
189
|
+
ensureScheduled() {
|
|
190
|
+
if (this.batchDepth === 0 && !this.flushing && !this.scheduled) {
|
|
191
|
+
this.scheduled = true;
|
|
192
|
+
queueMicrotask(() => {
|
|
193
|
+
this.scheduled = false;
|
|
194
|
+
this.flush();
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
remove(effect2) {
|
|
199
|
+
this.dirtyEffects.delete(effect2);
|
|
200
|
+
this.lowPriorityEffects.delete(effect2);
|
|
201
|
+
}
|
|
202
|
+
batch(fn) {
|
|
203
|
+
this.batchDepth++;
|
|
204
|
+
try {
|
|
205
|
+
return fn();
|
|
206
|
+
} finally {
|
|
207
|
+
this.batchDepth--;
|
|
208
|
+
if (this.batchDepth === 0) this.flush();
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
flush() {
|
|
212
|
+
if (this.flushing || this.batchDepth > 0) return;
|
|
213
|
+
this.flushing = true;
|
|
214
|
+
let rounds = 0;
|
|
215
|
+
let firstError;
|
|
216
|
+
let hasError = false;
|
|
217
|
+
try {
|
|
218
|
+
while (this.dirtyEffects.size > 0 || this.lowPriorityEffects.size > 0) {
|
|
219
|
+
if (++rounds > 100) {
|
|
220
|
+
this.dirtyEffects.clear();
|
|
221
|
+
this.lowPriorityEffects.clear();
|
|
222
|
+
throw new Error("Vobs: \u54CD\u5E94\u5F0F\u66F4\u65B0\u8D85\u8FC7 100 \u8F6E\uFF0C\u53EF\u80FD\u5B58\u5728\u5FAA\u73AF\u4F9D\u8D56");
|
|
223
|
+
}
|
|
224
|
+
this.collectRunnable(this.dirtyEffects, this.normalBuffer);
|
|
225
|
+
this.collectRunnable(this.lowPriorityEffects, this.lowBuffer);
|
|
226
|
+
sortEffects(this.normalBuffer);
|
|
227
|
+
sortEffects(this.lowBuffer);
|
|
228
|
+
for (const effect2 of this.normalBuffer) {
|
|
229
|
+
try {
|
|
230
|
+
effect2.run();
|
|
231
|
+
} catch (error) {
|
|
232
|
+
if (!hasError) {
|
|
233
|
+
firstError = error;
|
|
234
|
+
hasError = true;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
for (const effect2 of this.lowBuffer) {
|
|
239
|
+
try {
|
|
240
|
+
effect2.run();
|
|
241
|
+
} catch (error) {
|
|
242
|
+
if (!hasError) {
|
|
243
|
+
firstError = error;
|
|
244
|
+
hasError = true;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this.normalBuffer.length = 0;
|
|
249
|
+
this.lowBuffer.length = 0;
|
|
250
|
+
}
|
|
251
|
+
} finally {
|
|
252
|
+
this.normalBuffer.length = 0;
|
|
253
|
+
this.lowBuffer.length = 0;
|
|
254
|
+
this.flushing = false;
|
|
255
|
+
}
|
|
256
|
+
if (hasError) throw firstError;
|
|
257
|
+
}
|
|
258
|
+
/** 收集未 disposed 的 effect 并清空源集合;run() 期间新调度的 effect 留给下一轮。 */
|
|
259
|
+
collectRunnable(source, target) {
|
|
260
|
+
for (const effect2 of source) {
|
|
261
|
+
if (!effect2.disposed) target.push(effect2);
|
|
262
|
+
}
|
|
263
|
+
source.clear();
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
__name(_Scheduler, "Scheduler");
|
|
267
|
+
var Scheduler = _Scheduler;
|
|
268
|
+
function sortEffects(effects) {
|
|
269
|
+
if (effects.length > 1) {
|
|
270
|
+
effects.sort((a, b) => b.depth - a.depth || a.order - b.order);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
__name(sortEffects, "sortEffects");
|
|
274
|
+
var scheduler = new Scheduler();
|
|
275
|
+
|
|
276
|
+
// packages/reactivity/src/effect.ts
|
|
277
|
+
var nextEffectOrder = 1;
|
|
278
|
+
function cleanupDependencies(subscriber) {
|
|
279
|
+
for (const dependency of subscriber.dependencies) {
|
|
280
|
+
dependency.unsubscribe(subscriber);
|
|
281
|
+
}
|
|
282
|
+
subscriber.dependencies.clear();
|
|
283
|
+
}
|
|
284
|
+
__name(cleanupDependencies, "cleanupDependencies");
|
|
285
|
+
function effect(callback) {
|
|
286
|
+
const owner = getCurrentOwner();
|
|
287
|
+
let cleanup;
|
|
288
|
+
let dirty = true;
|
|
289
|
+
let disposed = false;
|
|
290
|
+
const eff = {
|
|
291
|
+
order: nextEffectOrder++,
|
|
292
|
+
depth: owner?.depth ?? 0,
|
|
293
|
+
dependencies: /* @__PURE__ */ new Set(),
|
|
294
|
+
get disposed() {
|
|
295
|
+
return disposed;
|
|
296
|
+
},
|
|
297
|
+
notify() {
|
|
298
|
+
if (disposed || dirty) return;
|
|
299
|
+
dirty = true;
|
|
300
|
+
scheduler.schedule(eff);
|
|
301
|
+
},
|
|
302
|
+
run() {
|
|
303
|
+
if (disposed || !dirty) return;
|
|
304
|
+
dirty = false;
|
|
305
|
+
const previousCleanup = cleanup;
|
|
306
|
+
cleanup = void 0;
|
|
307
|
+
let cleanupError;
|
|
308
|
+
if (previousCleanup) {
|
|
309
|
+
try {
|
|
310
|
+
previousCleanup();
|
|
311
|
+
} catch (error) {
|
|
312
|
+
const handled2 = owner?.handleError(error) ?? false;
|
|
313
|
+
if (!handled2) cleanupError = error;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
cleanupDependencies(eff);
|
|
317
|
+
const previous = getCurrentSubscriber();
|
|
318
|
+
setCurrentSubscriber(eff);
|
|
319
|
+
let thrown;
|
|
320
|
+
let handled = false;
|
|
321
|
+
try {
|
|
322
|
+
const result = owner ? owner.run(callback) : callback();
|
|
323
|
+
cleanup = typeof result === "function" ? result : void 0;
|
|
324
|
+
} catch (error) {
|
|
325
|
+
thrown = error;
|
|
326
|
+
handled = owner?.handleError(error) ?? false;
|
|
327
|
+
if (!handled) throw error;
|
|
328
|
+
} finally {
|
|
329
|
+
setCurrentSubscriber(previous);
|
|
330
|
+
}
|
|
331
|
+
if (cleanupError && !thrown) throw cleanupError;
|
|
332
|
+
},
|
|
333
|
+
scheduleLow() {
|
|
334
|
+
if (disposed || dirty) return;
|
|
335
|
+
dirty = true;
|
|
336
|
+
scheduler.scheduleLow(eff);
|
|
337
|
+
},
|
|
338
|
+
dispose() {
|
|
339
|
+
if (disposed) return;
|
|
340
|
+
disposed = true;
|
|
341
|
+
dirty = false;
|
|
342
|
+
scheduler.remove(eff);
|
|
343
|
+
const previousCleanup = cleanup;
|
|
344
|
+
cleanup = void 0;
|
|
345
|
+
let cleanupError;
|
|
346
|
+
if (previousCleanup) {
|
|
347
|
+
try {
|
|
348
|
+
previousCleanup();
|
|
349
|
+
} catch (error) {
|
|
350
|
+
const handled = owner?.handleError(error) ?? false;
|
|
351
|
+
if (!handled) cleanupError = error;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
cleanupDependencies(eff);
|
|
355
|
+
if (cleanupError) throw cleanupError;
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
owner?.addCleanup(eff.dispose);
|
|
359
|
+
eff.run();
|
|
360
|
+
return eff;
|
|
361
|
+
}
|
|
362
|
+
__name(effect, "effect");
|
|
363
|
+
|
|
364
|
+
// packages/resource/src/resource.ts
|
|
365
|
+
var defaultClient = createResourceClient();
|
|
366
|
+
function resource(optionsOrFetcher) {
|
|
367
|
+
return typeof optionsOrFetcher === "function" ? defaultClient.resource(optionsOrFetcher) : defaultClient.resource(optionsOrFetcher);
|
|
368
|
+
}
|
|
369
|
+
__name(resource, "resource");
|
|
370
|
+
function createResourceClient(options = {}) {
|
|
371
|
+
let owner = createOwner();
|
|
372
|
+
const cache = /* @__PURE__ */ new Map();
|
|
373
|
+
const entries = /* @__PURE__ */ new Set();
|
|
374
|
+
const defaultStaleTime = validateStaleTime(options.staleTime ?? 0);
|
|
375
|
+
const defaultRetry = validateRetry(options.retry ?? 0);
|
|
376
|
+
const defaultRetryDelay = options.retryDelay ?? 0;
|
|
377
|
+
function createEntry(key, staleTime) {
|
|
378
|
+
const entry = owner.run(() => ({
|
|
379
|
+
key,
|
|
380
|
+
data: state(null),
|
|
381
|
+
error: state(null),
|
|
382
|
+
loading: state(false),
|
|
383
|
+
staleTime,
|
|
384
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
385
|
+
updatedAt: 0,
|
|
386
|
+
revision: 0,
|
|
387
|
+
inFlight: null,
|
|
388
|
+
controller: null
|
|
389
|
+
}));
|
|
390
|
+
owner.onDispose(() => entry.controller?.abort());
|
|
391
|
+
entries.add(entry);
|
|
392
|
+
return entry;
|
|
393
|
+
}
|
|
394
|
+
__name(createEntry, "createEntry");
|
|
395
|
+
function execute(entry, fetcher, retry, retryDelay) {
|
|
396
|
+
if (entry.inFlight) return entry.inFlight;
|
|
397
|
+
entry.loading.value = true;
|
|
398
|
+
entry.error.value = null;
|
|
399
|
+
const controller = new AbortController();
|
|
400
|
+
entry.controller = controller;
|
|
401
|
+
const revision = entry.revision;
|
|
402
|
+
const request = requestWithRetry(fetcher, controller.signal, retry, retryDelay);
|
|
403
|
+
entry.inFlight = request.then(
|
|
404
|
+
(data) => {
|
|
405
|
+
if (entry.revision === revision) {
|
|
406
|
+
entry.revision++;
|
|
407
|
+
entry.data.value = data;
|
|
408
|
+
entry.error.value = null;
|
|
409
|
+
entry.updatedAt = Date.now();
|
|
410
|
+
}
|
|
411
|
+
return data;
|
|
412
|
+
},
|
|
413
|
+
(reason) => {
|
|
414
|
+
const error = toError(reason);
|
|
415
|
+
if (entry.revision === revision) {
|
|
416
|
+
entry.error.value = error;
|
|
417
|
+
if (!controller.signal.aborted) options.onError?.(error, entry.key);
|
|
418
|
+
}
|
|
419
|
+
throw error;
|
|
420
|
+
}
|
|
421
|
+
).finally(() => {
|
|
422
|
+
entry.loading.value = false;
|
|
423
|
+
if (entry.controller === controller) entry.controller = null;
|
|
424
|
+
entry.inFlight = null;
|
|
425
|
+
});
|
|
426
|
+
return entry.inFlight;
|
|
427
|
+
}
|
|
428
|
+
__name(execute, "execute");
|
|
429
|
+
function isFresh(entry) {
|
|
430
|
+
return entry.updatedAt > 0 && Date.now() - entry.updatedAt <= entry.staleTime;
|
|
431
|
+
}
|
|
432
|
+
__name(isFresh, "isFresh");
|
|
433
|
+
function createResource(optionsOrFetcher) {
|
|
434
|
+
const config = normalizeOptions(optionsOrFetcher, defaultStaleTime, defaultRetry, defaultRetryDelay);
|
|
435
|
+
if (isReactiveKey(config.key)) return createReactiveResource(config);
|
|
436
|
+
const staticKey = resolveKey(config.key);
|
|
437
|
+
const keyId = config.cache && staticKey ? stableSerialize(staticKey) : void 0;
|
|
438
|
+
let entry = keyId ? cache.get(keyId) : void 0;
|
|
439
|
+
if (!entry) {
|
|
440
|
+
entry = createEntry(staticKey, config.staleTime);
|
|
441
|
+
if (keyId) cache.set(keyId, entry);
|
|
442
|
+
}
|
|
443
|
+
const request = /* @__PURE__ */ __name((force) => {
|
|
444
|
+
if (entry.inFlight) return entry.inFlight;
|
|
445
|
+
if (!force && config.strategy === "stale-while-revalidate" && entry.data.value !== null) {
|
|
446
|
+
if (!isFresh(entry)) void execute(entry, config.fetcher, config.retry, config.retryDelay).catch(() => void 0);
|
|
447
|
+
return Promise.resolve(entry.data.value);
|
|
448
|
+
}
|
|
449
|
+
if (!force && isFresh(entry)) return Promise.resolve(entry.data.value);
|
|
450
|
+
return execute(entry, config.fetcher, config.retry, config.retryDelay);
|
|
451
|
+
}, "request");
|
|
452
|
+
void request(false).catch(() => void 0);
|
|
453
|
+
const resourceHandle = {};
|
|
454
|
+
entry.subscribers.add(resourceHandle);
|
|
455
|
+
const dispose = /* @__PURE__ */ __name(() => {
|
|
456
|
+
if (!entry?.subscribers.delete(resourceHandle)) return;
|
|
457
|
+
if (entry.subscribers.size === 0) entry.controller?.abort();
|
|
458
|
+
}, "dispose");
|
|
459
|
+
getCurrentOwner()?.onDispose(dispose);
|
|
460
|
+
return {
|
|
461
|
+
key: staticKey,
|
|
462
|
+
data: entry.data,
|
|
463
|
+
error: entry.error,
|
|
464
|
+
loading: entry.loading,
|
|
465
|
+
dispose,
|
|
466
|
+
refetch: /* @__PURE__ */ __name(() => request(true), "refetch"),
|
|
467
|
+
prefetch: /* @__PURE__ */ __name(() => request(false), "prefetch"),
|
|
468
|
+
invalidate: /* @__PURE__ */ __name(() => {
|
|
469
|
+
entry.updatedAt = 0;
|
|
470
|
+
}, "invalidate"),
|
|
471
|
+
mutate(next) {
|
|
472
|
+
const value = typeof next === "function" ? next(entry.data.value) : next;
|
|
473
|
+
entry.revision++;
|
|
474
|
+
entry.data.value = value;
|
|
475
|
+
entry.error.value = null;
|
|
476
|
+
entry.updatedAt = Date.now();
|
|
477
|
+
},
|
|
478
|
+
optimistic(next, action) {
|
|
479
|
+
const previous = {
|
|
480
|
+
data: entry.data.value,
|
|
481
|
+
error: entry.error.value,
|
|
482
|
+
updatedAt: entry.updatedAt
|
|
483
|
+
};
|
|
484
|
+
const value = typeof next === "function" ? next(entry.data.value) : next;
|
|
485
|
+
const revision = ++entry.revision;
|
|
486
|
+
entry.data.value = value;
|
|
487
|
+
entry.error.value = null;
|
|
488
|
+
entry.updatedAt = Date.now();
|
|
489
|
+
let actionResult;
|
|
490
|
+
try {
|
|
491
|
+
actionResult = Promise.resolve(action());
|
|
492
|
+
} catch (reason) {
|
|
493
|
+
actionResult = Promise.reject(reason);
|
|
494
|
+
}
|
|
495
|
+
return actionResult.catch((reason) => {
|
|
496
|
+
const error = toError(reason);
|
|
497
|
+
if (entry.revision === revision) {
|
|
498
|
+
entry.revision++;
|
|
499
|
+
entry.data.value = previous.data;
|
|
500
|
+
entry.error.value = error;
|
|
501
|
+
entry.updatedAt = previous.updatedAt;
|
|
502
|
+
options.onError?.(error, entry.key);
|
|
503
|
+
}
|
|
504
|
+
throw error;
|
|
505
|
+
});
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
function createReactiveResource(reactiveConfig) {
|
|
509
|
+
const data = state(null);
|
|
510
|
+
const error = state(null);
|
|
511
|
+
const loading = state(false);
|
|
512
|
+
const handle = {};
|
|
513
|
+
let activeEntry;
|
|
514
|
+
let activeKey;
|
|
515
|
+
let disposed = false;
|
|
516
|
+
const sync = /* @__PURE__ */ __name(() => {
|
|
517
|
+
if (!activeEntry) return;
|
|
518
|
+
data.value = activeEntry.data.value;
|
|
519
|
+
error.value = activeEntry.error.value;
|
|
520
|
+
loading.value = activeEntry.loading.value;
|
|
521
|
+
}, "sync");
|
|
522
|
+
const switchKey = /* @__PURE__ */ __name((nextKey) => {
|
|
523
|
+
const keyId2 = reactiveConfig.cache ? stableSerialize(nextKey) : void 0;
|
|
524
|
+
let nextEntry = keyId2 ? cache.get(keyId2) : void 0;
|
|
525
|
+
if (!nextEntry) {
|
|
526
|
+
nextEntry = createEntry(nextKey, reactiveConfig.staleTime);
|
|
527
|
+
if (keyId2) cache.set(keyId2, nextEntry);
|
|
528
|
+
}
|
|
529
|
+
if (activeEntry === nextEntry) {
|
|
530
|
+
sync();
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
if (activeEntry) {
|
|
534
|
+
activeEntry.subscribers.delete(handle);
|
|
535
|
+
if (activeEntry.subscribers.size === 0) activeEntry.controller?.abort();
|
|
536
|
+
}
|
|
537
|
+
activeEntry = nextEntry;
|
|
538
|
+
activeKey = nextKey;
|
|
539
|
+
activeEntry.subscribers.add(handle);
|
|
540
|
+
sync();
|
|
541
|
+
void request2(false).catch(() => void 0);
|
|
542
|
+
}, "switchKey");
|
|
543
|
+
const stop = effect(() => {
|
|
544
|
+
if (disposed) return;
|
|
545
|
+
const nextKey = resolveKey(reactiveConfig.key);
|
|
546
|
+
if (!nextKey) throw new Error("resource: \u54CD\u5E94\u5F0F key \u4E0D\u80FD\u662F undefined");
|
|
547
|
+
switchKey(nextKey);
|
|
548
|
+
sync();
|
|
549
|
+
});
|
|
550
|
+
const dispose2 = /* @__PURE__ */ __name(() => {
|
|
551
|
+
if (disposed) return;
|
|
552
|
+
disposed = true;
|
|
553
|
+
stop.dispose();
|
|
554
|
+
if (activeEntry) {
|
|
555
|
+
activeEntry.subscribers.delete(handle);
|
|
556
|
+
if (activeEntry.subscribers.size === 0) activeEntry.controller?.abort();
|
|
557
|
+
}
|
|
558
|
+
activeEntry = void 0;
|
|
559
|
+
}, "dispose");
|
|
560
|
+
getCurrentOwner()?.onDispose(dispose2);
|
|
561
|
+
return {
|
|
562
|
+
get key() {
|
|
563
|
+
return activeKey;
|
|
564
|
+
},
|
|
565
|
+
data,
|
|
566
|
+
error,
|
|
567
|
+
loading,
|
|
568
|
+
dispose: dispose2,
|
|
569
|
+
refetch: /* @__PURE__ */ __name(() => request2(true), "refetch"),
|
|
570
|
+
prefetch: /* @__PURE__ */ __name(() => request2(false), "prefetch"),
|
|
571
|
+
invalidate: /* @__PURE__ */ __name(() => {
|
|
572
|
+
if (activeEntry) activeEntry.updatedAt = 0;
|
|
573
|
+
}, "invalidate"),
|
|
574
|
+
mutate(next) {
|
|
575
|
+
if (!activeEntry) return;
|
|
576
|
+
const value = typeof next === "function" ? next(activeEntry.data.value) : next;
|
|
577
|
+
activeEntry.revision++;
|
|
578
|
+
activeEntry.data.value = value;
|
|
579
|
+
activeEntry.error.value = null;
|
|
580
|
+
activeEntry.updatedAt = Date.now();
|
|
581
|
+
},
|
|
582
|
+
optimistic(next, action) {
|
|
583
|
+
if (!activeEntry) return Promise.reject(new Error("resource: key \u5C1A\u672A\u521D\u59CB\u5316"));
|
|
584
|
+
return createOptimistic(activeEntry, next, action);
|
|
585
|
+
}
|
|
586
|
+
};
|
|
587
|
+
function request2(force) {
|
|
588
|
+
if (!activeEntry) return Promise.reject(new Error("resource: key \u5C1A\u672A\u521D\u59CB\u5316"));
|
|
589
|
+
if (!force && isFresh(activeEntry) && reactiveConfig.strategy === "cache-first") {
|
|
590
|
+
return Promise.resolve(activeEntry.data.value);
|
|
591
|
+
}
|
|
592
|
+
if (!force && reactiveConfig.strategy === "stale-while-revalidate" && activeEntry.data.value !== null) {
|
|
593
|
+
if (!isFresh(activeEntry)) void execute(activeEntry, reactiveConfig.fetcher, reactiveConfig.retry, reactiveConfig.retryDelay).catch(() => void 0);
|
|
594
|
+
return Promise.resolve(activeEntry.data.value);
|
|
595
|
+
}
|
|
596
|
+
return execute(activeEntry, reactiveConfig.fetcher, reactiveConfig.retry, reactiveConfig.retryDelay);
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function createOptimistic(target, next, action) {
|
|
600
|
+
const previous = { data: target.data.value, error: target.error.value, updatedAt: target.updatedAt };
|
|
601
|
+
const value = typeof next === "function" ? next(target.data.value) : next;
|
|
602
|
+
const revision = ++target.revision;
|
|
603
|
+
target.data.value = value;
|
|
604
|
+
target.error.value = null;
|
|
605
|
+
target.updatedAt = Date.now();
|
|
606
|
+
return Promise.resolve().then(action).catch((reason) => {
|
|
607
|
+
const failure = toError(reason);
|
|
608
|
+
if (target.revision === revision) {
|
|
609
|
+
target.revision++;
|
|
610
|
+
target.data.value = previous.data;
|
|
611
|
+
target.error.value = failure;
|
|
612
|
+
target.updatedAt = previous.updatedAt;
|
|
613
|
+
options.onError?.(failure, target.key);
|
|
614
|
+
}
|
|
615
|
+
throw failure;
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
__name(createResource, "createResource");
|
|
620
|
+
return {
|
|
621
|
+
resource: createResource,
|
|
622
|
+
invalidate(key) {
|
|
623
|
+
const entry = cache.get(stableSerialize(key));
|
|
624
|
+
if (entry) entry.updatedAt = 0;
|
|
625
|
+
},
|
|
626
|
+
async prefetchAll() {
|
|
627
|
+
const requests = [...entries].map((entry) => entry.inFlight).filter((request) => request !== null);
|
|
628
|
+
await Promise.allSettled(requests);
|
|
629
|
+
},
|
|
630
|
+
dehydrate() {
|
|
631
|
+
const entries2 = [];
|
|
632
|
+
for (const entry of cache.values()) {
|
|
633
|
+
if (entry.updatedAt <= 0 || entry.error.value) continue;
|
|
634
|
+
entries2.push({
|
|
635
|
+
key: entry.key ?? [],
|
|
636
|
+
data: entry.data.value,
|
|
637
|
+
updatedAt: entry.updatedAt,
|
|
638
|
+
staleTime: entry.staleTime
|
|
639
|
+
});
|
|
640
|
+
}
|
|
641
|
+
return { version: 1, entries: entries2 };
|
|
642
|
+
},
|
|
643
|
+
hydrate(snapshot) {
|
|
644
|
+
for (const restored of parseDehydratedState(snapshot).entries) {
|
|
645
|
+
const keyId = stableSerialize(restored.key);
|
|
646
|
+
const entry = cache.get(keyId) ?? createEntry(restored.key, restored.staleTime);
|
|
647
|
+
entry.data.value = restored.data;
|
|
648
|
+
entry.error.value = null;
|
|
649
|
+
entry.loading.value = false;
|
|
650
|
+
entry.updatedAt = restored.updatedAt;
|
|
651
|
+
entry.revision++;
|
|
652
|
+
cache.set(keyId, entry);
|
|
653
|
+
}
|
|
654
|
+
},
|
|
655
|
+
get(key) {
|
|
656
|
+
const entry = cache.get(stableSerialize(key));
|
|
657
|
+
if (!entry) return void 0;
|
|
658
|
+
return {
|
|
659
|
+
data: entry.data.value,
|
|
660
|
+
error: entry.error.value,
|
|
661
|
+
loading: entry.loading.value,
|
|
662
|
+
updatedAt: entry.updatedAt
|
|
663
|
+
};
|
|
664
|
+
},
|
|
665
|
+
clear() {
|
|
666
|
+
cache.clear();
|
|
667
|
+
entries.clear();
|
|
668
|
+
owner.dispose();
|
|
669
|
+
owner = createOwner();
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
__name(createResourceClient, "createResourceClient");
|
|
674
|
+
function normalizeOptions(optionsOrFetcher, defaultStaleTime, defaultRetry, defaultRetryDelay) {
|
|
675
|
+
if (typeof optionsOrFetcher === "function") {
|
|
676
|
+
return {
|
|
677
|
+
fetcher: optionsOrFetcher,
|
|
678
|
+
staleTime: defaultStaleTime,
|
|
679
|
+
cache: false,
|
|
680
|
+
strategy: "cache-first",
|
|
681
|
+
retry: defaultRetry,
|
|
682
|
+
retryDelay: defaultRetryDelay
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
return {
|
|
686
|
+
key: optionsOrFetcher.key,
|
|
687
|
+
fetcher: optionsOrFetcher.fetcher,
|
|
688
|
+
staleTime: validateStaleTime(optionsOrFetcher.staleTime ?? defaultStaleTime),
|
|
689
|
+
cache: optionsOrFetcher.cache ?? Boolean(optionsOrFetcher.key),
|
|
690
|
+
strategy: optionsOrFetcher.strategy ?? "cache-first",
|
|
691
|
+
retry: validateRetry(optionsOrFetcher.retry ?? defaultRetry),
|
|
692
|
+
retryDelay: optionsOrFetcher.retryDelay ?? defaultRetryDelay
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
__name(normalizeOptions, "normalizeOptions");
|
|
696
|
+
function isReactiveKey(key) {
|
|
697
|
+
return typeof key === "function" || isSignal(key);
|
|
698
|
+
}
|
|
699
|
+
__name(isReactiveKey, "isReactiveKey");
|
|
700
|
+
function isSignal(value) {
|
|
701
|
+
return value !== null && typeof value === "object" && "value" in value && typeof value.dispose === "function";
|
|
702
|
+
}
|
|
703
|
+
__name(isSignal, "isSignal");
|
|
704
|
+
function resolveKey(source) {
|
|
705
|
+
const key = typeof source === "function" ? source() : isSignal(source) ? source.value : source;
|
|
706
|
+
if (key === void 0) return void 0;
|
|
707
|
+
if (!Array.isArray(key)) throw new Error("resource: key \u5FC5\u987B\u662F\u6570\u7EC4");
|
|
708
|
+
return key;
|
|
709
|
+
}
|
|
710
|
+
__name(resolveKey, "resolveKey");
|
|
711
|
+
function requestWithRetry(fetcher, signal, retry, retryDelay) {
|
|
712
|
+
let attempt = 0;
|
|
713
|
+
const request = /* @__PURE__ */ __name(() => Promise.resolve().then(() => fetcher(signal)).catch((reason) => {
|
|
714
|
+
const error = toError(reason);
|
|
715
|
+
if (signal.aborted) throw error;
|
|
716
|
+
if (attempt++ >= retry) throw error;
|
|
717
|
+
const delay = resolveRetryDelay(retryDelay, attempt, error);
|
|
718
|
+
return delay > 0 ? wait(delay).then(request) : request();
|
|
719
|
+
}), "request");
|
|
720
|
+
return request();
|
|
721
|
+
}
|
|
722
|
+
__name(requestWithRetry, "requestWithRetry");
|
|
723
|
+
function resolveRetryDelay(retryDelay, attempt, error) {
|
|
724
|
+
const delay = typeof retryDelay === "function" ? retryDelay(attempt, error) : retryDelay;
|
|
725
|
+
if (!Number.isFinite(delay) || delay < 0) {
|
|
726
|
+
throw new Error("resource: retryDelay \u5FC5\u987B\u662F\u5927\u4E8E\u7B49\u4E8E 0 \u7684\u6709\u9650\u6570\u5B57");
|
|
727
|
+
}
|
|
728
|
+
return delay;
|
|
729
|
+
}
|
|
730
|
+
__name(resolveRetryDelay, "resolveRetryDelay");
|
|
731
|
+
function wait(delay) {
|
|
732
|
+
return new Promise((resolve) => setTimeout(resolve, delay));
|
|
733
|
+
}
|
|
734
|
+
__name(wait, "wait");
|
|
735
|
+
function validateStaleTime(staleTime) {
|
|
736
|
+
if (!Number.isFinite(staleTime) || staleTime < 0) {
|
|
737
|
+
throw new Error("resource: staleTime \u5FC5\u987B\u662F\u5927\u4E8E\u7B49\u4E8E 0 \u7684\u6709\u9650\u6570\u5B57");
|
|
738
|
+
}
|
|
739
|
+
return staleTime;
|
|
740
|
+
}
|
|
741
|
+
__name(validateStaleTime, "validateStaleTime");
|
|
742
|
+
function validateRetry(retry) {
|
|
743
|
+
if (!Number.isInteger(retry) || retry < 0) {
|
|
744
|
+
throw new Error("resource: retry \u5FC5\u987B\u662F\u5927\u4E8E\u7B49\u4E8E 0 \u7684\u6574\u6570");
|
|
745
|
+
}
|
|
746
|
+
return retry;
|
|
747
|
+
}
|
|
748
|
+
__name(validateRetry, "validateRetry");
|
|
749
|
+
function toError(reason) {
|
|
750
|
+
return reason instanceof Error ? reason : new Error(String(reason));
|
|
751
|
+
}
|
|
752
|
+
__name(toError, "toError");
|
|
753
|
+
function stableSerialize(value) {
|
|
754
|
+
return serialize(value, /* @__PURE__ */ new Set());
|
|
755
|
+
}
|
|
756
|
+
__name(stableSerialize, "stableSerialize");
|
|
757
|
+
function serializeResourceState(snapshot) {
|
|
758
|
+
const serialized = JSON.stringify(snapshot);
|
|
759
|
+
return serialized.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
|
|
760
|
+
}
|
|
761
|
+
__name(serializeResourceState, "serializeResourceState");
|
|
762
|
+
function parseDehydratedState(snapshot) {
|
|
763
|
+
let value = snapshot;
|
|
764
|
+
if (typeof snapshot === "string") {
|
|
765
|
+
try {
|
|
766
|
+
value = JSON.parse(snapshot);
|
|
767
|
+
} catch {
|
|
768
|
+
throw new Error("resource: \u9884\u53D6\u72B6\u6001\u4E0D\u662F\u6709\u6548 JSON");
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
if (!value || typeof value !== "object") throw new Error("resource: \u9884\u53D6\u72B6\u6001\u683C\u5F0F\u65E0\u6548");
|
|
772
|
+
const candidate = value;
|
|
773
|
+
if (candidate.version !== 1 || !Array.isArray(candidate.entries)) {
|
|
774
|
+
throw new Error("resource: \u9884\u53D6\u72B6\u6001\u7248\u672C\u6216 entries \u65E0\u6548");
|
|
775
|
+
}
|
|
776
|
+
const entries = [];
|
|
777
|
+
for (const entry of candidate.entries) {
|
|
778
|
+
if (!entry || typeof entry !== "object") throw new Error("resource: \u9884\u53D6\u6761\u76EE\u683C\u5F0F\u65E0\u6548");
|
|
779
|
+
const candidateEntry = entry;
|
|
780
|
+
if (!Array.isArray(candidateEntry.key) || typeof candidateEntry.updatedAt !== "number" || !Number.isFinite(candidateEntry.updatedAt) || typeof candidateEntry.staleTime !== "number" || !Number.isFinite(candidateEntry.staleTime) || candidateEntry.staleTime < 0) {
|
|
781
|
+
throw new Error("resource: \u9884\u53D6\u6761\u76EE\u5B57\u6BB5\u65E0\u6548");
|
|
782
|
+
}
|
|
783
|
+
stableSerialize(candidateEntry.key);
|
|
784
|
+
entries.push({
|
|
785
|
+
key: candidateEntry.key,
|
|
786
|
+
data: candidateEntry.data,
|
|
787
|
+
updatedAt: candidateEntry.updatedAt,
|
|
788
|
+
staleTime: candidateEntry.staleTime
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
return { version: 1, entries };
|
|
792
|
+
}
|
|
793
|
+
__name(parseDehydratedState, "parseDehydratedState");
|
|
794
|
+
function serialize(value, stack) {
|
|
795
|
+
if (value === null) return "null";
|
|
796
|
+
switch (typeof value) {
|
|
797
|
+
case "string":
|
|
798
|
+
return `string:${JSON.stringify(value)}`;
|
|
799
|
+
case "boolean":
|
|
800
|
+
return `boolean:${value}`;
|
|
801
|
+
case "number":
|
|
802
|
+
if (Number.isNaN(value)) return "number:NaN";
|
|
803
|
+
if (Object.is(value, -0)) return "number:-0";
|
|
804
|
+
return `number:${value}`;
|
|
805
|
+
case "bigint":
|
|
806
|
+
return `bigint:${value}`;
|
|
807
|
+
case "undefined":
|
|
808
|
+
return "undefined";
|
|
809
|
+
case "function":
|
|
810
|
+
case "symbol":
|
|
811
|
+
throw new Error(`resource: key \u4E0D\u80FD\u5305\u542B ${typeof value}`);
|
|
812
|
+
}
|
|
813
|
+
const object = value;
|
|
814
|
+
if (stack.has(object)) throw new Error("resource: key \u4E0D\u80FD\u5305\u542B\u5FAA\u73AF\u5F15\u7528");
|
|
815
|
+
stack.add(object);
|
|
816
|
+
try {
|
|
817
|
+
if (Array.isArray(object)) {
|
|
818
|
+
return `array:[${object.map((item) => serialize(item, stack)).join(",")}]`;
|
|
819
|
+
}
|
|
820
|
+
if (object instanceof Date) return `date:${object.toJSON()}`;
|
|
821
|
+
if (object instanceof RegExp) return `regexp:${object.toString()}`;
|
|
822
|
+
const entries = Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${serialize(object[key], stack)}`);
|
|
823
|
+
return `object:{${entries.join(",")}}`;
|
|
824
|
+
} finally {
|
|
825
|
+
stack.delete(object);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
__name(serialize, "serialize");
|
|
829
|
+
|
|
830
|
+
// packages/runtime/src/debug.ts
|
|
831
|
+
var activeRuntimeDebugHooks = null;
|
|
832
|
+
function getRuntimeDebugHooks() {
|
|
833
|
+
return activeRuntimeDebugHooks;
|
|
834
|
+
}
|
|
835
|
+
__name(getRuntimeDebugHooks, "getRuntimeDebugHooks");
|
|
836
|
+
function invokeRuntimeDebug(name, ...args) {
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
__name(invokeRuntimeDebug, "invokeRuntimeDebug");
|
|
840
|
+
function describeDebugNode(node) {
|
|
841
|
+
if (!node || typeof node !== "object") return "node";
|
|
842
|
+
const value = node;
|
|
843
|
+
const name = typeof value.tagName === "string" ? value.tagName.toLowerCase() : typeof value.nodeName === "string" ? value.nodeName.toLowerCase() : "node";
|
|
844
|
+
const id = typeof value.id === "string" && value.id ? `#${value.id}` : "";
|
|
845
|
+
const className = typeof value.className === "string" && value.className ? `.${value.className.trim().split(/\s+/).filter(Boolean).join(".")}` : "";
|
|
846
|
+
return `${name}${id}${className}`;
|
|
847
|
+
}
|
|
848
|
+
__name(describeDebugNode, "describeDebugNode");
|
|
849
|
+
|
|
850
|
+
// packages/runtime/src/hmr.ts
|
|
851
|
+
var globalTarget = globalThis;
|
|
852
|
+
var hmrGlobal = globalTarget.__VOBS_HMR__ ?? { modules: /* @__PURE__ */ new Map() };
|
|
853
|
+
globalTarget.__VOBS_HMR__ = hmrGlobal;
|
|
854
|
+
function markHmrInstanceMounted(node, parent) {
|
|
855
|
+
const instance = hmrInstances.get(node);
|
|
856
|
+
if (instance) instance.parent = parent;
|
|
857
|
+
}
|
|
858
|
+
__name(markHmrInstanceMounted, "markHmrInstanceMounted");
|
|
859
|
+
var hmrInstances = /* @__PURE__ */ new WeakMap();
|
|
860
|
+
var nodeOwners = /* @__PURE__ */ new WeakMap();
|
|
861
|
+
function getRenderer() {
|
|
862
|
+
{
|
|
863
|
+
throw new Error("\u6E32\u67D3\u5668\u672A\u521D\u59CB\u5316");
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
__name(getRenderer, "getRenderer");
|
|
867
|
+
function createComment(content) {
|
|
868
|
+
return getRenderer().createComment(content);
|
|
869
|
+
}
|
|
870
|
+
__name(createComment, "createComment");
|
|
871
|
+
function insertBefore(parent, child, anchor) {
|
|
872
|
+
if (isVobsFragment(child)) {
|
|
873
|
+
child.mount(parent, isVobsFragment(anchor) ? anchor.start : anchor);
|
|
874
|
+
return;
|
|
875
|
+
}
|
|
876
|
+
getRenderer().insertBefore(parent, child, isVobsFragment(anchor) ? anchor.start : anchor);
|
|
877
|
+
markHmrInstanceMounted(child, parent);
|
|
878
|
+
}
|
|
879
|
+
__name(insertBefore, "insertBefore");
|
|
880
|
+
function removeChild(parent, child) {
|
|
881
|
+
disposeNodeOwner(child);
|
|
882
|
+
if (isVobsFragment(child)) {
|
|
883
|
+
child.unmount(parent);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
getRenderer().removeChild(parent, child);
|
|
887
|
+
}
|
|
888
|
+
__name(removeChild, "removeChild");
|
|
889
|
+
function createBlock(factory) {
|
|
890
|
+
const owner = createOwner();
|
|
891
|
+
setOwnerDebugName(owner, "dynamic");
|
|
892
|
+
let node;
|
|
893
|
+
try {
|
|
894
|
+
node = owner.run(factory);
|
|
895
|
+
} catch (error) {
|
|
896
|
+
owner.dispose();
|
|
897
|
+
throw error;
|
|
898
|
+
}
|
|
899
|
+
if (!node) {
|
|
900
|
+
owner.dispose();
|
|
901
|
+
return null;
|
|
902
|
+
}
|
|
903
|
+
associateNodeOwner(node, owner);
|
|
904
|
+
return node;
|
|
905
|
+
}
|
|
906
|
+
__name(createBlock, "createBlock");
|
|
907
|
+
function associateNodeOwner(node, owner) {
|
|
908
|
+
nodeOwners.set(node, owner);
|
|
909
|
+
}
|
|
910
|
+
__name(associateNodeOwner, "associateNodeOwner");
|
|
911
|
+
function disposeNodeOwner(node) {
|
|
912
|
+
const owner = nodeOwners.get(node);
|
|
913
|
+
if (!owner) return;
|
|
914
|
+
nodeOwners.delete(node);
|
|
915
|
+
owner.dispose();
|
|
916
|
+
}
|
|
917
|
+
__name(disposeNodeOwner, "disposeNodeOwner");
|
|
918
|
+
|
|
919
|
+
// packages/runtime/src/fragment.ts
|
|
920
|
+
function createFragment(factory) {
|
|
921
|
+
const start = createComment("vobs:fragment:start");
|
|
922
|
+
const end = createComment("vobs:fragment:end");
|
|
923
|
+
let parent = null;
|
|
924
|
+
let initialized = false;
|
|
925
|
+
const owner = getCurrentOwner();
|
|
926
|
+
const fragment = {
|
|
927
|
+
kind: "vobs-fragment",
|
|
928
|
+
start,
|
|
929
|
+
end,
|
|
930
|
+
mount(nextParent, anchor) {
|
|
931
|
+
if (parent && parent !== nextParent) {
|
|
932
|
+
throw new Error("Vobs Fragment: \u4E0D\u80FD\u8DE8\u7236\u8282\u70B9\u79FB\u52A8 Fragment");
|
|
933
|
+
}
|
|
934
|
+
if (initialized) {
|
|
935
|
+
moveRange(nextParent, start, end, anchor);
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
const renderer = getRenderer();
|
|
939
|
+
renderer.insertBefore(nextParent, start, anchor);
|
|
940
|
+
renderer.insertBefore(nextParent, end, anchor);
|
|
941
|
+
parent = nextParent;
|
|
942
|
+
initialized = true;
|
|
943
|
+
if (owner) owner.run(() => factory(nextParent, end));
|
|
944
|
+
else factory(nextParent, end);
|
|
945
|
+
},
|
|
946
|
+
unmount(nextParent) {
|
|
947
|
+
if (!initialized || parent !== nextParent) {
|
|
948
|
+
throw new Error("Vobs Fragment: Fragment \u4E0D\u5C5E\u4E8E\u6307\u5B9A\u7236\u8282\u70B9");
|
|
949
|
+
}
|
|
950
|
+
const renderer = getRenderer();
|
|
951
|
+
let current = renderer.nextSibling(start);
|
|
952
|
+
while (current && current !== end) {
|
|
953
|
+
const next = renderer.nextSibling(current);
|
|
954
|
+
renderer.removeChild(nextParent, current);
|
|
955
|
+
current = next;
|
|
956
|
+
}
|
|
957
|
+
renderer.removeChild(nextParent, start);
|
|
958
|
+
renderer.removeChild(nextParent, end);
|
|
959
|
+
parent = null;
|
|
960
|
+
initialized = false;
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
return fragment;
|
|
964
|
+
}
|
|
965
|
+
__name(createFragment, "createFragment");
|
|
966
|
+
function isVobsFragment(value) {
|
|
967
|
+
return Boolean(value) && typeof value === "object" && value.kind === "vobs-fragment";
|
|
968
|
+
}
|
|
969
|
+
__name(isVobsFragment, "isVobsFragment");
|
|
970
|
+
function moveRange(parent, start, end, anchor) {
|
|
971
|
+
const renderer = getRenderer();
|
|
972
|
+
const nodes = [start];
|
|
973
|
+
let current = renderer.nextSibling(start);
|
|
974
|
+
while (current) {
|
|
975
|
+
nodes.push(current);
|
|
976
|
+
if (current === end) break;
|
|
977
|
+
current = renderer.nextSibling(current);
|
|
978
|
+
}
|
|
979
|
+
if (nodes[nodes.length - 1] !== end) {
|
|
980
|
+
throw new Error("Vobs Fragment: \u627E\u4E0D\u5230\u7ED3\u675F\u951A\u70B9");
|
|
981
|
+
}
|
|
982
|
+
for (const node of nodes) renderer.insertBefore(parent, node, anchor);
|
|
983
|
+
}
|
|
984
|
+
__name(moveRange, "moveRange");
|
|
985
|
+
|
|
986
|
+
// packages/runtime/src/dynamic.ts
|
|
987
|
+
function insertDynamic(parent, anchor, factory) {
|
|
988
|
+
const marker = createComment("vobs:dynamic");
|
|
989
|
+
insertBefore(parent, marker, anchor);
|
|
990
|
+
let current = null;
|
|
991
|
+
effect(() => {
|
|
992
|
+
const next = createBlock(factory);
|
|
993
|
+
if (next === current) return;
|
|
994
|
+
if (current) removeChild(parent, current);
|
|
995
|
+
current = next;
|
|
996
|
+
if (current) insertBefore(parent, current, marker);
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
__name(insertDynamic, "insertDynamic");
|
|
1000
|
+
|
|
1001
|
+
// packages/runtime/src/error.ts
|
|
1002
|
+
var _VobsError = class _VobsError extends Error {
|
|
1003
|
+
constructor(options) {
|
|
1004
|
+
super(options.message);
|
|
1005
|
+
this.name = "VobsError";
|
|
1006
|
+
this.code = options.code;
|
|
1007
|
+
this.severity = options.severity ?? "error";
|
|
1008
|
+
this.layer = options.layer ?? "runtime";
|
|
1009
|
+
this.cause = options.cause;
|
|
1010
|
+
this.fix = options.fix;
|
|
1011
|
+
this.location = options.location;
|
|
1012
|
+
this.trace = options.trace;
|
|
1013
|
+
this.example = options.example;
|
|
1014
|
+
this.docs = options.docs;
|
|
1015
|
+
this.codeFrame = options.codeFrame;
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
__name(_VobsError, "VobsError");
|
|
1019
|
+
var VobsError = _VobsError;
|
|
1020
|
+
function isVobsError(value) {
|
|
1021
|
+
return value instanceof VobsError || Boolean(value && typeof value === "object" && typeof value.code === "string" && typeof value.message === "string" && typeof value.layer === "string");
|
|
1022
|
+
}
|
|
1023
|
+
__name(isVobsError, "isVobsError");
|
|
1024
|
+
function normalizeVobsError(value, defaults = {}) {
|
|
1025
|
+
if (value instanceof VobsError) return value;
|
|
1026
|
+
if (value instanceof Error) {
|
|
1027
|
+
const metadata = value;
|
|
1028
|
+
const code = defaults.code ?? (typeof metadata.vobsCode === "string" ? metadata.vobsCode : void 0);
|
|
1029
|
+
if (code) defineErrorMetadata(value, "code", code);
|
|
1030
|
+
defineErrorMetadata(value, "severity", defaults.severity ?? "error");
|
|
1031
|
+
defineErrorMetadata(value, "layer", defaults.layer ?? "runtime");
|
|
1032
|
+
const fix = defaults.fix ?? (typeof metadata.vobsHint === "string" ? metadata.vobsHint : void 0);
|
|
1033
|
+
if (fix) defineErrorMetadata(value, "fix", fix);
|
|
1034
|
+
const source = metadata.vobsSource;
|
|
1035
|
+
if (source && typeof source === "object" && typeof source.file === "string" && typeof source.line === "number" && typeof source.column === "number") {
|
|
1036
|
+
defineErrorMetadata(value, "location", source);
|
|
1037
|
+
}
|
|
1038
|
+
return value;
|
|
1039
|
+
}
|
|
1040
|
+
if (isVobsError(value)) {
|
|
1041
|
+
const candidate = value;
|
|
1042
|
+
return new VobsError({
|
|
1043
|
+
code: candidate.code,
|
|
1044
|
+
message: candidate.message,
|
|
1045
|
+
severity: candidate.severity ?? defaults.severity,
|
|
1046
|
+
layer: candidate.layer ?? defaults.layer,
|
|
1047
|
+
cause: candidate.cause,
|
|
1048
|
+
fix: candidate.fix ?? defaults.fix,
|
|
1049
|
+
location: candidate.location,
|
|
1050
|
+
trace: candidate.trace,
|
|
1051
|
+
example: candidate.example,
|
|
1052
|
+
docs: candidate.docs,
|
|
1053
|
+
codeFrame: candidate.codeFrame
|
|
1054
|
+
});
|
|
1055
|
+
}
|
|
1056
|
+
const message = String(value);
|
|
1057
|
+
return new VobsError({
|
|
1058
|
+
code: defaults.code ?? "VOBS_UNKNOWN",
|
|
1059
|
+
message,
|
|
1060
|
+
severity: defaults.severity ?? "error",
|
|
1061
|
+
layer: defaults.layer ?? "runtime",
|
|
1062
|
+
cause: void 0,
|
|
1063
|
+
fix: defaults.fix
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
__name(normalizeVobsError, "normalizeVobsError");
|
|
1067
|
+
function defineErrorMetadata(target, key, value) {
|
|
1068
|
+
if (key in target) return;
|
|
1069
|
+
try {
|
|
1070
|
+
Object.defineProperty(target, key, { configurable: true, enumerable: false, value, writable: true });
|
|
1071
|
+
} catch {
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
__name(defineErrorMetadata, "defineErrorMetadata");
|
|
1075
|
+
|
|
1076
|
+
// packages/runtime/src/boundary.ts
|
|
1077
|
+
function insertBoundary(parent, anchor, options) {
|
|
1078
|
+
const boundary = createOwner();
|
|
1079
|
+
boundary.run(() => {
|
|
1080
|
+
const error = state(null);
|
|
1081
|
+
let fallbackActive = false;
|
|
1082
|
+
let lastError = null;
|
|
1083
|
+
let initialized = false;
|
|
1084
|
+
let previousKey;
|
|
1085
|
+
boundary.onError((reason) => {
|
|
1086
|
+
if (fallbackActive) throw reason;
|
|
1087
|
+
const normalized = normalizeVobsError(reason, {
|
|
1088
|
+
code: "VOBS_R001",
|
|
1089
|
+
layer: "runtime",
|
|
1090
|
+
fix: "\u68C0\u67E5\u7EC4\u4EF6\u6E32\u67D3\u903B\u8F91\uFF0C\u6216\u5728\u8FB9\u754C fallback \u4E2D\u63D0\u4F9B\u6062\u590D\u64CD\u4F5C\u3002"
|
|
1091
|
+
});
|
|
1092
|
+
lastError = normalized;
|
|
1093
|
+
invokeRuntimeDebug("error", {
|
|
1094
|
+
error: normalized,
|
|
1095
|
+
owner: boundary,
|
|
1096
|
+
phase: "boundary",
|
|
1097
|
+
handled: true,
|
|
1098
|
+
recovery: "fallback"
|
|
1099
|
+
});
|
|
1100
|
+
error.value = normalized;
|
|
1101
|
+
});
|
|
1102
|
+
const retry = /* @__PURE__ */ __name(() => {
|
|
1103
|
+
if (error.value) {
|
|
1104
|
+
invokeRuntimeDebug("error", {
|
|
1105
|
+
error: error.value,
|
|
1106
|
+
owner: boundary,
|
|
1107
|
+
phase: "boundary",
|
|
1108
|
+
handled: true,
|
|
1109
|
+
recovery: "retrying"
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
error.value = null;
|
|
1113
|
+
return options.onRetry?.();
|
|
1114
|
+
}, "retry");
|
|
1115
|
+
insertDynamic(parent, anchor, () => {
|
|
1116
|
+
const nextKey = options.resetKey?.();
|
|
1117
|
+
if (!initialized || !Object.is(previousKey, nextKey)) {
|
|
1118
|
+
initialized = true;
|
|
1119
|
+
previousKey = nextKey;
|
|
1120
|
+
if (error.value) error.value = null;
|
|
1121
|
+
}
|
|
1122
|
+
const currentError = error.value;
|
|
1123
|
+
if (!currentError) {
|
|
1124
|
+
if (fallbackActive && lastError) {
|
|
1125
|
+
invokeRuntimeDebug("error", {
|
|
1126
|
+
error: lastError,
|
|
1127
|
+
owner: boundary,
|
|
1128
|
+
phase: "boundary",
|
|
1129
|
+
handled: true,
|
|
1130
|
+
recovery: "recovered"
|
|
1131
|
+
});
|
|
1132
|
+
lastError = null;
|
|
1133
|
+
}
|
|
1134
|
+
fallbackActive = false;
|
|
1135
|
+
return options.children();
|
|
1136
|
+
}
|
|
1137
|
+
fallbackActive = true;
|
|
1138
|
+
return options.fallback(currentError, retry);
|
|
1139
|
+
});
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
__name(insertBoundary, "insertBoundary");
|
|
1143
|
+
|
|
1144
|
+
// packages/vobs/src/app.ts
|
|
1145
|
+
function createInjectionKey(description) {
|
|
1146
|
+
return Symbol(description);
|
|
1147
|
+
}
|
|
1148
|
+
__name(createInjectionKey, "createInjectionKey");
|
|
1149
|
+
|
|
1150
|
+
// packages/resource/src/boundary.ts
|
|
1151
|
+
function insertResourceBoundary(parent, anchor, options) {
|
|
1152
|
+
insertBoundary(parent, anchor, {
|
|
1153
|
+
onRetry: /* @__PURE__ */ __name(() => options.resource.refetch(), "onRetry"),
|
|
1154
|
+
fallback: /* @__PURE__ */ __name((error, retry) => options.fallback?.(error, () => Promise.resolve(retry())) ?? null, "fallback"),
|
|
1155
|
+
children: /* @__PURE__ */ __name(() => {
|
|
1156
|
+
if (options.resource.error.value) throw options.resource.error.value;
|
|
1157
|
+
if (options.resource.loading.value) return resolveView(options.loading);
|
|
1158
|
+
const data = options.resource.data.value;
|
|
1159
|
+
if (data === null) return resolveView(options.empty);
|
|
1160
|
+
return options.children(data);
|
|
1161
|
+
}, "children")
|
|
1162
|
+
});
|
|
1163
|
+
}
|
|
1164
|
+
__name(insertResourceBoundary, "insertResourceBoundary");
|
|
1165
|
+
function ResourceBoundary(props) {
|
|
1166
|
+
return createFragment((parent, anchor) => insertResourceBoundary(parent, anchor, props));
|
|
1167
|
+
}
|
|
1168
|
+
__name(ResourceBoundary, "ResourceBoundary");
|
|
1169
|
+
function resolveView(view) {
|
|
1170
|
+
if (!view) return null;
|
|
1171
|
+
return typeof view === "function" ? view() : view;
|
|
1172
|
+
}
|
|
1173
|
+
__name(resolveView, "resolveView");
|
|
1174
|
+
|
|
1175
|
+
// packages/router/src/index.ts
|
|
1176
|
+
var ROUTER_KEY = createInjectionKey("vobs.router");
|
|
1177
|
+
|
|
1178
|
+
// packages/resource/src/plugin.ts
|
|
1179
|
+
var RESOURCE_KEY = createInjectionKey("vobs.resource");
|
|
1180
|
+
function resourcePlugin(options = {}) {
|
|
1181
|
+
return {
|
|
1182
|
+
name: "@vobs/resource",
|
|
1183
|
+
version: "0.1.0",
|
|
1184
|
+
install(context) {
|
|
1185
|
+
const client = options.client ?? createResourceClient(options);
|
|
1186
|
+
context.provide(RESOURCE_KEY, client);
|
|
1187
|
+
return () => {
|
|
1188
|
+
if (!options.client) client.clear();
|
|
1189
|
+
};
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
__name(resourcePlugin, "resourcePlugin");
|
|
1194
|
+
function resourceRouterPlugin(options = {}) {
|
|
1195
|
+
return {
|
|
1196
|
+
name: "@vobs/resource-router",
|
|
1197
|
+
version: "0.1.0",
|
|
1198
|
+
install(context) {
|
|
1199
|
+
const router = options.router ?? context.inject(ROUTER_KEY);
|
|
1200
|
+
const client = options.client ?? context.inject(RESOURCE_KEY);
|
|
1201
|
+
if (!router) throw new Error("Vobs Resource Router: \u627E\u4E0D\u5230 Router\uFF0C\u8BF7\u5B89\u88C5 routerPlugin \u6216\u4F20\u5165 router");
|
|
1202
|
+
if (!client) throw new Error("Vobs Resource Router: \u627E\u4E0D\u5230 ResourceClient\uFF0C\u8BF7\u5B89\u88C5 resourcePlugin \u6216\u4F20\u5165 client");
|
|
1203
|
+
return router.beforeEach(async (to) => {
|
|
1204
|
+
const prefetch = readPrefetch(to);
|
|
1205
|
+
await Promise.all(prefetch.map((task, index) => router.devtools.trackDataRequest(
|
|
1206
|
+
"loader",
|
|
1207
|
+
`${to.fullPath}#prefetch-${index + 1}`,
|
|
1208
|
+
() => task({ route: to, client }),
|
|
1209
|
+
{ route: to.fullPath, trigger: "resource" }
|
|
1210
|
+
)));
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
__name(resourceRouterPlugin, "resourceRouterPlugin");
|
|
1216
|
+
function readPrefetch(route) {
|
|
1217
|
+
const value = route.meta.prefetch;
|
|
1218
|
+
if (value === void 0) return [];
|
|
1219
|
+
if (typeof value === "function") return [value];
|
|
1220
|
+
if (!Array.isArray(value) || value.some((task) => typeof task !== "function")) {
|
|
1221
|
+
throw new Error("Vobs Resource Router: route.meta.prefetch \u5FC5\u987B\u662F\u51FD\u6570\u6216\u51FD\u6570\u6570\u7EC4");
|
|
1222
|
+
}
|
|
1223
|
+
return value;
|
|
1224
|
+
}
|
|
1225
|
+
__name(readPrefetch, "readPrefetch");
|
|
1226
|
+
|
|
1227
|
+
export { RESOURCE_KEY, ResourceBoundary, createResourceClient, insertResourceBoundary, resource, resourcePlugin, resourceRouterPlugin, serializeResourceState, stableSerialize };
|
|
1228
|
+
//# sourceMappingURL=index.js.map
|
|
1229
|
+
//# sourceMappingURL=index.js.map
|