@vertz/ui 0.2.0 → 0.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/README.md +339 -857
- package/dist/css/public.d.ts +24 -27
- package/dist/css/public.js +5 -1
- package/dist/form/public.d.ts +94 -38
- package/dist/form/public.js +5 -3
- package/dist/index.d.ts +754 -167
- package/dist/index.js +606 -84
- package/dist/internals.d.ts +192 -23
- package/dist/internals.js +151 -102
- package/dist/jsx-runtime/index.d.ts +44 -17
- package/dist/jsx-runtime/index.js +26 -7
- package/dist/query/public.d.ts +73 -7
- package/dist/query/public.js +12 -4
- package/dist/router/public.d.ts +199 -26
- package/dist/router/public.js +22 -7
- package/dist/shared/chunk-0xcmwgdb.js +288 -0
- package/dist/shared/{chunk-j8vzvne3.js → chunk-9e92w0wt.js} +4 -1
- package/dist/shared/chunk-g4rch80a.js +33 -0
- package/dist/shared/chunk-hh0dhmb4.js +528 -0
- package/dist/shared/{chunk-pgymxpn1.js → chunk-hrd0mft1.js} +136 -34
- package/dist/shared/chunk-jrtrk5z4.js +125 -0
- package/dist/shared/chunk-ka5ked7n.js +188 -0
- package/dist/shared/chunk-n91rwj2r.js +483 -0
- package/dist/shared/chunk-prj7nm08.js +67 -0
- package/dist/shared/chunk-q6cpe5k7.js +230 -0
- package/dist/shared/{chunk-f1ynwam4.js → chunk-qacth5ah.js} +162 -36
- package/dist/shared/chunk-ryb49346.js +374 -0
- package/dist/shared/chunk-v3yyf79g.js +48 -0
- package/dist/test/index.d.ts +67 -6
- package/dist/test/index.js +4 -3
- package/package.json +14 -9
- package/dist/shared/chunk-bp3v6s9j.js +0 -62
- package/dist/shared/chunk-d8h2eh8d.js +0 -141
- package/dist/shared/chunk-tsdpgmks.js +0 -98
- package/dist/shared/chunk-xd9d7q5p.js +0 -115
- package/dist/shared/chunk-zbbvx05f.js +0 -202
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
// src/hydrate/component-registry.ts
|
|
2
|
-
async function resolveComponent(registry, componentId) {
|
|
3
|
-
const loader = registry[componentId];
|
|
4
|
-
if (!loader) {
|
|
5
|
-
throw new TypeError(`[hydrate] Component "${componentId}" not found in registry`);
|
|
6
|
-
}
|
|
7
|
-
const mod = await loader();
|
|
8
|
-
return mod.default;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// src/hydrate/props-deserializer.ts
|
|
12
|
-
function deserializeProps(container) {
|
|
13
|
-
const script = container.querySelector('script[type="application/json"]');
|
|
14
|
-
if (!script || !script.textContent) {
|
|
15
|
-
return {};
|
|
16
|
-
}
|
|
17
|
-
try {
|
|
18
|
-
return JSON.parse(script.textContent);
|
|
19
|
-
} catch {
|
|
20
|
-
return {};
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// src/hydrate/strategies.ts
|
|
25
|
-
function eagerStrategy(el, hydrateFn) {
|
|
26
|
-
hydrateFn();
|
|
27
|
-
}
|
|
28
|
-
function lazyStrategy(el, hydrateFn) {
|
|
29
|
-
if (typeof IntersectionObserver === "undefined") {
|
|
30
|
-
hydrateFn();
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const observer = new IntersectionObserver((entries) => {
|
|
34
|
-
for (const entry of entries) {
|
|
35
|
-
if (entry.isIntersecting) {
|
|
36
|
-
observer.disconnect();
|
|
37
|
-
hydrateFn();
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}, { rootMargin: "200px" });
|
|
42
|
-
observer.observe(el);
|
|
43
|
-
}
|
|
44
|
-
function interactionStrategy(el, hydrateFn) {
|
|
45
|
-
const events = ["click", "focus", "pointerenter"];
|
|
46
|
-
function handler() {
|
|
47
|
-
for (const event of events) {
|
|
48
|
-
el.removeEventListener(event, handler);
|
|
49
|
-
}
|
|
50
|
-
hydrateFn();
|
|
51
|
-
}
|
|
52
|
-
for (const event of events) {
|
|
53
|
-
el.addEventListener(event, handler);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
function idleStrategy(el, hydrateFn) {
|
|
57
|
-
if (typeof requestIdleCallback !== "undefined") {
|
|
58
|
-
requestIdleCallback(() => hydrateFn());
|
|
59
|
-
} else {
|
|
60
|
-
setTimeout(hydrateFn, 0);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function mediaStrategy(query) {
|
|
64
|
-
return (el, hydrateFn) => {
|
|
65
|
-
const mql = window.matchMedia(query);
|
|
66
|
-
if (mql.matches) {
|
|
67
|
-
hydrateFn();
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
function onChange(event) {
|
|
71
|
-
if (event.matches) {
|
|
72
|
-
mql.removeEventListener("change", onChange);
|
|
73
|
-
hydrateFn();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
mql.addEventListener("change", onChange);
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function visibleStrategy(el, hydrateFn) {
|
|
80
|
-
if (typeof IntersectionObserver === "undefined") {
|
|
81
|
-
hydrateFn();
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const observer = new IntersectionObserver((entries) => {
|
|
85
|
-
for (const entry of entries) {
|
|
86
|
-
if (entry.isIntersecting) {
|
|
87
|
-
observer.disconnect();
|
|
88
|
-
hydrateFn();
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
observer.observe(el);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// src/hydrate/hydrate.ts
|
|
97
|
-
function hydrate(registry) {
|
|
98
|
-
const elements = document.querySelectorAll("[data-v-id]");
|
|
99
|
-
for (const el of elements) {
|
|
100
|
-
if (el.hasAttribute("data-v-hydrated"))
|
|
101
|
-
continue;
|
|
102
|
-
const componentId = el.getAttribute("data-v-id");
|
|
103
|
-
if (!componentId)
|
|
104
|
-
continue;
|
|
105
|
-
const strategy = el.getAttribute("hydrate") ?? "lazy";
|
|
106
|
-
const props = deserializeProps(el);
|
|
107
|
-
const doHydrate = () => {
|
|
108
|
-
resolveComponent(registry, componentId).then((component) => {
|
|
109
|
-
component(props, el);
|
|
110
|
-
el.setAttribute("data-v-hydrated", "");
|
|
111
|
-
}).catch((error) => {
|
|
112
|
-
console.error(`[hydrate] Failed to hydrate component "${componentId}":`, error);
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
switch (strategy) {
|
|
116
|
-
case "eager":
|
|
117
|
-
eagerStrategy(el, doHydrate);
|
|
118
|
-
break;
|
|
119
|
-
case "lazy":
|
|
120
|
-
lazyStrategy(el, doHydrate);
|
|
121
|
-
break;
|
|
122
|
-
case "interaction":
|
|
123
|
-
interactionStrategy(el, doHydrate);
|
|
124
|
-
break;
|
|
125
|
-
case "idle":
|
|
126
|
-
idleStrategy(el, doHydrate);
|
|
127
|
-
break;
|
|
128
|
-
case "media": {
|
|
129
|
-
const query = el.getAttribute("hydrate-media") ?? "";
|
|
130
|
-
mediaStrategy(query)(el, doHydrate);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
case "visible":
|
|
134
|
-
visibleStrategy(el, doHydrate);
|
|
135
|
-
break;
|
|
136
|
-
default:
|
|
137
|
-
lazyStrategy(el, doHydrate);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
export { resolveComponent, deserializeProps, eagerStrategy, lazyStrategy, interactionStrategy, idleStrategy, mediaStrategy, visibleStrategy, hydrate };
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
signal
|
|
3
|
-
} from "./chunk-pgymxpn1.js";
|
|
4
|
-
|
|
5
|
-
// src/form/form-data.ts
|
|
6
|
-
function formDataToObject(formData, options) {
|
|
7
|
-
const result = {};
|
|
8
|
-
const coerce = options?.coerce ?? false;
|
|
9
|
-
for (const [key, value] of formData.entries()) {
|
|
10
|
-
if (typeof value !== "string") {
|
|
11
|
-
continue;
|
|
12
|
-
}
|
|
13
|
-
result[key] = coerce ? coerceValue(value) : value;
|
|
14
|
-
}
|
|
15
|
-
return result;
|
|
16
|
-
}
|
|
17
|
-
function coerceValue(value) {
|
|
18
|
-
if (value === "true")
|
|
19
|
-
return true;
|
|
20
|
-
if (value === "false")
|
|
21
|
-
return false;
|
|
22
|
-
if (value !== "" && !Number.isNaN(Number(value))) {
|
|
23
|
-
return Number(value);
|
|
24
|
-
}
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// src/form/validation.ts
|
|
29
|
-
function validate(schema, data) {
|
|
30
|
-
try {
|
|
31
|
-
const parsed = schema.parse(data);
|
|
32
|
-
return { success: true, data: parsed, errors: {} };
|
|
33
|
-
} catch (err) {
|
|
34
|
-
if (err instanceof Error) {
|
|
35
|
-
const fieldErrors = err.fieldErrors;
|
|
36
|
-
if (fieldErrors && Object.keys(fieldErrors).length > 0) {
|
|
37
|
-
return { success: false, data: undefined, errors: fieldErrors };
|
|
38
|
-
}
|
|
39
|
-
return { success: false, data: undefined, errors: { _form: err.message } };
|
|
40
|
-
}
|
|
41
|
-
return { success: false, data: undefined, errors: { _form: "Validation failed" } };
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// src/form/form.ts
|
|
46
|
-
function form(sdkMethod, options) {
|
|
47
|
-
const submitting = signal(false);
|
|
48
|
-
const errors = signal({});
|
|
49
|
-
return {
|
|
50
|
-
attrs() {
|
|
51
|
-
return {
|
|
52
|
-
action: sdkMethod.url,
|
|
53
|
-
method: sdkMethod.method
|
|
54
|
-
};
|
|
55
|
-
},
|
|
56
|
-
submitting,
|
|
57
|
-
handleSubmit(callbacks) {
|
|
58
|
-
return async (formDataOrEvent) => {
|
|
59
|
-
let formData;
|
|
60
|
-
if (formDataOrEvent instanceof Event) {
|
|
61
|
-
formDataOrEvent.preventDefault();
|
|
62
|
-
const target = formDataOrEvent.target;
|
|
63
|
-
formData = new FormData(target);
|
|
64
|
-
} else {
|
|
65
|
-
formData = formDataOrEvent;
|
|
66
|
-
}
|
|
67
|
-
const data = formDataToObject(formData);
|
|
68
|
-
const result = validate(options.schema, data);
|
|
69
|
-
if (!result.success) {
|
|
70
|
-
errors.value = result.errors;
|
|
71
|
-
callbacks?.onError?.(result.errors);
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
errors.value = {};
|
|
75
|
-
submitting.value = true;
|
|
76
|
-
let response;
|
|
77
|
-
try {
|
|
78
|
-
response = await sdkMethod(result.data);
|
|
79
|
-
} catch (err) {
|
|
80
|
-
submitting.value = false;
|
|
81
|
-
const message = err instanceof Error ? err.message : "Submission failed";
|
|
82
|
-
const serverErrors = { _form: message };
|
|
83
|
-
errors.value = serverErrors;
|
|
84
|
-
callbacks?.onError?.(serverErrors);
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
submitting.value = false;
|
|
88
|
-
callbacks?.onSuccess?.(response);
|
|
89
|
-
};
|
|
90
|
-
},
|
|
91
|
-
error(field) {
|
|
92
|
-
const currentErrors = errors.value;
|
|
93
|
-
return currentErrors[field];
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export { formDataToObject, validate, form };
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeLoaders,
|
|
3
|
-
matchRoute
|
|
4
|
-
} from "./chunk-j8vzvne3.js";
|
|
5
|
-
import {
|
|
6
|
-
signal
|
|
7
|
-
} from "./chunk-pgymxpn1.js";
|
|
8
|
-
|
|
9
|
-
// src/router/navigate.ts
|
|
10
|
-
function createRouter(routes, initialUrl) {
|
|
11
|
-
const isSSR = typeof window === "undefined" || typeof globalThis.__SSR_URL__ !== "undefined";
|
|
12
|
-
let url;
|
|
13
|
-
if (initialUrl) {
|
|
14
|
-
url = initialUrl;
|
|
15
|
-
} else if (isSSR) {
|
|
16
|
-
url = globalThis.__SSR_URL__ || "/";
|
|
17
|
-
} else {
|
|
18
|
-
url = window.location.pathname + window.location.search;
|
|
19
|
-
}
|
|
20
|
-
const initialMatch = matchRoute(routes, url);
|
|
21
|
-
const current = signal(initialMatch);
|
|
22
|
-
const loaderData = signal([]);
|
|
23
|
-
const loaderError = signal(null);
|
|
24
|
-
const searchParams = signal(initialMatch?.search ?? {});
|
|
25
|
-
let navigationGen = 0;
|
|
26
|
-
let currentAbort = null;
|
|
27
|
-
if (initialMatch) {
|
|
28
|
-
const gen = ++navigationGen;
|
|
29
|
-
const abort = new AbortController;
|
|
30
|
-
currentAbort = abort;
|
|
31
|
-
runLoaders(initialMatch, gen, abort.signal).catch(() => {});
|
|
32
|
-
}
|
|
33
|
-
async function runLoaders(match, gen, abortSignal) {
|
|
34
|
-
try {
|
|
35
|
-
loaderError.value = null;
|
|
36
|
-
const results = await executeLoaders(match.matched, match.params, abortSignal);
|
|
37
|
-
if (gen === navigationGen) {
|
|
38
|
-
loaderData.value = results;
|
|
39
|
-
}
|
|
40
|
-
} catch (err) {
|
|
41
|
-
if (gen === navigationGen) {
|
|
42
|
-
loaderError.value = err instanceof Error ? err : new Error(String(err));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
async function applyNavigation(url2) {
|
|
47
|
-
if (currentAbort) {
|
|
48
|
-
currentAbort.abort();
|
|
49
|
-
}
|
|
50
|
-
const gen = ++navigationGen;
|
|
51
|
-
const abort = new AbortController;
|
|
52
|
-
currentAbort = abort;
|
|
53
|
-
const match = matchRoute(routes, url2);
|
|
54
|
-
current.value = match;
|
|
55
|
-
if (match) {
|
|
56
|
-
searchParams.value = match.search;
|
|
57
|
-
await runLoaders(match, gen, abort.signal);
|
|
58
|
-
} else {
|
|
59
|
-
searchParams.value = {};
|
|
60
|
-
if (gen === navigationGen) {
|
|
61
|
-
loaderData.value = [];
|
|
62
|
-
loaderError.value = null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async function navigate(url2, options) {
|
|
67
|
-
if (!isSSR) {
|
|
68
|
-
if (options?.replace) {
|
|
69
|
-
window.history.replaceState(null, "", url2);
|
|
70
|
-
} else {
|
|
71
|
-
window.history.pushState(null, "", url2);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
await applyNavigation(url2);
|
|
75
|
-
}
|
|
76
|
-
async function revalidate() {
|
|
77
|
-
const match = current.value;
|
|
78
|
-
if (match) {
|
|
79
|
-
if (currentAbort) {
|
|
80
|
-
currentAbort.abort();
|
|
81
|
-
}
|
|
82
|
-
const gen = ++navigationGen;
|
|
83
|
-
const abort = new AbortController;
|
|
84
|
-
currentAbort = abort;
|
|
85
|
-
await runLoaders(match, gen, abort.signal);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
let onPopState = null;
|
|
89
|
-
if (!isSSR) {
|
|
90
|
-
onPopState = () => {
|
|
91
|
-
const url2 = window.location.pathname + window.location.search;
|
|
92
|
-
applyNavigation(url2).catch(() => {});
|
|
93
|
-
};
|
|
94
|
-
window.addEventListener("popstate", onPopState);
|
|
95
|
-
}
|
|
96
|
-
function dispose() {
|
|
97
|
-
if (onPopState) {
|
|
98
|
-
window.removeEventListener("popstate", onPopState);
|
|
99
|
-
}
|
|
100
|
-
if (currentAbort) {
|
|
101
|
-
currentAbort.abort();
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
return {
|
|
105
|
-
current,
|
|
106
|
-
dispose,
|
|
107
|
-
loaderData,
|
|
108
|
-
loaderError,
|
|
109
|
-
navigate,
|
|
110
|
-
revalidate,
|
|
111
|
-
searchParams
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export { createRouter };
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
computed,
|
|
3
|
-
effect,
|
|
4
|
-
setReadValueCallback,
|
|
5
|
-
signal,
|
|
6
|
-
untrack
|
|
7
|
-
} from "./chunk-pgymxpn1.js";
|
|
8
|
-
|
|
9
|
-
// src/query/cache.ts
|
|
10
|
-
class MemoryCache {
|
|
11
|
-
_store = new Map;
|
|
12
|
-
get(key) {
|
|
13
|
-
return this._store.get(key);
|
|
14
|
-
}
|
|
15
|
-
set(key, value) {
|
|
16
|
-
this._store.set(key, value);
|
|
17
|
-
}
|
|
18
|
-
delete(key) {
|
|
19
|
-
this._store.delete(key);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// src/query/key-derivation.ts
|
|
24
|
-
function deriveKey(thunk) {
|
|
25
|
-
return `__q:${hashString(thunk.toString())}`;
|
|
26
|
-
}
|
|
27
|
-
function hashString(str) {
|
|
28
|
-
let hash = 5381;
|
|
29
|
-
for (let i = 0;i < str.length; i++) {
|
|
30
|
-
hash = hash * 33 ^ str.charCodeAt(i);
|
|
31
|
-
}
|
|
32
|
-
return (hash >>> 0).toString(36);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// src/query/query.ts
|
|
36
|
-
var defaultCache = new MemoryCache;
|
|
37
|
-
var inflight = new Map;
|
|
38
|
-
function query(thunk, options = {}) {
|
|
39
|
-
const {
|
|
40
|
-
initialData,
|
|
41
|
-
debounce: debounceMs,
|
|
42
|
-
enabled = true,
|
|
43
|
-
key: customKey,
|
|
44
|
-
cache = defaultCache
|
|
45
|
-
} = options;
|
|
46
|
-
const baseKey = deriveKey(thunk);
|
|
47
|
-
const depHashSignal = signal("");
|
|
48
|
-
const cacheKeyComputed = computed(() => {
|
|
49
|
-
const dh = depHashSignal.value;
|
|
50
|
-
return customKey ?? (dh ? `${baseKey}:${dh}` : `${baseKey}:init`);
|
|
51
|
-
});
|
|
52
|
-
function getCacheKey() {
|
|
53
|
-
return cacheKeyComputed.value;
|
|
54
|
-
}
|
|
55
|
-
function callThunkWithCapture() {
|
|
56
|
-
const captured = [];
|
|
57
|
-
const prevCb = setReadValueCallback((v) => captured.push(v));
|
|
58
|
-
let promise;
|
|
59
|
-
try {
|
|
60
|
-
promise = thunk();
|
|
61
|
-
} finally {
|
|
62
|
-
setReadValueCallback(prevCb);
|
|
63
|
-
}
|
|
64
|
-
const serialized = captured.map((v) => JSON.stringify(v)).join("|");
|
|
65
|
-
untrack(() => {
|
|
66
|
-
depHashSignal.value = hashString(serialized);
|
|
67
|
-
});
|
|
68
|
-
return promise;
|
|
69
|
-
}
|
|
70
|
-
const data = signal(initialData);
|
|
71
|
-
const loading = signal(initialData === undefined && enabled);
|
|
72
|
-
const error = signal(undefined);
|
|
73
|
-
if (initialData !== undefined) {
|
|
74
|
-
cache.set(getCacheKey(), initialData);
|
|
75
|
-
}
|
|
76
|
-
let fetchId = 0;
|
|
77
|
-
let debounceTimer;
|
|
78
|
-
const inflightKeys = new Set;
|
|
79
|
-
const refetchTrigger = signal(0);
|
|
80
|
-
function handleFetchPromise(promise, id, key) {
|
|
81
|
-
promise.then((result) => {
|
|
82
|
-
inflight.delete(key);
|
|
83
|
-
inflightKeys.delete(key);
|
|
84
|
-
if (id !== fetchId)
|
|
85
|
-
return;
|
|
86
|
-
cache.set(key, result);
|
|
87
|
-
data.value = result;
|
|
88
|
-
loading.value = false;
|
|
89
|
-
}, (err) => {
|
|
90
|
-
inflight.delete(key);
|
|
91
|
-
inflightKeys.delete(key);
|
|
92
|
-
if (id !== fetchId)
|
|
93
|
-
return;
|
|
94
|
-
error.value = err;
|
|
95
|
-
loading.value = false;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
function startFetch(fetchPromise, key) {
|
|
99
|
-
const id = ++fetchId;
|
|
100
|
-
untrack(() => {
|
|
101
|
-
loading.value = true;
|
|
102
|
-
error.value = undefined;
|
|
103
|
-
});
|
|
104
|
-
const existing = inflight.get(key);
|
|
105
|
-
if (existing) {
|
|
106
|
-
handleFetchPromise(existing, id, key);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
inflight.set(key, fetchPromise);
|
|
110
|
-
inflightKeys.add(key);
|
|
111
|
-
handleFetchPromise(fetchPromise, id, key);
|
|
112
|
-
}
|
|
113
|
-
function refetch() {
|
|
114
|
-
const key = getCacheKey();
|
|
115
|
-
cache.delete(key);
|
|
116
|
-
inflight.delete(key);
|
|
117
|
-
refetchTrigger.value = refetchTrigger.peek() + 1;
|
|
118
|
-
}
|
|
119
|
-
let disposeFn;
|
|
120
|
-
if (enabled) {
|
|
121
|
-
let isFirst = true;
|
|
122
|
-
disposeFn = effect(() => {
|
|
123
|
-
refetchTrigger.value;
|
|
124
|
-
if (customKey) {
|
|
125
|
-
const existing = untrack(() => inflight.get(customKey));
|
|
126
|
-
if (existing) {
|
|
127
|
-
const id = ++fetchId;
|
|
128
|
-
untrack(() => {
|
|
129
|
-
loading.value = true;
|
|
130
|
-
error.value = undefined;
|
|
131
|
-
});
|
|
132
|
-
handleFetchPromise(existing, id, customKey);
|
|
133
|
-
isFirst = false;
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
const promise = callThunkWithCapture();
|
|
138
|
-
const key = untrack(() => getCacheKey());
|
|
139
|
-
if (!customKey) {
|
|
140
|
-
const existing = untrack(() => inflight.get(key));
|
|
141
|
-
if (existing) {
|
|
142
|
-
promise.catch(() => {});
|
|
143
|
-
const id = ++fetchId;
|
|
144
|
-
untrack(() => {
|
|
145
|
-
loading.value = true;
|
|
146
|
-
error.value = undefined;
|
|
147
|
-
});
|
|
148
|
-
handleFetchPromise(existing, id, key);
|
|
149
|
-
isFirst = false;
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (!isFirst && !customKey) {
|
|
154
|
-
const cached = untrack(() => cache.get(key));
|
|
155
|
-
if (cached !== undefined) {
|
|
156
|
-
promise.catch(() => {});
|
|
157
|
-
untrack(() => {
|
|
158
|
-
data.value = cached;
|
|
159
|
-
loading.value = false;
|
|
160
|
-
error.value = undefined;
|
|
161
|
-
});
|
|
162
|
-
isFirst = false;
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
if (isFirst && initialData !== undefined) {
|
|
167
|
-
promise.catch(() => {});
|
|
168
|
-
isFirst = false;
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
isFirst = false;
|
|
172
|
-
if (debounceMs !== undefined && debounceMs > 0) {
|
|
173
|
-
clearTimeout(debounceTimer);
|
|
174
|
-
promise.catch(() => {});
|
|
175
|
-
debounceTimer = setTimeout(() => {
|
|
176
|
-
startFetch(promise, key);
|
|
177
|
-
}, debounceMs);
|
|
178
|
-
} else {
|
|
179
|
-
startFetch(promise, key);
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
function dispose() {
|
|
184
|
-
disposeFn?.();
|
|
185
|
-
clearTimeout(debounceTimer);
|
|
186
|
-
fetchId++;
|
|
187
|
-
for (const key of inflightKeys) {
|
|
188
|
-
inflight.delete(key);
|
|
189
|
-
}
|
|
190
|
-
inflightKeys.clear();
|
|
191
|
-
}
|
|
192
|
-
return {
|
|
193
|
-
data,
|
|
194
|
-
loading,
|
|
195
|
-
error,
|
|
196
|
-
refetch,
|
|
197
|
-
revalidate: refetch,
|
|
198
|
-
dispose
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export { MemoryCache, deriveKey, query };
|