@vielzeug/sourcerer 1.0.6 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_dev.cjs +2 -0
- package/dist/_dev.cjs.map +1 -0
- package/dist/_dev.d.ts +2 -0
- package/dist/_dev.d.ts.map +1 -0
- package/dist/_dev.js +12 -0
- package/dist/_dev.js.map +1 -0
- package/dist/_utils.cjs +1 -1
- package/dist/_utils.cjs.map +1 -1
- package/dist/_utils.d.ts +20 -0
- package/dist/_utils.d.ts.map +1 -1
- package/dist/_utils.js +16 -3
- package/dist/_utils.js.map +1 -1
- package/dist/codecs.cjs +1 -1
- package/dist/codecs.cjs.map +1 -1
- package/dist/codecs.d.ts +1 -1
- package/dist/codecs.d.ts.map +1 -1
- package/dist/codecs.js +21 -19
- package/dist/codecs.js.map +1 -1
- package/dist/core.cjs +1 -1
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.ts +25 -1
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +1 -1
- package/dist/core.js.map +1 -1
- package/dist/cursorSource.cjs +1 -1
- package/dist/cursorSource.cjs.map +1 -1
- package/dist/cursorSource.js +69 -69
- package/dist/cursorSource.js.map +1 -1
- package/dist/derive.cjs +1 -1
- package/dist/derive.cjs.map +1 -1
- package/dist/derive.d.ts +1 -0
- package/dist/derive.d.ts.map +1 -1
- package/dist/derive.js +2 -4
- package/dist/derive.js.map +1 -1
- package/dist/devtools.cjs +2 -0
- package/dist/devtools.cjs.map +1 -0
- package/dist/devtools.d.ts +52 -0
- package/dist/devtools.d.ts.map +1 -0
- package/dist/devtools.js +20 -0
- package/dist/devtools.js.map +1 -0
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/fetchManager.cjs.map +1 -1
- package/dist/fetchManager.d.ts +13 -0
- package/dist/fetchManager.d.ts.map +1 -1
- package/dist/fetchManager.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -14
- package/dist/infiniteSource.cjs +1 -1
- package/dist/infiniteSource.cjs.map +1 -1
- package/dist/infiniteSource.js +62 -62
- package/dist/infiniteSource.js.map +1 -1
- package/dist/localSource.cjs +1 -1
- package/dist/localSource.cjs.map +1 -1
- package/dist/localSource.d.ts.map +1 -1
- package/dist/localSource.js +69 -79
- package/dist/localSource.js.map +1 -1
- package/dist/merge.cjs +1 -1
- package/dist/merge.cjs.map +1 -1
- package/dist/merge.d.ts +6 -1
- package/dist/merge.d.ts.map +1 -1
- package/dist/merge.js +8 -1
- package/dist/merge.js.map +1 -1
- package/dist/remoteSource.cjs +1 -1
- package/dist/remoteSource.cjs.map +1 -1
- package/dist/remoteSource.d.ts.map +1 -1
- package/dist/remoteSource.js +94 -94
- package/dist/remoteSource.js.map +1 -1
- package/dist/sourcerer.cjs +1 -1
- package/dist/sourcerer.cjs.map +1 -1
- package/dist/sourcerer.iife.js +1 -1
- package/dist/sourcerer.iife.js.map +1 -1
- package/dist/sourcerer.js +1 -1
- package/dist/sourcerer.js.map +1 -1
- package/dist/types.d.ts +14 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -1
- package/dist/applyQuery.cjs +0 -2
- package/dist/applyQuery.cjs.map +0 -1
- package/dist/applyQuery.d.ts +0 -20
- package/dist/applyQuery.d.ts.map +0 -1
- package/dist/applyQuery.js +0 -8
- package/dist/applyQuery.js.map +0 -1
package/dist/remoteSource.js
CHANGED
|
@@ -1,165 +1,165 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { createAsyncSearchCoordinator as
|
|
4
|
-
import { createAsyncSource as
|
|
5
|
-
import { clampPage as
|
|
1
|
+
import { clampPositiveInt as e, defaultKeyOf as t, extractError as n, retry as r } from "./_utils.js";
|
|
2
|
+
import { SourcererError as i } from "./errors.js";
|
|
3
|
+
import { createAsyncSearchCoordinator as a } from "./asyncSearch.js";
|
|
4
|
+
import { createAsyncSource as o } from "./asyncSource.js";
|
|
5
|
+
import { clampPage as s, createMeta as c, pageCount as l } from "./pagination.js";
|
|
6
6
|
//#region src/remoteSource.ts
|
|
7
|
-
function
|
|
8
|
-
let
|
|
9
|
-
|
|
10
|
-
let
|
|
7
|
+
function u(u) {
|
|
8
|
+
let d = u.queryKey ?? t, f = u.staleTime ?? 0, p = e(u.limit ?? 20, "createRemoteSource", "limit"), m = 1, h = "", g = u.filter, _ = u.sort, v = [], y = 0, b = null, x = 0, S = "", C = null;
|
|
9
|
+
u.snapshot && (v = u.snapshot.items, y = u.snapshot.total, u.snapshot.page !== void 0 && (m = u.snapshot.page), u.snapshot.search && (h = u.snapshot.search), x = Date.now());
|
|
10
|
+
let w = [], T = c({
|
|
11
11
|
error: null,
|
|
12
12
|
isLoading: !1,
|
|
13
13
|
isSearchPending: !1,
|
|
14
14
|
pageNumber: 1,
|
|
15
|
-
pageSize:
|
|
15
|
+
pageSize: p,
|
|
16
16
|
totalItems: 0
|
|
17
|
-
}),
|
|
18
|
-
let e =
|
|
19
|
-
|
|
20
|
-
error:
|
|
21
|
-
isLoading:
|
|
22
|
-
isSearchPending:
|
|
17
|
+
}), E = () => {
|
|
18
|
+
let e = l(y, p), t = s(m, e);
|
|
19
|
+
w = v, T = c({
|
|
20
|
+
error: b,
|
|
21
|
+
isLoading: D.pendingCount() > 0,
|
|
22
|
+
isSearchPending: D.core.isScheduled,
|
|
23
23
|
pageNumber: t,
|
|
24
|
-
pageSize:
|
|
25
|
-
totalItems:
|
|
24
|
+
pageSize: p,
|
|
25
|
+
totalItems: y
|
|
26
26
|
});
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
},
|
|
34
|
-
...
|
|
35
|
-
...
|
|
36
|
-
...
|
|
37
|
-
limit:
|
|
38
|
-
page:
|
|
39
|
-
}),
|
|
40
|
-
let
|
|
41
|
-
return
|
|
27
|
+
}, D = o(u, d, E), { autoFetch: O, debounceMs: k, retryAttempts: A, retryDelay: j } = D;
|
|
28
|
+
E();
|
|
29
|
+
let M = () => {
|
|
30
|
+
D.disposed || D.core.notify();
|
|
31
|
+
}, N = a(D.core, M), P = (e) => {
|
|
32
|
+
C?.active && (C.active = !1, C = null), v = e.items, y = e.total, m = s(m, l(y, p));
|
|
33
|
+
}, F = () => ({
|
|
34
|
+
...g !== void 0 && { filter: g },
|
|
35
|
+
..._ !== void 0 && { sort: _ },
|
|
36
|
+
...h && { search: h },
|
|
37
|
+
limit: p,
|
|
38
|
+
page: m
|
|
39
|
+
}), I = (e) => {
|
|
40
|
+
let t = d(e);
|
|
41
|
+
return f > 0 && t === S && y > 0 && Date.now() - x < f && !C?.active ? Promise.resolve() : (b = null, D.fetch(e, async (e, a, o) => {
|
|
42
42
|
let s = Date.now();
|
|
43
43
|
try {
|
|
44
|
-
let
|
|
45
|
-
delay:
|
|
44
|
+
let n = await r((t) => u.fetch(e, t), {
|
|
45
|
+
delay: j,
|
|
46
46
|
signal: a,
|
|
47
|
-
times:
|
|
47
|
+
times: A + 1
|
|
48
48
|
});
|
|
49
|
-
o() && (
|
|
49
|
+
o() && (P(n), b = null, S = t, x = Date.now(), u.onFetch?.({
|
|
50
50
|
durationMs: Date.now() - s,
|
|
51
|
-
query:
|
|
51
|
+
query: e,
|
|
52
52
|
status: "success"
|
|
53
53
|
}));
|
|
54
|
-
} catch (
|
|
54
|
+
} catch (t) {
|
|
55
55
|
if (a.aborted) return;
|
|
56
|
-
o() && (
|
|
57
|
-
cause:
|
|
56
|
+
o() && (C?.active ? (C.active = !1, v = C.prevItems, y = C.prevTotal, C = null) : (v = [], y = 0), b = new i(n(t), {
|
|
57
|
+
cause: t,
|
|
58
58
|
context: {
|
|
59
59
|
kind: "remote",
|
|
60
|
-
limit:
|
|
61
|
-
page:
|
|
62
|
-
...
|
|
60
|
+
limit: e.limit,
|
|
61
|
+
page: e.page,
|
|
62
|
+
...e.search && { search: e.search }
|
|
63
63
|
}
|
|
64
|
-
}),
|
|
64
|
+
}), u.onFetch?.({
|
|
65
65
|
durationMs: Date.now() - s,
|
|
66
|
-
error:
|
|
67
|
-
query:
|
|
66
|
+
error: b,
|
|
67
|
+
query: e,
|
|
68
68
|
status: "error"
|
|
69
69
|
}));
|
|
70
70
|
}
|
|
71
71
|
}, () => {
|
|
72
|
-
|
|
72
|
+
M(), N.settleIfIdle(D.pendingCount());
|
|
73
73
|
}));
|
|
74
|
-
},
|
|
75
|
-
return
|
|
74
|
+
}, L = () => I(F());
|
|
75
|
+
return O && L(), D.startRefreshInterval(() => void L()), {
|
|
76
76
|
get current() {
|
|
77
|
-
return
|
|
77
|
+
return w;
|
|
78
78
|
},
|
|
79
79
|
get disposalSignal() {
|
|
80
|
-
return
|
|
80
|
+
return D.disposalSignal;
|
|
81
81
|
},
|
|
82
82
|
dispose: () => {
|
|
83
|
-
|
|
83
|
+
N.cancel(), N.dispose(), D.dispose();
|
|
84
84
|
},
|
|
85
85
|
get disposed() {
|
|
86
|
-
return
|
|
86
|
+
return D.disposed;
|
|
87
87
|
},
|
|
88
|
-
goTo(
|
|
89
|
-
let
|
|
90
|
-
return
|
|
88
|
+
goTo(t) {
|
|
89
|
+
let n = y > 0 ? s(t, l(y, p)) : e(t, "source.goTo", "target");
|
|
90
|
+
return n === m ? Promise.resolve() : (m = n, L());
|
|
91
91
|
},
|
|
92
92
|
goToLast() {
|
|
93
|
-
let e =
|
|
94
|
-
return
|
|
93
|
+
let e = l(y, p);
|
|
94
|
+
return m === e ? Promise.resolve() : (m = e, L());
|
|
95
95
|
},
|
|
96
96
|
get meta() {
|
|
97
|
-
return
|
|
97
|
+
return T;
|
|
98
98
|
},
|
|
99
99
|
next() {
|
|
100
|
-
let e =
|
|
101
|
-
return
|
|
100
|
+
let e = l(y, p);
|
|
101
|
+
return m >= e ? Promise.resolve() : (m++, L());
|
|
102
102
|
},
|
|
103
|
-
optimisticUpdate(
|
|
104
|
-
if (
|
|
105
|
-
let
|
|
106
|
-
|
|
103
|
+
optimisticUpdate(e, t) {
|
|
104
|
+
if (C?.active) throw new i("An optimistic update is already active. Rollback the previous update before starting another.");
|
|
105
|
+
let n = v, r = y;
|
|
106
|
+
C = {
|
|
107
107
|
active: !0,
|
|
108
|
-
prevItems:
|
|
109
|
-
prevTotal:
|
|
108
|
+
prevItems: n,
|
|
109
|
+
prevTotal: r
|
|
110
110
|
};
|
|
111
111
|
try {
|
|
112
|
-
|
|
112
|
+
v = e(v);
|
|
113
113
|
} catch (e) {
|
|
114
|
-
throw
|
|
114
|
+
throw C = null, e;
|
|
115
115
|
}
|
|
116
|
-
return
|
|
117
|
-
|
|
116
|
+
return y = t?.total ?? y, M(), () => {
|
|
117
|
+
C?.active && (C.active = !1, v = n, y = r, C = null, M());
|
|
118
118
|
};
|
|
119
119
|
},
|
|
120
|
-
patch(
|
|
121
|
-
let
|
|
122
|
-
if (
|
|
123
|
-
let
|
|
124
|
-
|
|
120
|
+
patch(t) {
|
|
121
|
+
let n = !1;
|
|
122
|
+
if (t.limit !== void 0) {
|
|
123
|
+
let r = e(t.limit, "source.patch", "limit");
|
|
124
|
+
r !== p && (p = r, n = !0);
|
|
125
125
|
}
|
|
126
|
-
if ("filter" in
|
|
127
|
-
let
|
|
128
|
-
|
|
126
|
+
if ("filter" in t && (g = t.filter, n = !0), "sort" in t && (_ = t.sort, n = !0), "search" in t && (t.search !== h || D.core.isScheduled) && (h = t.search ?? "", n = !0), t.page !== void 0) {
|
|
127
|
+
let r = y > 0 ? s(t.page, l(y, p)) : e(t.page, "source.patch", "page");
|
|
128
|
+
r !== m && (m = r, n = !0);
|
|
129
129
|
}
|
|
130
|
-
return
|
|
130
|
+
return n ? (N.cancel(), (t.limit !== void 0 || "filter" in t || "sort" in t || "search" in t) && t.page === void 0 && (m = 1), L()) : Promise.resolve();
|
|
131
131
|
},
|
|
132
132
|
prev() {
|
|
133
|
-
return
|
|
133
|
+
return m <= 1 ? Promise.resolve() : (m--, L());
|
|
134
134
|
},
|
|
135
135
|
get query() {
|
|
136
136
|
return {
|
|
137
|
-
...
|
|
138
|
-
...
|
|
139
|
-
...
|
|
140
|
-
limit:
|
|
141
|
-
page:
|
|
137
|
+
...g !== void 0 && { filter: g },
|
|
138
|
+
..._ !== void 0 && { sort: _ },
|
|
139
|
+
...h && { search: h },
|
|
140
|
+
limit: p,
|
|
141
|
+
page: m
|
|
142
142
|
};
|
|
143
143
|
},
|
|
144
144
|
ready(e) {
|
|
145
|
-
return
|
|
145
|
+
return D.ready(e);
|
|
146
146
|
},
|
|
147
147
|
refresh() {
|
|
148
|
-
return
|
|
148
|
+
return L();
|
|
149
149
|
},
|
|
150
150
|
reset() {
|
|
151
|
-
return
|
|
151
|
+
return N.cancel(), h = "", m = 1, g = u.filter, _ = u.sort, L();
|
|
152
152
|
},
|
|
153
153
|
search(e, t) {
|
|
154
|
-
return t?.immediate ? e ===
|
|
154
|
+
return t?.immediate ? e === h && !D.core.isScheduled ? Promise.resolve() : (N.cancel(), h = e, m = 1, L()) : e === h ? Promise.resolve() : (h = e, m = 1, N.schedule(() => void L(), k));
|
|
155
155
|
},
|
|
156
|
-
subscribe: (e) =>
|
|
156
|
+
subscribe: (e) => D.core.subscribe(e),
|
|
157
157
|
[Symbol.dispose]: () => {
|
|
158
|
-
|
|
158
|
+
N.cancel(), N.dispose(), D.dispose();
|
|
159
159
|
}
|
|
160
160
|
};
|
|
161
161
|
}
|
|
162
162
|
//#endregion
|
|
163
|
-
export {
|
|
163
|
+
export { u as createRemoteSource };
|
|
164
164
|
|
|
165
165
|
//# sourceMappingURL=remoteSource.js.map
|
package/dist/remoteSource.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteSource.js","names":[],"sources":["../src/remoteSource.ts"],"sourcesContent":["import type { RemoteConfig, RemoteSource, RemoteSourceQuery, SearchOptions } from './types';\n\nimport { defaultKeyOf, extractError, retry } from './_utils';\nimport { createAsyncSearchCoordinator } from './asyncSearch';\nimport { createAsyncSource } from './asyncSource';\nimport { SourcererError } from './errors';\nimport { clampPage, createMeta, pageCount } from './pagination';\n\n/** Creates a remote page-based source that fetches data from a network endpoint. */\nexport function createRemoteSource<T, TFilter = unknown, TSort = unknown>(\n cfg: RemoteConfig<T, TFilter, TSort>,\n): RemoteSource<T, TFilter, TSort> {\n const keyOf = cfg.queryKey ?? defaultKeyOf;\n\n // ── Config defaults ─────────────────────────────────────────────────────────\n const staleTimeMs = cfg.staleTime ?? 0;\n\n // ── Mutable state ───────────────────────────────────────────────────────────\n let limit = Math.max(1, Math.trunc(cfg.limit ?? 20));\n let page = 1;\n let search = '';\n let filter: TFilter | undefined = cfg.filter;\n let sort: TSort | undefined = cfg.sort;\n let items: readonly T[] = [];\n let total = 0;\n let error: SourcererError | null = null;\n let lastFetchTime = 0;\n let lastFetchKey = '';\n\n // Optimistic update state.\n let optimistic: { active: boolean; prevItems: readonly T[]; prevTotal: number } | null = null;\n\n // ── Snapshot pre-population ─────────────────────────────────────────────────\n if (cfg.snapshot) {\n items = cfg.snapshot.items;\n total = cfg.snapshot.total;\n\n if (cfg.snapshot.page !== undefined) page = cfg.snapshot.page;\n\n if (cfg.snapshot.search) search = cfg.snapshot.search;\n\n lastFetchTime = Date.now();\n }\n\n // ── Cached accessors ────────────────────────────────────────────────────────\n let cachedCurrent: readonly T[] = [];\n let cachedMeta = createMeta({\n error: null,\n isLoading: false,\n isSearchPending: false,\n pageNumber: 1,\n pageSize: limit,\n totalItems: 0,\n });\n\n const refreshMeta = () => {\n const pages = pageCount(total, limit);\n const safePage = clampPage(page, pages);\n\n // items is already the current page from the server — no local slicing needed.\n cachedCurrent = items;\n cachedMeta = createMeta({\n error,\n isLoading: base.pendingCount() > 0,\n isSearchPending: base.core.isScheduled,\n pageNumber: safePage,\n pageSize: limit,\n totalItems: total,\n });\n };\n\n // onBeforeNotify ensures refreshMeta() runs before any subscriber observes the new state,\n // eliminating the need for a parallel listeners Set.\n const base = createAsyncSource<RemoteSourceQuery<TFilter, TSort>>(cfg, keyOf, refreshMeta);\n const { autoFetch, debounceMs, retryAttempts, retryDelay } = base;\n\n // Initialise cache before first fetch.\n refreshMeta();\n\n const notifyListeners = () => {\n if (base.disposed) return;\n\n base.core.notify();\n };\n const searchCoordinator = createAsyncSearchCoordinator(base.core, notifyListeners);\n\n // ── Assign result ───────────────────────────────────────────────────────────\n const assign = (result: Readonly<{ items: readonly T[]; total: number }>) => {\n if (optimistic?.active) {\n optimistic.active = false;\n optimistic = null;\n }\n\n items = result.items;\n total = result.total;\n page = clampPage(page, pageCount(total, limit));\n };\n\n // ── Core fetch ──────────────────────────────────────────────────────────────\n const toRemoteQuery = (): RemoteSourceQuery<TFilter, TSort> => ({\n ...(filter !== undefined && { filter }),\n ...(sort !== undefined && { sort }),\n ...(search && { search }),\n limit,\n page,\n });\n\n const fetchQuery = (q: RemoteSourceQuery<TFilter, TSort>): Promise<void> => {\n const key = keyOf(q);\n\n if (\n staleTimeMs > 0 &&\n key === lastFetchKey &&\n total > 0 &&\n Date.now() - lastFetchTime < staleTimeMs &&\n !optimistic?.active\n ) {\n return Promise.resolve();\n }\n\n error = null;\n\n return base.fetch(\n q,\n async (q: RemoteSourceQuery<TFilter, TSort>, signal, isLatest) => {\n const startTime = Date.now();\n\n try {\n const result = await retry((sig) => cfg.fetch(q, sig!), {\n delay: retryDelay,\n signal,\n times: retryAttempts + 1,\n });\n\n if (isLatest()) {\n assign(result);\n error = null;\n lastFetchKey = key;\n lastFetchTime = Date.now();\n cfg.onFetch?.({ durationMs: Date.now() - startTime, query: q, status: 'success' });\n }\n } catch (reason: unknown) {\n if (signal.aborted) return;\n\n if (isLatest()) {\n if (optimistic?.active) {\n optimistic.active = false;\n items = optimistic.prevItems;\n total = optimistic.prevTotal;\n optimistic = null;\n } else {\n items = [];\n total = 0;\n }\n\n error = new SourcererError(extractError(reason), {\n cause: reason,\n context: { kind: 'remote', limit: q.limit, page: q.page, ...(q.search && { search: q.search }) },\n });\n cfg.onFetch?.({ durationMs: Date.now() - startTime, error, query: q, status: 'error' });\n }\n }\n },\n () => {\n notifyListeners();\n\n searchCoordinator.settleIfIdle(base.pendingCount());\n },\n );\n };\n\n const doUpdate = () => fetchQuery(toRemoteQuery());\n\n // ── Auto-fetch + refresh interval ───────────────────────────────────────────\n if (autoFetch) void doUpdate();\n\n base.startRefreshInterval(() => void doUpdate());\n\n // ── Public API ──────────────────────────────────────────────────────────────\n return {\n get current() {\n return cachedCurrent;\n },\n\n get disposalSignal() {\n return base.disposalSignal;\n },\n\n dispose: () => {\n searchCoordinator.cancel();\n searchCoordinator.dispose();\n base.dispose();\n },\n\n get disposed() {\n return base.disposed;\n },\n\n goTo(target) {\n const clamped = total > 0 ? clampPage(target, pageCount(total, limit)) : Math.max(1, Math.trunc(target));\n\n if (clamped === page) return Promise.resolve();\n\n page = clamped;\n\n return doUpdate();\n },\n\n goToLast() {\n const last = pageCount(total, limit);\n\n if (page === last) return Promise.resolve();\n\n page = last;\n\n return doUpdate();\n },\n\n get meta() {\n return cachedMeta;\n },\n\n next() {\n const pages = pageCount(total, limit);\n\n if (page >= pages) return Promise.resolve();\n\n page++;\n\n return doUpdate();\n },\n\n optimisticUpdate(mutator, options) {\n if (optimistic?.active) {\n throw new SourcererError(\n 'An optimistic update is already active. Rollback the previous update before starting another.',\n );\n }\n\n const prevItems = items;\n const prevTotal = total;\n\n optimistic = { active: true, prevItems, prevTotal };\n\n try {\n items = mutator(items);\n } catch (e: unknown) {\n optimistic = null;\n throw e;\n }\n\n total = options?.total ?? total;\n notifyListeners();\n\n return () => {\n if (optimistic?.active) {\n optimistic.active = false;\n items = prevItems;\n total = prevTotal;\n optimistic = null;\n notifyListeners();\n }\n };\n },\n\n patch(changes) {\n let changed = false;\n\n if (changes.limit !== undefined) {\n const next = Math.max(1, Math.trunc(changes.limit));\n\n if (next !== limit) {\n limit = next;\n changed = true;\n }\n }\n\n if ('filter' in changes) {\n filter = changes.filter;\n changed = true;\n }\n\n if ('sort' in changes) {\n sort = changes.sort;\n changed = true;\n }\n\n // `|| base.core.isScheduled` also catches patching in the same search text as an already-pending\n // debounced search() call — that still needs flushing, not silently dropping as a no-op.\n if ('search' in changes && (changes.search !== search || base.core.isScheduled)) {\n search = changes.search ?? '';\n changed = true;\n }\n\n if (changes.page !== undefined) {\n const next =\n total > 0 ? clampPage(changes.page, pageCount(total, limit)) : Math.max(1, Math.trunc(changes.page));\n\n if (next !== page) {\n page = next;\n changed = true;\n }\n }\n\n if (!changed) return Promise.resolve();\n\n // patch() is documented as a single atomic fetch — cancel any debounced search()\n // still pending so it doesn't fire a second, redundant fetch afterwards.\n searchCoordinator.cancel();\n\n // Reset to page 1 when non-page query fields changed without explicit page\n if (\n (changes.limit !== undefined || 'filter' in changes || 'sort' in changes || 'search' in changes) &&\n changes.page === undefined\n ) {\n page = 1;\n }\n\n return doUpdate();\n },\n\n prev() {\n if (page <= 1) return Promise.resolve();\n\n page--;\n\n return doUpdate();\n },\n\n get query() {\n return {\n ...(filter !== undefined && { filter }),\n ...(sort !== undefined && { sort }),\n ...(search && { search }),\n limit,\n page,\n };\n },\n\n ready(timeout) {\n return base.ready(timeout);\n },\n\n refresh() {\n return doUpdate();\n },\n\n reset() {\n searchCoordinator.cancel();\n search = '';\n page = 1;\n filter = cfg.filter;\n sort = cfg.sort;\n\n return doUpdate();\n },\n\n search(q, opts?: SearchOptions): Promise<void> {\n if (opts?.immediate) {\n // A pending debounced search for this same text still needs flushing —\n // `q === search` alone doesn't mean the fetch already happened.\n if (q === search && !base.core.isScheduled) return Promise.resolve();\n\n searchCoordinator.cancel();\n search = q;\n page = 1;\n\n return doUpdate();\n }\n\n if (q === search) return Promise.resolve();\n\n search = q;\n page = 1;\n\n return searchCoordinator.schedule(() => void doUpdate(), debounceMs);\n },\n\n subscribe: (listener) => base.core.subscribe(listener),\n\n [Symbol.dispose]: () => {\n searchCoordinator.cancel();\n searchCoordinator.dispose();\n base.dispose();\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"remoteSource.js","names":[],"sources":["../src/remoteSource.ts"],"sourcesContent":["import type { RemoteConfig, RemoteSource, RemoteSourceQuery, SearchOptions } from './types';\n\nimport { clampPositiveInt, defaultKeyOf, extractError, retry } from './_utils';\nimport { createAsyncSearchCoordinator } from './asyncSearch';\nimport { createAsyncSource } from './asyncSource';\nimport { SourcererError } from './errors';\nimport { clampPage, createMeta, pageCount } from './pagination';\n\n/** Creates a remote page-based source that fetches data from a network endpoint. */\nexport function createRemoteSource<T, TFilter = unknown, TSort = unknown>(\n cfg: RemoteConfig<T, TFilter, TSort>,\n): RemoteSource<T, TFilter, TSort> {\n const keyOf = cfg.queryKey ?? defaultKeyOf;\n\n // ── Config defaults ─────────────────────────────────────────────────────────\n const staleTimeMs = cfg.staleTime ?? 0;\n\n // ── Mutable state ───────────────────────────────────────────────────────────\n let limit = clampPositiveInt(cfg.limit ?? 20, 'createRemoteSource', 'limit');\n let page = 1;\n let search = '';\n let filter: TFilter | undefined = cfg.filter;\n let sort: TSort | undefined = cfg.sort;\n let items: readonly T[] = [];\n let total = 0;\n let error: SourcererError | null = null;\n let lastFetchTime = 0;\n let lastFetchKey = '';\n\n // Optimistic update state.\n let optimistic: { active: boolean; prevItems: readonly T[]; prevTotal: number } | null = null;\n\n // ── Snapshot pre-population ─────────────────────────────────────────────────\n if (cfg.snapshot) {\n items = cfg.snapshot.items;\n total = cfg.snapshot.total;\n\n if (cfg.snapshot.page !== undefined) page = cfg.snapshot.page;\n\n if (cfg.snapshot.search) search = cfg.snapshot.search;\n\n lastFetchTime = Date.now();\n }\n\n // ── Cached accessors ────────────────────────────────────────────────────────\n let cachedCurrent: readonly T[] = [];\n let cachedMeta = createMeta({\n error: null,\n isLoading: false,\n isSearchPending: false,\n pageNumber: 1,\n pageSize: limit,\n totalItems: 0,\n });\n\n const refreshMeta = () => {\n const pages = pageCount(total, limit);\n const safePage = clampPage(page, pages);\n\n // items is already the current page from the server — no local slicing needed.\n cachedCurrent = items;\n cachedMeta = createMeta({\n error,\n isLoading: base.pendingCount() > 0,\n isSearchPending: base.core.isScheduled,\n pageNumber: safePage,\n pageSize: limit,\n totalItems: total,\n });\n };\n\n // onBeforeNotify ensures refreshMeta() runs before any subscriber observes the new state,\n // eliminating the need for a parallel listeners Set.\n const base = createAsyncSource<RemoteSourceQuery<TFilter, TSort>>(cfg, keyOf, refreshMeta);\n const { autoFetch, debounceMs, retryAttempts, retryDelay } = base;\n\n // Initialise cache before first fetch.\n refreshMeta();\n\n const notifyListeners = () => {\n if (base.disposed) return;\n\n base.core.notify();\n };\n const searchCoordinator = createAsyncSearchCoordinator(base.core, notifyListeners);\n\n // ── Assign result ───────────────────────────────────────────────────────────\n const assign = (result: Readonly<{ items: readonly T[]; total: number }>) => {\n if (optimistic?.active) {\n optimistic.active = false;\n optimistic = null;\n }\n\n items = result.items;\n total = result.total;\n page = clampPage(page, pageCount(total, limit));\n };\n\n // ── Core fetch ──────────────────────────────────────────────────────────────\n const toRemoteQuery = (): RemoteSourceQuery<TFilter, TSort> => ({\n ...(filter !== undefined && { filter }),\n ...(sort !== undefined && { sort }),\n ...(search && { search }),\n limit,\n page,\n });\n\n const fetchQuery = (q: RemoteSourceQuery<TFilter, TSort>): Promise<void> => {\n const key = keyOf(q);\n\n if (\n staleTimeMs > 0 &&\n key === lastFetchKey &&\n total > 0 &&\n Date.now() - lastFetchTime < staleTimeMs &&\n !optimistic?.active\n ) {\n return Promise.resolve();\n }\n\n error = null;\n\n return base.fetch(\n q,\n async (q: RemoteSourceQuery<TFilter, TSort>, signal, isLatest) => {\n const startTime = Date.now();\n\n try {\n const result = await retry((sig) => cfg.fetch(q, sig!), {\n delay: retryDelay,\n signal,\n times: retryAttempts + 1,\n });\n\n if (isLatest()) {\n assign(result);\n error = null;\n lastFetchKey = key;\n lastFetchTime = Date.now();\n cfg.onFetch?.({ durationMs: Date.now() - startTime, query: q, status: 'success' });\n }\n } catch (reason: unknown) {\n if (signal.aborted) return;\n\n if (isLatest()) {\n if (optimistic?.active) {\n optimistic.active = false;\n items = optimistic.prevItems;\n total = optimistic.prevTotal;\n optimistic = null;\n } else {\n items = [];\n total = 0;\n }\n\n error = new SourcererError(extractError(reason), {\n cause: reason,\n context: { kind: 'remote', limit: q.limit, page: q.page, ...(q.search && { search: q.search }) },\n });\n cfg.onFetch?.({ durationMs: Date.now() - startTime, error, query: q, status: 'error' });\n }\n }\n },\n () => {\n notifyListeners();\n\n searchCoordinator.settleIfIdle(base.pendingCount());\n },\n );\n };\n\n const doUpdate = () => fetchQuery(toRemoteQuery());\n\n // ── Auto-fetch + refresh interval ───────────────────────────────────────────\n if (autoFetch) void doUpdate();\n\n base.startRefreshInterval(() => void doUpdate());\n\n // ── Public API ──────────────────────────────────────────────────────────────\n return {\n get current() {\n return cachedCurrent;\n },\n\n get disposalSignal() {\n return base.disposalSignal;\n },\n\n dispose: () => {\n searchCoordinator.cancel();\n searchCoordinator.dispose();\n base.dispose();\n },\n\n get disposed() {\n return base.disposed;\n },\n\n goTo(target) {\n const clamped =\n total > 0 ? clampPage(target, pageCount(total, limit)) : clampPositiveInt(target, 'source.goTo', 'target');\n\n if (clamped === page) return Promise.resolve();\n\n page = clamped;\n\n return doUpdate();\n },\n\n goToLast() {\n const last = pageCount(total, limit);\n\n if (page === last) return Promise.resolve();\n\n page = last;\n\n return doUpdate();\n },\n\n get meta() {\n return cachedMeta;\n },\n\n next() {\n const pages = pageCount(total, limit);\n\n if (page >= pages) return Promise.resolve();\n\n page++;\n\n return doUpdate();\n },\n\n optimisticUpdate(mutator, options) {\n if (optimistic?.active) {\n throw new SourcererError(\n 'An optimistic update is already active. Rollback the previous update before starting another.',\n );\n }\n\n const prevItems = items;\n const prevTotal = total;\n\n optimistic = { active: true, prevItems, prevTotal };\n\n try {\n items = mutator(items);\n } catch (e: unknown) {\n optimistic = null;\n throw e;\n }\n\n total = options?.total ?? total;\n notifyListeners();\n\n return () => {\n if (optimistic?.active) {\n optimistic.active = false;\n items = prevItems;\n total = prevTotal;\n optimistic = null;\n notifyListeners();\n }\n };\n },\n\n patch(changes) {\n let changed = false;\n\n if (changes.limit !== undefined) {\n const next = clampPositiveInt(changes.limit, 'source.patch', 'limit');\n\n if (next !== limit) {\n limit = next;\n changed = true;\n }\n }\n\n if ('filter' in changes) {\n filter = changes.filter;\n changed = true;\n }\n\n if ('sort' in changes) {\n sort = changes.sort;\n changed = true;\n }\n\n // `|| base.core.isScheduled` also catches patching in the same search text as an already-pending\n // debounced search() call — that still needs flushing, not silently dropping as a no-op.\n if ('search' in changes && (changes.search !== search || base.core.isScheduled)) {\n search = changes.search ?? '';\n changed = true;\n }\n\n if (changes.page !== undefined) {\n const next =\n total > 0\n ? clampPage(changes.page, pageCount(total, limit))\n : clampPositiveInt(changes.page, 'source.patch', 'page');\n\n if (next !== page) {\n page = next;\n changed = true;\n }\n }\n\n if (!changed) return Promise.resolve();\n\n // patch() is documented as a single atomic fetch — cancel any debounced search()\n // still pending so it doesn't fire a second, redundant fetch afterwards.\n searchCoordinator.cancel();\n\n // Reset to page 1 when non-page query fields changed without explicit page\n if (\n (changes.limit !== undefined || 'filter' in changes || 'sort' in changes || 'search' in changes) &&\n changes.page === undefined\n ) {\n page = 1;\n }\n\n return doUpdate();\n },\n\n prev() {\n if (page <= 1) return Promise.resolve();\n\n page--;\n\n return doUpdate();\n },\n\n get query() {\n return {\n ...(filter !== undefined && { filter }),\n ...(sort !== undefined && { sort }),\n ...(search && { search }),\n limit,\n page,\n };\n },\n\n ready(timeout) {\n return base.ready(timeout);\n },\n\n refresh() {\n return doUpdate();\n },\n\n reset() {\n searchCoordinator.cancel();\n search = '';\n page = 1;\n filter = cfg.filter;\n sort = cfg.sort;\n\n return doUpdate();\n },\n\n search(q, opts?: SearchOptions): Promise<void> {\n if (opts?.immediate) {\n // A pending debounced search for this same text still needs flushing —\n // `q === search` alone doesn't mean the fetch already happened.\n if (q === search && !base.core.isScheduled) return Promise.resolve();\n\n searchCoordinator.cancel();\n search = q;\n page = 1;\n\n return doUpdate();\n }\n\n if (q === search) return Promise.resolve();\n\n search = q;\n page = 1;\n\n return searchCoordinator.schedule(() => void doUpdate(), debounceMs);\n },\n\n subscribe: (listener) => base.core.subscribe(listener),\n\n [Symbol.dispose]: () => {\n searchCoordinator.cancel();\n searchCoordinator.dispose();\n base.dispose();\n },\n };\n}\n"],"mappings":";;;;;;AASA,SAAgB,EACd,GACiC;CACjC,IAAM,IAAQ,EAAI,YAAY,GAGxB,IAAc,EAAI,aAAa,GAGjC,IAAQ,EAAiB,EAAI,SAAS,IAAI,sBAAsB,OAAO,GACvE,IAAO,GACP,IAAS,IACT,IAA8B,EAAI,QAClC,IAA0B,EAAI,MAC9B,IAAsB,CAAC,GACvB,IAAQ,GACR,IAA+B,MAC/B,IAAgB,GAChB,IAAe,IAGf,IAAqF;CAGzF,AAAI,EAAI,aACN,IAAQ,EAAI,SAAS,OACrB,IAAQ,EAAI,SAAS,OAEjB,EAAI,SAAS,SAAS,KAAA,MAAW,IAAO,EAAI,SAAS,OAErD,EAAI,SAAS,WAAQ,IAAS,EAAI,SAAS,SAE/C,IAAgB,KAAK,IAAI;CAI3B,IAAI,IAA8B,CAAC,GAC/B,IAAa,EAAW;EAC1B,OAAO;EACP,WAAW;EACX,iBAAiB;EACjB,YAAY;EACZ,UAAU;EACV,YAAY;CACd,CAAC,GAEK,UAAoB;EACxB,IAAM,IAAQ,EAAU,GAAO,CAAK,GAC9B,IAAW,EAAU,GAAM,CAAK;EAItC,AADA,IAAgB,GAChB,IAAa,EAAW;GACtB;GACA,WAAW,EAAK,aAAa,IAAI;GACjC,iBAAiB,EAAK,KAAK;GAC3B,YAAY;GACZ,UAAU;GACV,YAAY;EACd,CAAC;CACH,GAIM,IAAO,EAAqD,GAAK,GAAO,CAAW,GACnF,EAAE,cAAW,eAAY,kBAAe,kBAAe;CAG7D,EAAY;CAEZ,IAAM,UAAwB;EACxB,EAAK,YAET,EAAK,KAAK,OAAO;CACnB,GACM,IAAoB,EAA6B,EAAK,MAAM,CAAe,GAG3E,KAAU,MAA6D;EAQ3E,AAPI,GAAY,WACd,EAAW,SAAS,IACpB,IAAa,OAGf,IAAQ,EAAO,OACf,IAAQ,EAAO,OACf,IAAO,EAAU,GAAM,EAAU,GAAO,CAAK,CAAC;CAChD,GAGM,WAA0D;EAC9D,GAAI,MAAW,KAAA,KAAa,EAAE,UAAO;EACrC,GAAI,MAAS,KAAA,KAAa,EAAE,QAAK;EACjC,GAAI,KAAU,EAAE,UAAO;EACvB;EACA;CACF,IAEM,KAAc,MAAwD;EAC1E,IAAM,IAAM,EAAM,CAAC;EAcnB,OAXE,IAAc,KACd,MAAQ,KACR,IAAQ,KACR,KAAK,IAAI,IAAI,IAAgB,KAC7B,CAAC,GAAY,SAEN,QAAQ,QAAQ,KAGzB,IAAQ,MAED,EAAK,MACV,GACA,OAAO,GAAsC,GAAQ,MAAa;GAChE,IAAM,IAAY,KAAK,IAAI;GAE3B,IAAI;IACF,IAAM,IAAS,MAAM,GAAO,MAAQ,EAAI,MAAM,GAAG,CAAI,GAAG;KACtD,OAAO;KACP;KACA,OAAO,IAAgB;IACzB,CAAC;IAED,AAAI,EAAS,MACX,EAAO,CAAM,GACb,IAAQ,MACR,IAAe,GACf,IAAgB,KAAK,IAAI,GACzB,EAAI,UAAU;KAAE,YAAY,KAAK,IAAI,IAAI;KAAW,OAAO;KAAG,QAAQ;IAAU,CAAC;GAErF,SAAS,GAAiB;IACxB,IAAI,EAAO,SAAS;IAEpB,AAAI,EAAS,MACP,GAAY,UACd,EAAW,SAAS,IACpB,IAAQ,EAAW,WACnB,IAAQ,EAAW,WACnB,IAAa,SAEb,IAAQ,CAAC,GACT,IAAQ,IAGV,IAAQ,IAAI,EAAe,EAAa,CAAM,GAAG;KAC/C,OAAO;KACP,SAAS;MAAE,MAAM;MAAU,OAAO,EAAE;MAAO,MAAM,EAAE;MAAM,GAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO;KAAG;IACjG,CAAC,GACD,EAAI,UAAU;KAAE,YAAY,KAAK,IAAI,IAAI;KAAW;KAAO,OAAO;KAAG,QAAQ;IAAQ,CAAC;GAE1F;EACF,SACM;GAGJ,AAFA,EAAgB,GAEhB,EAAkB,aAAa,EAAK,aAAa,CAAC;EACpD,CACF;CACF,GAEM,UAAiB,EAAW,EAAc,CAAC;CAQjD,OALI,KAAW,EAAc,GAE7B,EAAK,2BAA2B,KAAK,EAAS,CAAC,GAGxC;EACL,IAAI,UAAU;GACZ,OAAO;EACT;EAEA,IAAI,iBAAiB;GACnB,OAAO,EAAK;EACd;EAEA,eAAe;GAGb,AAFA,EAAkB,OAAO,GACzB,EAAkB,QAAQ,GAC1B,EAAK,QAAQ;EACf;EAEA,IAAI,WAAW;GACb,OAAO,EAAK;EACd;EAEA,KAAK,GAAQ;GACX,IAAM,IACJ,IAAQ,IAAI,EAAU,GAAQ,EAAU,GAAO,CAAK,CAAC,IAAI,EAAiB,GAAQ,eAAe,QAAQ;GAM3G,OAJI,MAAY,IAAa,QAAQ,QAAQ,KAE7C,IAAO,GAEA,EAAS;EAClB;EAEA,WAAW;GACT,IAAM,IAAO,EAAU,GAAO,CAAK;GAMnC,OAJI,MAAS,IAAa,QAAQ,QAAQ,KAE1C,IAAO,GAEA,EAAS;EAClB;EAEA,IAAI,OAAO;GACT,OAAO;EACT;EAEA,OAAO;GACL,IAAM,IAAQ,EAAU,GAAO,CAAK;GAMpC,OAJI,KAAQ,IAAc,QAAQ,QAAQ,KAE1C,KAEO,EAAS;EAClB;EAEA,iBAAiB,GAAS,GAAS;GACjC,IAAI,GAAY,QACd,MAAM,IAAI,EACR,+FACF;GAGF,IAAM,IAAY,GACZ,IAAY;GAElB,IAAa;IAAE,QAAQ;IAAM;IAAW;GAAU;GAElD,IAAI;IACF,IAAQ,EAAQ,CAAK;GACvB,SAAS,GAAY;IAEnB,MADA,IAAa,MACP;GACR;GAKA,OAHA,IAAQ,GAAS,SAAS,GAC1B,EAAgB,SAEH;IACX,AAAI,GAAY,WACd,EAAW,SAAS,IACpB,IAAQ,GACR,IAAQ,GACR,IAAa,MACb,EAAgB;GAEpB;EACF;EAEA,MAAM,GAAS;GACb,IAAI,IAAU;GAEd,IAAI,EAAQ,UAAU,KAAA,GAAW;IAC/B,IAAM,IAAO,EAAiB,EAAQ,OAAO,gBAAgB,OAAO;IAEpE,AAAI,MAAS,MACX,IAAQ,GACR,IAAU;GAEd;GAmBA,IAjBI,YAAY,MACd,IAAS,EAAQ,QACjB,IAAU,KAGR,UAAU,MACZ,IAAO,EAAQ,MACf,IAAU,KAKR,YAAY,MAAY,EAAQ,WAAW,KAAU,EAAK,KAAK,iBACjE,IAAS,EAAQ,UAAU,IAC3B,IAAU,KAGR,EAAQ,SAAS,KAAA,GAAW;IAC9B,IAAM,IACJ,IAAQ,IACJ,EAAU,EAAQ,MAAM,EAAU,GAAO,CAAK,CAAC,IAC/C,EAAiB,EAAQ,MAAM,gBAAgB,MAAM;IAE3D,AAAI,MAAS,MACX,IAAO,GACP,IAAU;GAEd;GAgBA,OAdK,KAIL,EAAkB,OAAO,IAItB,EAAQ,UAAU,KAAA,KAAa,YAAY,KAAW,UAAU,KAAW,YAAY,MACxF,EAAQ,SAAS,KAAA,MAEjB,IAAO,IAGF,EAAS,KAdK,QAAQ,QAAQ;EAevC;EAEA,OAAO;GAKL,OAJI,KAAQ,IAAU,QAAQ,QAAQ,KAEtC,KAEO,EAAS;EAClB;EAEA,IAAI,QAAQ;GACV,OAAO;IACL,GAAI,MAAW,KAAA,KAAa,EAAE,UAAO;IACrC,GAAI,MAAS,KAAA,KAAa,EAAE,QAAK;IACjC,GAAI,KAAU,EAAE,UAAO;IACvB;IACA;GACF;EACF;EAEA,MAAM,GAAS;GACb,OAAO,EAAK,MAAM,CAAO;EAC3B;EAEA,UAAU;GACR,OAAO,EAAS;EAClB;EAEA,QAAQ;GAON,OANA,EAAkB,OAAO,GACzB,IAAS,IACT,IAAO,GACP,IAAS,EAAI,QACb,IAAO,EAAI,MAEJ,EAAS;EAClB;EAEA,OAAO,GAAG,GAAqC;GAkB7C,OAjBI,GAAM,YAGJ,MAAM,KAAU,CAAC,EAAK,KAAK,cAAoB,QAAQ,QAAQ,KAEnE,EAAkB,OAAO,GACzB,IAAS,GACT,IAAO,GAEA,EAAS,KAGd,MAAM,IAAe,QAAQ,QAAQ,KAEzC,IAAS,GACT,IAAO,GAEA,EAAkB,eAAe,KAAK,EAAS,GAAG,CAAU;EACrE;EAEA,YAAY,MAAa,EAAK,KAAK,UAAU,CAAQ;GAEpD,OAAO,gBAAgB;GAGtB,AAFA,EAAkB,OAAO,GACzB,EAAkB,QAAQ,GAC1B,EAAK,QAAQ;EACf;CACF;AACF"}
|
package/dist/sourcerer.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/arsenal");function t(e,t){return e.patch(t)}var n=class e extends Error{#e;constructor(e,t={}){super(e,t.cause===void 0?void 0:{cause:t.cause}),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype),this.#e=t}get attempt(){return this.#e.attempt??0}get context(){return this.#e.context}static is(t){return t instanceof e}},r=class extends n{timeoutMs;constructor(e){super(`Source.ready() timed out after ${e}ms`),this.timeoutMs=e}},i=class extends n{constructor(){super(`Source disposed while waiting for ready()`)}},a=e=>{let t={...e.search&&{search:e.search},limit:String(e.limit),page:String(e.page)},n=e;return n.filter!==void 0&&(t.filter=JSON.stringify(n.filter)),n.sort!==void 0&&(t.sort=JSON.stringify(n.sort)),t},o=(e,t={})=>{let r=e instanceof URLSearchParams?Object.fromEntries(e.entries()):e,{defaultLimit:i=20,strict:a=!1}=t,o=(e,t)=>{if(e===void 0)return t;let n=Array.isArray(e)?e[0]:e,r=Number(n);return Number.isInteger(r)&&r>0?r:t},s=(e,t)=>{if(t===void 0)return;let r=Array.isArray(t)?t[0]:t;try{return JSON.parse(r)}catch{if(a)throw new n(`Invalid query param "${e}": ${r}`);return}},c=r.limit,l=r.page,u=r.search,d=r.filter,f=r.sort,p=d===void 0?void 0:s(`filter`,d),m=f===void 0?void 0:s(`sort`,f);return{...p!==void 0&&{filter:p},...m!==void 0&&{sort:m},...u!==void 0&&{search:Array.isArray(u)?u[0]:u},limit:o(c,i),page:o(l,1)}},s=e.hash,c=e=>e instanceof Error?e.message:typeof e==`string`&&e.length>0?e:`Request failed`,l=t=>(0,e.backoff)(t);function u(e,t){let n=null,r=()=>{n&&=(n(),null)};return{cancel(){e.cancelTimer(),r()},dispose(){r()},schedule(i,a){r();let o=new Promise(e=>{n=e});return e.schedule(i,a),t(),o},settleIfIdle(e){e===0&&r()}}}function d(e){let t=new Set,n=new Set,a=new AbortController,o,s=!1;return{cancelTimer(){o&&=(clearTimeout(o),void 0)},get disposalSignal(){return a.signal},dispose(){o&&=(clearTimeout(o),void 0);for(let e of n)e.timeoutId!==void 0&&clearTimeout(e.timeoutId),e.reject(new i);n.clear(),t.clear(),s=!0,a.abort()},flush(e){return o?(clearTimeout(o),o=void 0,e()):Promise.resolve()},get isDisposed(){return s},get isScheduled(){return o!==void 0},notify(r){if(!s){(r??e?.onBeforeNotify)?.();for(let e of t)e();for(let e of n)e.check()}},ready(e,t){return s?Promise.reject(new i):e()?Promise.resolve():new Promise((i,a)=>{let o={check:()=>{e()&&(o.timeoutId!==void 0&&clearTimeout(o.timeoutId),n.delete(o),i())},reject:a};t!==void 0&&(o.timeoutId=setTimeout(()=>{n.delete(o),a(new r(t))},t)),n.add(o)})},schedule(e,t){s||(o&&clearTimeout(o),o=setTimeout(()=>{o=void 0,e()},t))},subscribe(e){return s?()=>{}:(t.add(e),()=>t.delete(e))}}}function f(e){let t=new Map,n=``,r=0;return{dispose(){for(let e of t.values())e.controller.abort();t.clear(),r=0},get pendingCount(){return r},async run(i,a,o){let s=e(i);n=s;for(let[e,n]of t)e!==s&&(n.controller.abort(),t.delete(e));let c=t.get(s);if(c){r++,o();try{await c.promise}finally{r--,o()}return}let l=new AbortController;r++,o();let u=a(i,l.signal,()=>s===n).finally(()=>{t.delete(s),r--,o()});t.set(s,{controller:l,promise:u}),await u}}}function p(e,t=s,n){let r=d({onBeforeNotify:n}),i=f(t),a=e.debounceMs??300,o=e.retry?.attempts??0,c=e.retry?.delay??l,u=e.autoFetch!==!1,p,m=()=>{r.isDisposed||(p!==void 0&&(clearInterval(p),p=void 0),i.dispose(),r.dispose())};return{autoFetch:u,core:r,debounceMs:a,get disposalSignal(){return r.disposalSignal},dispose:m,get disposed(){return r.isDisposed},fetch(e,t,n){return i.run(e,t,n)},pendingCount:()=>i.pendingCount,ready(e){return r.ready(()=>i.pendingCount===0&&!r.isScheduled,e)},retryAttempts:o,retryDelay:c,startRefreshInterval(t){e.refreshInterval!==void 0&&e.refreshInterval>0&&(p=setInterval(()=>{r.isDisposed||t()},e.refreshInterval))},[Symbol.dispose]:m}}function m(t){let r=t.queryKey??s,i=Math.max(1,Math.trunc(t.limit??20)),a=``,o,l,d,f,m=[],h=0,g=null,_=[],v={error:null,hasNextPage:!1,hasPrevPage:!1,isLoading:!1,isSearchPending:!1,pageSize:i,totalItems:0},y=()=>{_=m,v={error:g,hasNextPage:d!==void 0,hasPrevPage:f!==void 0,isLoading:b.pendingCount()>0,isSearchPending:b.core.isScheduled,pageSize:i,totalItems:h}},b=p(t,r,y),{autoFetch:x,debounceMs:S,retryAttempts:C,retryDelay:w}=b;y();let T=()=>{b.disposed||b.core.notify()},E=u(b.core,T),D=()=>({...o!==void 0&&{after:o},...l!==void 0&&{before:l},...a&&{search:a},limit:i}),O=r=>(g=null,b.fetch(r,async(r,i,a)=>{let o=Date.now();try{let n=await(0,e.retry)(e=>t.fetch(r,e),{delay:w,signal:i,times:C+1});a()&&(m=n.items,h=n.total??n.items.length,d=n.nextCursor,f=n.prevCursor,g=null,t.onFetch?.({durationMs:Date.now()-o,query:r,status:`success`}))}catch(e){if(i.aborted)return;a()&&(m=[],h=0,d=void 0,f=void 0,g=new n(c(e),{cause:e,context:{kind:`cursor`,limit:r.limit,...r.search&&{search:r.search}}}),t.onFetch?.({durationMs:Date.now()-o,error:g,query:r,status:`error`}))}},()=>{T(),E.settleIfIdle(b.pendingCount())})),k=()=>O(D());return x&&k(),b.startRefreshInterval(()=>void k()),{get current(){return _},get disposalSignal(){return b.disposalSignal},dispose:()=>{E.cancel(),E.dispose(),b.dispose()},get disposed(){return b.disposed},get meta(){return v},next(){return d?(o=d,l=void 0,k()):Promise.resolve()},patch(e){let t=!1;if(e.limit!==void 0){let n=Math.max(1,Math.trunc(e.limit));n!==i&&(i=n,o=void 0,l=void 0,t=!0)}return`search`in e&&(e.search!==a||b.core.isScheduled)&&(a=e.search??``,o=void 0,l=void 0,t=!0),t?(E.cancel(),k()):Promise.resolve()},prev(){return f?(l=f,o=void 0,k()):Promise.resolve()},get query(){return{...o!==void 0&&{after:o},...l!==void 0&&{before:l},...a&&{search:a},limit:i}},ready(e){return b.ready(e)},refresh(){return k()},reset(){return E.cancel(),a=``,o=void 0,l=void 0,k()},search(e,t){return t?.immediate?e===a&&!b.core.isScheduled?Promise.resolve():(E.cancel(),a=e,o=void 0,l=void 0,k()):e===a?Promise.resolve():(a=e,o=void 0,l=void 0,E.schedule(()=>void k(),S))},subscribe:e=>b.core.subscribe(e),[Symbol.dispose]:()=>{E.cancel(),E.dispose(),b.dispose()}}}function h(e,t){let n=d(),r=[],i=()=>{r=t(e.current)};i();let a=e.subscribe(()=>{i(),n.notify()});`disposalSignal`in e&&e.disposalSignal instanceof AbortSignal&&e.disposalSignal.addEventListener(`abort`,()=>n.dispose(),{once:!0});let o={get current(){return r},get disposalSignal(){return n.disposalSignal},dispose(){n.isDisposed||(a(),n.dispose())},get disposed(){return n.isDisposed},get meta(){return e.meta},subscribe(e){return n.subscribe(e)},[Symbol.dispose](){o.dispose()}};return o}function g(t){let r=t.queryKey??s,i=Math.max(1,Math.trunc(t.limit??20)),a=``,o=1,l=0,d=[],f=0,m=null,h=!1,g=[],_={error:null,hasMore:!1,isLoading:!1,isLoadingMore:!1,isSearchPending:!1,loadedPages:0,pageSize:i,totalItems:0},v=()=>{g=d,_={error:m,hasMore:d.length<f,isLoading:y.pendingCount()>0&&!h,isLoadingMore:h,isSearchPending:y.core.isScheduled,loadedPages:l,pageSize:i,totalItems:f}},y=p(t,r,v),{autoFetch:b,debounceMs:x,retryAttempts:S,retryDelay:C}=y;v();let w=()=>{y.disposed||y.core.notify()},T=u(y.core,w),E=(r,s)=>{let u={...a&&{search:a},limit:i,page:r};return m=null,y.fetch(u,async(i,a,u)=>{let p=Date.now();try{let n=await(0,e.retry)(e=>t.fetch(i,e),{delay:C,signal:a,times:S+1});u()&&(d=s?[...d,...n.items]:n.items,f=n.total,o=r,l=s?l+1:1,m=null,t.onFetch?.({durationMs:Date.now()-p,query:i,status:`success`}))}catch(e){if(a.aborted)return;u()&&(s||(d=[]),f=s?f:0,m=new n(c(e),{cause:e,context:{kind:`infinite`,limit:i.limit,page:i.page,...i.search&&{search:i.search}}}),t.onFetch?.({durationMs:Date.now()-p,error:m,query:i,status:`error`}))}finally{h=!1}},()=>{w(),T.settleIfIdle(y.pendingCount())})},D=()=>E(1,!1);return b&&D(),y.startRefreshInterval(()=>void D()),{get current(){return g},get disposalSignal(){return y.disposalSignal},dispose:()=>{T.cancel(),T.dispose(),y.dispose()},get disposed(){return y.disposed},loadMore(){return!_.hasMore||y.pendingCount()>0||h?Promise.resolve():(h=!0,v(),E(o+1,!0))},get meta(){return _},patch(e){let t=!1;if(e.limit!==void 0){let n=Math.max(1,Math.trunc(e.limit));n!==i&&(i=n,t=!0)}return`search`in e&&(e.search!==a||y.core.isScheduled)&&(a=e.search??``,t=!0),t?(T.cancel(),d=[],f=0,o=1,l=0,D()):Promise.resolve()},get query(){return{...a&&{search:a},limit:i,page:o}},ready(e){return y.ready(e)},reset(){return T.cancel(),o=1,l=0,d=[],f=0,a=``,D()},search(e,t){return t?.immediate?e===a&&!y.core.isScheduled?Promise.resolve():(T.cancel(),a=e,d=[],f=0,l=0,o=1,D()):e===a?Promise.resolve():(a=e,d=[],f=0,l=0,o=1,T.schedule(()=>void D(),x))},subscribe:e=>y.core.subscribe(e),[Symbol.dispose]:()=>{T.cancel(),T.dispose(),y.dispose()}}}var _=(e,t)=>{let n=Math.trunc(e);return Number.isFinite(n)?Math.max(t,n):t},v=(e,t)=>{let n=_(e,0),r=_(t,1);return Math.max(1,Math.ceil(n/r))},y=(e,t)=>Math.max(1,Math.min(_(e,1),Math.max(1,t))),b=e=>{let t=_(e.pageSize,1),n=_(e.totalItems,0),r=v(n,t),i=y(e.pageNumber,r);return{error:e.error,isLoading:e.isLoading,isSearchPending:e.isSearchPending,pageCount:r,pageNumber:i,pageSize:t,totalItems:n}};function x(e){if(e.totalItems===0)return{end:0,start:0};let t=(e.pageNumber-1)*e.pageSize+1;return{end:Math.min(e.pageNumber*e.pageSize,e.totalItems),start:t}}var S=20,C=300;function w(e,t){let n=t.toLowerCase();return e.filter(e=>JSON.stringify(e).toLowerCase().includes(n))}function T(e,t={}){let r=d(),i=t.filterAsync!==void 0||t.sortAsync!==void 0,a=t.debounceMs??C,o=t.initialData??e,s=``,l=t.filter,u=t.sort,f=t.limit??S,p=1,m=[],h=!1,g=!1,_=null,x=null,T=null,E=()=>r.notify(),D=()=>{T&&=(T.resolve(),null)},O=()=>{let e=o;return s&&(e=(t.searchFn??w)(e,s)),l&&(e=e.filter(l)),u&&(e=[...e].sort(u)),e},k=()=>{m=O();let e=v(m.length,f);p=y(p,e)},A=async()=>{x?.abort();let e=new AbortController;x=e,h=!0,_=null,E();try{let n=o;if(s&&(n=(t.searchFn??w)(n,s)),l&&(n=n.filter(l)),t.filterAsync&&!e.signal.aborted&&(n=await t.filterAsync(n,e.signal)),u&&(n=[...n].sort(u)),t.sortAsync&&!e.signal.aborted&&(n=await t.sortAsync(n,e.signal)),e.signal.aborted)return;m=n,h=!1,g=!1;let r=v(m.length,f);p=y(p,r)}catch(t){e.signal.aborted||(h=!1,g=!1,_=new n(c(t),{cause:t}))}finally{x===e&&(x=null)}E(),D()},j=()=>i?A():(g=!1,k(),E(),D(),Promise.resolve());i?(m=O(),A()):k();let M={get current(){let e=(p-1)*f;return m.slice(e,e+f)},get disposalSignal(){return r.disposalSignal},dispose(){r.isDisposed||(r.cancelTimer(),x?.abort(),x=null,D(),r.dispose())},get disposed(){return r.isDisposed},goTo(e){let t=y(e,v(m.length,f));return t===p?Promise.resolve():(p=t,E(),Promise.resolve())},goToLast(){return M.goTo(v(m.length,f))},get meta(){return b({error:_,isLoading:h,isSearchPending:g,pageNumber:p,pageSize:f,totalItems:m.length})},next(){return M.goTo(p+1)},patch(e){let t=!1;if(e.limit!==void 0){let n=Math.max(1,Math.trunc(e.limit));n!==f&&(f=n,t=!0)}if(`filter`in e&&(l=e.filter,t=!0),`sort`in e&&(u=e.sort,t=!0),`search`in e&&(e.search!==s||r.isScheduled)&&(s=e.search??``,t=!0),e.page!==void 0){let n=y(e.page,v(m.length,f));n!==p&&(p=n,t=!0)}return t?(r.cancelTimer(),D(),(e.limit!==void 0||`filter`in e||`sort`in e||`search`in e)&&e.page===void 0&&(p=1),j()):Promise.resolve()},prev(){return M.goTo(p-1)},get query(){return{limit:f,page:p,...s&&{search:s}}},ready(e){return r.ready(()=>!h&&!r.isScheduled,e)},reset(){return r.cancelTimer(),g=!1,s=``,l=t.filter,u=t.sort,p=1,D(),j()},search(e,t){if(t?.immediate)return e===s&&!r.isScheduled?Promise.resolve():(r.cancelTimer(),g=!1,s=e,p=1,D(),j());if(e===s)return Promise.resolve();D(),s=e,p=1,g=!0,E();let n,i=new Promise(e=>{n=e});return T={promise:i,resolve:n},r.schedule(()=>{g=!1,j()},a),i},setData(e){return o=e,p=1,j()},subscribe(e){return r.subscribe(e)},[Symbol.dispose](){M.dispose()}};return M}function E(e,t){let n=d(),r=t(e.map(e=>e.current)),i=e.map(i=>i.subscribe(()=>{r=t(e.map(e=>e.current)),n.notify()})),a={get current(){return r},get disposalSignal(){return n.disposalSignal},dispose(){if(!n.isDisposed){for(let e of i)e();n.dispose()}},get disposed(){return n.isDisposed},subscribe(e){return n.subscribe(e)},[Symbol.dispose](){a.dispose()}};return a}function D(t){let r=t.queryKey??s,i=t.staleTime??0,a=Math.max(1,Math.trunc(t.limit??20)),o=1,l=``,d=t.filter,f=t.sort,m=[],h=0,g=null,_=0,x=``,S=null;t.snapshot&&(m=t.snapshot.items,h=t.snapshot.total,t.snapshot.page!==void 0&&(o=t.snapshot.page),t.snapshot.search&&(l=t.snapshot.search),_=Date.now());let C=[],w=b({error:null,isLoading:!1,isSearchPending:!1,pageNumber:1,pageSize:a,totalItems:0}),T=()=>{let e=v(h,a),t=y(o,e);C=m,w=b({error:g,isLoading:E.pendingCount()>0,isSearchPending:E.core.isScheduled,pageNumber:t,pageSize:a,totalItems:h})},E=p(t,r,T),{autoFetch:D,debounceMs:O,retryAttempts:k,retryDelay:A}=E;T();let j=()=>{E.disposed||E.core.notify()},M=u(E.core,j),N=e=>{S?.active&&(S.active=!1,S=null),m=e.items,h=e.total,o=y(o,v(h,a))},P=()=>({...d!==void 0&&{filter:d},...f!==void 0&&{sort:f},...l&&{search:l},limit:a,page:o}),F=a=>{let o=r(a);return i>0&&o===x&&h>0&&Date.now()-_<i&&!S?.active?Promise.resolve():(g=null,E.fetch(a,async(r,i,a)=>{let s=Date.now();try{let n=await(0,e.retry)(e=>t.fetch(r,e),{delay:A,signal:i,times:k+1});a()&&(N(n),g=null,x=o,_=Date.now(),t.onFetch?.({durationMs:Date.now()-s,query:r,status:`success`}))}catch(e){if(i.aborted)return;a()&&(S?.active?(S.active=!1,m=S.prevItems,h=S.prevTotal,S=null):(m=[],h=0),g=new n(c(e),{cause:e,context:{kind:`remote`,limit:r.limit,page:r.page,...r.search&&{search:r.search}}}),t.onFetch?.({durationMs:Date.now()-s,error:g,query:r,status:`error`}))}},()=>{j(),M.settleIfIdle(E.pendingCount())}))},I=()=>F(P());return D&&I(),E.startRefreshInterval(()=>void I()),{get current(){return C},get disposalSignal(){return E.disposalSignal},dispose:()=>{M.cancel(),M.dispose(),E.dispose()},get disposed(){return E.disposed},goTo(e){let t=h>0?y(e,v(h,a)):Math.max(1,Math.trunc(e));return t===o?Promise.resolve():(o=t,I())},goToLast(){let e=v(h,a);return o===e?Promise.resolve():(o=e,I())},get meta(){return w},next(){let e=v(h,a);return o>=e?Promise.resolve():(o++,I())},optimisticUpdate(e,t){if(S?.active)throw new n(`An optimistic update is already active. Rollback the previous update before starting another.`);let r=m,i=h;S={active:!0,prevItems:r,prevTotal:i};try{m=e(m)}catch(e){throw S=null,e}return h=t?.total??h,j(),()=>{S?.active&&(S.active=!1,m=r,h=i,S=null,j())}},patch(e){let t=!1;if(e.limit!==void 0){let n=Math.max(1,Math.trunc(e.limit));n!==a&&(a=n,t=!0)}if(`filter`in e&&(d=e.filter,t=!0),`sort`in e&&(f=e.sort,t=!0),`search`in e&&(e.search!==l||E.core.isScheduled)&&(l=e.search??``,t=!0),e.page!==void 0){let n=h>0?y(e.page,v(h,a)):Math.max(1,Math.trunc(e.page));n!==o&&(o=n,t=!0)}return t?(M.cancel(),(e.limit!==void 0||`filter`in e||`sort`in e||`search`in e)&&e.page===void 0&&(o=1),I()):Promise.resolve()},prev(){return o<=1?Promise.resolve():(o--,I())},get query(){return{...d!==void 0&&{filter:d},...f!==void 0&&{sort:f},...l&&{search:l},limit:a,page:o}},ready(e){return E.ready(e)},refresh(){return I()},reset(){return M.cancel(),l=``,o=1,d=t.filter,f=t.sort,I()},search(e,t){return t?.immediate?e===l&&!E.core.isScheduled?Promise.resolve():(M.cancel(),l=e,o=1,I()):e===l?Promise.resolve():(l=e,o=1,M.schedule(()=>void I(),O))},subscribe:e=>E.core.subscribe(e),[Symbol.dispose]:()=>{M.cancel(),M.dispose(),E.dispose()}}}var O=e=>{let t=e.query;return{items:e.current,...t.search&&{search:t.search},page:e.meta.pageNumber,total:e.meta.totalItems}};async function k(e){let t=D({...e,autoFetch:!1});try{if(await t.refresh(),t.meta.error)throw t.meta.error;return O(t)}finally{t.dispose()}}async function A(e){let t=D({...e,autoFetch:!1});if(await t.refresh(),t.meta.error)throw t.dispose(),t.meta.error;return{snapshot:O(t),source:t}}var j=e=>{if(e==null)return``;if(typeof e==`bigint`||typeof e==`boolean`||typeof e==`number`||typeof e==`string`)return String(e);if(e instanceof Date)return e.toISOString();try{return JSON.stringify(e)??``}catch{return String(e)}},M=(e,t,n=!1)=>{let r=n?t:t.toLowerCase();return t=>{let i=e(t)??``;return(n?i:i.toLowerCase()).includes(r)}},N=(e,t)=>n=>Object.is(e(n),t),P=(e,t)=>{let n=e=>e instanceof Date?e.getTime():e,r=t.min===void 0?void 0:n(t.min),i=t.max===void 0?void 0:n(t.max);return t=>{let a=n(e(t));return!(r!==void 0&&a<r||i!==void 0&&a>i)}},F=(e,t=`asc`)=>{let n=t===`asc`?1:-1;return(t,r)=>{let i=e(t),a=e(r);return i instanceof Date&&a instanceof Date?(i.getTime()-a.getTime())*n:i<a?-1*n:i>a?1*n:0}},I=(e,t={})=>{let n=Array.isArray(e)?e:[e],r=t.caseSensitive===!0;return(e,t)=>{if(t.length===0)return e;let i=r?t:t.toLowerCase();return e.filter(e=>n.some(t=>{let n=j(t(e));return(r?n:n.toLowerCase()).includes(i)}))}};function L(e){return e.meta.isLoading||e.meta.isSearchPending?{status:`loading`}:e.meta.error?{error:e.meta.error,status:`error`}:{items:e.current,status:`success`}}exports.SourceDisposedError=i,exports.SourceTimeoutError=r,exports.SourcererError=n,exports.applyQuery=t,exports.createCursorSource=m,exports.createInfiniteSource=g,exports.createLocalSource=T,exports.createRemoteSource=D,exports.decodeQuery=o,exports.deriveSource=h,exports.encodeQuery=a,exports.filterContains=M,exports.filterEquals=N,exports.filterRange=P,exports.itemRange=x,exports.mergeSource=E,exports.prefetchSource=k,exports.prefetchSourceAndKeep=A,exports.searchBy=I,exports.sortBy=F,exports.sourceState=L;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("@vielzeug/arsenal");var t=!globalThis.__SOURCERER_PROD__;function n(e){t&&console.warn(`[@vielzeug/sourcerer] ${e}`)}function r(e){t&&e()}var i=e.hash,a=e=>e instanceof Error?e.message:typeof e==`string`&&e.length>0?e:`Request failed`,o=t=>(0,e.backoff)(t);function s(e,t=200){return e.replace(/\p{C}/gu,`?`).slice(0,t)}var c=new Set;function l(e,t,i){let a=Number.isFinite(e)?Math.max(1,Math.trunc(e)):1;if(!Number.isFinite(e)||e<1){let o=`${t}:${i}`;c.has(o)||(c.add(o),r(()=>n(`${t}: ${i} ${e} is invalid — clamped to ${a}. Must be a positive integer.`)))}return a}var u=class e extends Error{#e;constructor(e,t={}){super(e,t.cause===void 0?void 0:{cause:t.cause}),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype),this.#e=t}get attempt(){return this.#e.attempt??0}get context(){return this.#e.context}static is(t){return t instanceof e}},d=class extends u{timeoutMs;constructor(e){super(`Source.ready() timed out after ${e}ms`),this.timeoutMs=e}},f=class extends u{constructor(){super(`Source disposed while waiting for ready()`)}},p=e=>{let t={...e.search&&{search:e.search},limit:String(e.limit),page:String(e.page)},n=e;return n.filter!==void 0&&(t.filter=JSON.stringify(n.filter)),n.sort!==void 0&&(t.sort=JSON.stringify(n.sort)),t},m=(e,t={})=>{let i=e instanceof URLSearchParams?Object.fromEntries(e.entries()):e,{defaultLimit:a=20,strict:o=!1}=t,c=(e,t,i)=>{if(t===void 0)return i;let a=Array.isArray(t)?t[0]:t,o=Number(a);return Number.isInteger(o)&&o>0?o:(r(()=>n(`decodeQuery: ${e} "${s(a,80)}" is not a positive integer — using ${i}.`)),i)},l=(e,t)=>{if(t===void 0)return;let n=Array.isArray(t)?t[0]:t;try{return JSON.parse(n)}catch{if(o)throw new u(`Invalid query param "${e}": ${s(n,80)}`);return}},d=i.limit,f=i.page,p=i.search,m=i.filter,h=i.sort,g=m===void 0?void 0:l(`filter`,m),_=h===void 0?void 0:l(`sort`,h);return{...g!==void 0&&{filter:g},..._!==void 0&&{sort:_},...p!==void 0&&{search:Array.isArray(p)?p[0]:p},limit:c(`limit`,d,a),page:c(`page`,f,1)}};function h(e,t){let n=null,r=()=>{n&&=(n(),null)};return{cancel(){e.cancelTimer(),r()},dispose(){r()},schedule(i,a){r();let o=new Promise(e=>{n=e});return e.schedule(i,a),t(),o},settleIfIdle(e){e===0&&r()}}}function g(e){let t=new Set,n=new Set,r=new AbortController,i,a=!1;return{cancelTimer(){i&&=(clearTimeout(i),void 0)},get disposalSignal(){return r.signal},dispose(){i&&=(clearTimeout(i),void 0);for(let e of n)e.timeoutId!==void 0&&clearTimeout(e.timeoutId),e.reject(new f);n.clear(),t.clear(),a=!0,r.abort()},flush(e){return i?(clearTimeout(i),i=void 0,e()):Promise.resolve()},get isDisposed(){return a},get isScheduled(){return i!==void 0},notify(r){if(!a){(r??e?.onBeforeNotify)?.();for(let e of t)e();for(let e of n)e.check()}},ready(e,t){return a?Promise.reject(new f):e()?Promise.resolve():new Promise((r,i)=>{let a={check:()=>{e()&&(a.timeoutId!==void 0&&clearTimeout(a.timeoutId),n.delete(a),r())},reject:i};t!==void 0&&(a.timeoutId=setTimeout(()=>{n.delete(a),i(new d(t))},t)),n.add(a)})},schedule(e,t){a||(i&&clearTimeout(i),i=setTimeout(()=>{i=void 0,e()},t))},subscribe(e){return a?()=>{}:(t.add(e),()=>t.delete(e))}}}function _(e){let t=new Map,n=``,r=0;return{dispose(){for(let e of t.values())e.controller.abort();t.clear(),r=0},get pendingCount(){return r},async run(i,a,o){let s=e(i);n=s;for(let[e,n]of t)e!==s&&(n.controller.abort(),t.delete(e));let c=t.get(s);if(c){r++,o();try{await c.promise}finally{r--,o()}return}let l=new AbortController;r++,o();let u=a(i,l.signal,()=>s===n).finally(()=>{t.delete(s),r--,o()});t.set(s,{controller:l,promise:u}),await u}}}function v(e,t=i,n){let r=g({onBeforeNotify:n}),a=_(t),s=e.debounceMs??300,c=e.retry?.attempts??0,l=e.retry?.delay??o,u=e.autoFetch!==!1,d,f=()=>{r.isDisposed||(d!==void 0&&(clearInterval(d),d=void 0),a.dispose(),r.dispose())};return{autoFetch:u,core:r,debounceMs:s,get disposalSignal(){return r.disposalSignal},dispose:f,get disposed(){return r.isDisposed},fetch(e,t,n){return a.run(e,t,n)},pendingCount:()=>a.pendingCount,ready(e){return r.ready(()=>a.pendingCount===0&&!r.isScheduled,e)},retryAttempts:c,retryDelay:l,startRefreshInterval(t){e.refreshInterval!==void 0&&e.refreshInterval>0&&(d=setInterval(()=>{r.isDisposed||t()},e.refreshInterval))},[Symbol.dispose]:f}}function y(t){let n=t.queryKey??i,r=l(t.limit??20,`createCursorSource`,`limit`),o=``,s,c,d,f,p=[],m=0,g=null,_=[],y={error:null,hasNextPage:!1,hasPrevPage:!1,isLoading:!1,isSearchPending:!1,pageSize:r,totalItems:0},b=()=>{_=p,y={error:g,hasNextPage:d!==void 0,hasPrevPage:f!==void 0,isLoading:x.pendingCount()>0,isSearchPending:x.core.isScheduled,pageSize:r,totalItems:m}},x=v(t,n,b),{autoFetch:S,debounceMs:C,retryAttempts:w,retryDelay:T}=x;b();let E=()=>{x.disposed||x.core.notify()},D=h(x.core,E),O=()=>({...s!==void 0&&{after:s},...c!==void 0&&{before:c},...o&&{search:o},limit:r}),k=n=>(g=null,x.fetch(n,async(n,r,i)=>{let o=Date.now();try{let a=await(0,e.retry)(e=>t.fetch(n,e),{delay:T,signal:r,times:w+1});i()&&(p=a.items,m=a.total??a.items.length,d=a.nextCursor,f=a.prevCursor,g=null,t.onFetch?.({durationMs:Date.now()-o,query:n,status:`success`}))}catch(e){if(r.aborted)return;i()&&(p=[],m=0,d=void 0,f=void 0,g=new u(a(e),{cause:e,context:{kind:`cursor`,limit:n.limit,...n.search&&{search:n.search}}}),t.onFetch?.({durationMs:Date.now()-o,error:g,query:n,status:`error`}))}},()=>{E(),D.settleIfIdle(x.pendingCount())})),A=()=>k(O());return S&&A(),x.startRefreshInterval(()=>void A()),{get current(){return _},get disposalSignal(){return x.disposalSignal},dispose:()=>{D.cancel(),D.dispose(),x.dispose()},get disposed(){return x.disposed},get meta(){return y},next(){return d?(s=d,c=void 0,A()):Promise.resolve()},patch(e){let t=!1;if(e.limit!==void 0){let n=l(e.limit,`source.patch`,`limit`);n!==r&&(r=n,s=void 0,c=void 0,t=!0)}return`search`in e&&(e.search!==o||x.core.isScheduled)&&(o=e.search??``,s=void 0,c=void 0,t=!0),t?(D.cancel(),A()):Promise.resolve()},prev(){return f?(c=f,s=void 0,A()):Promise.resolve()},get query(){return{...s!==void 0&&{after:s},...c!==void 0&&{before:c},...o&&{search:o},limit:r}},ready(e){return x.ready(e)},refresh(){return A()},reset(){return D.cancel(),o=``,s=void 0,c=void 0,A()},search(e,t){return t?.immediate?e===o&&!x.core.isScheduled?Promise.resolve():(D.cancel(),o=e,s=void 0,c=void 0,A()):e===o?Promise.resolve():(o=e,s=void 0,c=void 0,D.schedule(()=>void A(),C))},subscribe:e=>x.core.subscribe(e),[Symbol.dispose]:()=>{D.cancel(),D.dispose(),x.dispose()}}}function b(e,t){let n=g(),r=[],i=()=>{r=t(e.current)};i();let a=e.subscribe(()=>{i(),n.notify()}),o={get current(){return r},get disposalSignal(){return n.disposalSignal},dispose(){n.isDisposed||(a(),n.dispose())},get disposed(){return n.isDisposed},get meta(){return e.meta},subscribe(e){return n.subscribe(e)},[Symbol.dispose](){o.dispose()}};return e.disposalSignal instanceof AbortSignal&&e.disposalSignal.addEventListener(`abort`,()=>o.dispose(),{once:!0}),o}function x(t){let n=t.queryKey??i,r=l(t.limit??20,`createInfiniteSource`,`limit`),o=``,s=1,c=0,d=[],f=0,p=null,m=!1,g=[],_={error:null,hasMore:!1,isLoading:!1,isLoadingMore:!1,isSearchPending:!1,loadedPages:0,pageSize:r,totalItems:0},y=()=>{g=d,_={error:p,hasMore:d.length<f,isLoading:b.pendingCount()>0&&!m,isLoadingMore:m,isSearchPending:b.core.isScheduled,loadedPages:c,pageSize:r,totalItems:f}},b=v(t,n,y),{autoFetch:x,debounceMs:S,retryAttempts:C,retryDelay:w}=b;y();let T=()=>{b.disposed||b.core.notify()},E=h(b.core,T),D=(n,i)=>{let l={...o&&{search:o},limit:r,page:n};return p=null,b.fetch(l,async(r,o,l)=>{let h=Date.now();try{let a=await(0,e.retry)(e=>t.fetch(r,e),{delay:w,signal:o,times:C+1});l()&&(d=i?[...d,...a.items]:a.items,f=a.total,s=n,c=i?c+1:1,p=null,t.onFetch?.({durationMs:Date.now()-h,query:r,status:`success`}))}catch(e){if(o.aborted)return;l()&&(i||(d=[]),f=i?f:0,p=new u(a(e),{cause:e,context:{kind:`infinite`,limit:r.limit,page:r.page,...r.search&&{search:r.search}}}),t.onFetch?.({durationMs:Date.now()-h,error:p,query:r,status:`error`}))}finally{m=!1}},()=>{T(),E.settleIfIdle(b.pendingCount())})},O=()=>D(1,!1);return x&&O(),b.startRefreshInterval(()=>void O()),{get current(){return g},get disposalSignal(){return b.disposalSignal},dispose:()=>{E.cancel(),E.dispose(),b.dispose()},get disposed(){return b.disposed},loadMore(){return!_.hasMore||b.pendingCount()>0||m?Promise.resolve():(m=!0,y(),D(s+1,!0))},get meta(){return _},patch(e){let t=!1;if(e.limit!==void 0){let n=l(e.limit,`source.patch`,`limit`);n!==r&&(r=n,t=!0)}return`search`in e&&(e.search!==o||b.core.isScheduled)&&(o=e.search??``,t=!0),t?(E.cancel(),d=[],f=0,s=1,c=0,O()):Promise.resolve()},get query(){return{...o&&{search:o},limit:r,page:s}},ready(e){return b.ready(e)},reset(){return E.cancel(),s=1,c=0,d=[],f=0,o=``,O()},search(e,t){return t?.immediate?e===o&&!b.core.isScheduled?Promise.resolve():(E.cancel(),o=e,d=[],f=0,c=0,s=1,O()):e===o?Promise.resolve():(o=e,d=[],f=0,c=0,s=1,E.schedule(()=>void O(),S))},subscribe:e=>b.core.subscribe(e),[Symbol.dispose]:()=>{E.cancel(),E.dispose(),b.dispose()}}}var S=(e,t)=>{let n=Math.trunc(e);return Number.isFinite(n)?Math.max(t,n):t},C=(e,t)=>{let n=S(e,0),r=S(t,1);return Math.max(1,Math.ceil(n/r))},w=(e,t)=>Math.max(1,Math.min(S(e,1),Math.max(1,t))),T=e=>{let t=S(e.pageSize,1),n=S(e.totalItems,0),r=C(n,t),i=w(e.pageNumber,r);return{error:e.error,isLoading:e.isLoading,isSearchPending:e.isSearchPending,pageCount:r,pageNumber:i,pageSize:t,totalItems:n}};function E(e){if(e.totalItems===0)return{end:0,start:0};let t=(e.pageNumber-1)*e.pageSize+1;return{end:Math.min(e.pageNumber*e.pageSize,e.totalItems),start:t}}var D=20,O=300;function k(e,t){let n=t.toLowerCase();return e.filter(e=>JSON.stringify(e).toLowerCase().includes(n))}function A(e,t={}){let n=g(),r=t.filterAsync!==void 0||t.sortAsync!==void 0,i=t.debounceMs??O,o=t.initialData??e,s=``,c=t.filter,d=t.sort,f=l(t.limit??D,`createLocalSource`,`limit`),p=1,m=[],_=!1,v=!1,y=null,b=null,x=()=>n.notify(),S=h(n,x),E=()=>{let e=o;return s&&(e=(t.searchFn??k)(e,s)),c&&(e=e.filter(c)),d&&(e=[...e].sort(d)),e},A=()=>{m=E();let e=C(m.length,f);p=w(p,e)},j=async()=>{b?.abort();let e=new AbortController;b=e,_=!0,y=null,x();try{let n=o;if(s&&(n=(t.searchFn??k)(n,s)),c&&(n=n.filter(c)),t.filterAsync&&!e.signal.aborted&&(n=await t.filterAsync(n,e.signal)),d&&(n=[...n].sort(d)),t.sortAsync&&!e.signal.aborted&&(n=await t.sortAsync(n,e.signal)),e.signal.aborted)return;m=n,_=!1,v=!1;let r=C(m.length,f);p=w(p,r)}catch(t){e.signal.aborted||(_=!1,v=!1,y=new u(a(t),{cause:t}))}finally{b===e&&(b=null)}x(),S.settleIfIdle(0)},M=()=>r?j():(v=!1,A(),x(),S.settleIfIdle(0),Promise.resolve());r?(m=E(),j()):A();let N={get current(){let e=(p-1)*f;return m.slice(e,e+f)},get disposalSignal(){return n.disposalSignal},dispose(){n.isDisposed||(b?.abort(),b=null,S.cancel(),S.dispose(),n.dispose())},get disposed(){return n.isDisposed},goTo(e){let t=w(e,C(m.length,f));return t===p?Promise.resolve():(p=t,x(),Promise.resolve())},goToLast(){return N.goTo(C(m.length,f))},get meta(){return T({error:y,isLoading:_,isSearchPending:v,pageNumber:p,pageSize:f,totalItems:m.length})},next(){return N.goTo(p+1)},patch(e){let t=!1;if(e.limit!==void 0){let n=l(e.limit,`source.patch`,`limit`);n!==f&&(f=n,t=!0)}if(`filter`in e&&(c=e.filter,t=!0),`sort`in e&&(d=e.sort,t=!0),`search`in e&&(e.search!==s||n.isScheduled)&&(s=e.search??``,t=!0),e.page!==void 0){let n=w(e.page,C(m.length,f));n!==p&&(p=n,t=!0)}return t?(S.cancel(),(e.limit!==void 0||`filter`in e||`sort`in e||`search`in e)&&e.page===void 0&&(p=1),M()):Promise.resolve()},prev(){return N.goTo(p-1)},get query(){return{limit:f,page:p,...s&&{search:s}}},ready(e){return n.ready(()=>!_&&!n.isScheduled,e)},reset(){return S.cancel(),v=!1,s=``,c=t.filter,d=t.sort,p=1,M()},search(e,t){return t?.immediate?e===s&&!n.isScheduled?Promise.resolve():(S.cancel(),v=!1,s=e,p=1,M()):e===s?Promise.resolve():(s=e,p=1,v=!0,S.schedule(()=>{v=!1,M()},i))},setData(e){return o=e,p=1,M()},subscribe(e){return n.subscribe(e)},[Symbol.dispose](){N.dispose()}};return N}function j(e,t){let n=g(),r=t(e.map(e=>e.current)),i=e.map(i=>i.subscribe(()=>{r=t(e.map(e=>e.current)),n.notify()})),a={get current(){return r},get disposalSignal(){return n.disposalSignal},dispose(){if(!n.isDisposed){for(let e of i)e();n.dispose()}},get disposed(){return n.isDisposed},subscribe(e){return n.subscribe(e)},[Symbol.dispose](){a.dispose()}},o=e.map(e=>e.disposalSignal).filter(e=>e instanceof AbortSignal);if(o.length===e.length&&o.length>0){let e=o.filter(e=>!e.aborted).length;if(e===0)a.dispose();else for(let t of o)t.aborted||t.addEventListener(`abort`,()=>{e--,e===0&&a.dispose()},{once:!0})}return a}function M(t){let n=t.queryKey??i,r=t.staleTime??0,o=l(t.limit??20,`createRemoteSource`,`limit`),s=1,c=``,d=t.filter,f=t.sort,p=[],m=0,g=null,_=0,y=``,b=null;t.snapshot&&(p=t.snapshot.items,m=t.snapshot.total,t.snapshot.page!==void 0&&(s=t.snapshot.page),t.snapshot.search&&(c=t.snapshot.search),_=Date.now());let x=[],S=T({error:null,isLoading:!1,isSearchPending:!1,pageNumber:1,pageSize:o,totalItems:0}),E=()=>{let e=C(m,o),t=w(s,e);x=p,S=T({error:g,isLoading:D.pendingCount()>0,isSearchPending:D.core.isScheduled,pageNumber:t,pageSize:o,totalItems:m})},D=v(t,n,E),{autoFetch:O,debounceMs:k,retryAttempts:A,retryDelay:j}=D;E();let M=()=>{D.disposed||D.core.notify()},N=h(D.core,M),P=e=>{b?.active&&(b.active=!1,b=null),p=e.items,m=e.total,s=w(s,C(m,o))},F=()=>({...d!==void 0&&{filter:d},...f!==void 0&&{sort:f},...c&&{search:c},limit:o,page:s}),I=i=>{let o=n(i);return r>0&&o===y&&m>0&&Date.now()-_<r&&!b?.active?Promise.resolve():(g=null,D.fetch(i,async(n,r,i)=>{let s=Date.now();try{let a=await(0,e.retry)(e=>t.fetch(n,e),{delay:j,signal:r,times:A+1});i()&&(P(a),g=null,y=o,_=Date.now(),t.onFetch?.({durationMs:Date.now()-s,query:n,status:`success`}))}catch(e){if(r.aborted)return;i()&&(b?.active?(b.active=!1,p=b.prevItems,m=b.prevTotal,b=null):(p=[],m=0),g=new u(a(e),{cause:e,context:{kind:`remote`,limit:n.limit,page:n.page,...n.search&&{search:n.search}}}),t.onFetch?.({durationMs:Date.now()-s,error:g,query:n,status:`error`}))}},()=>{M(),N.settleIfIdle(D.pendingCount())}))},L=()=>I(F());return O&&L(),D.startRefreshInterval(()=>void L()),{get current(){return x},get disposalSignal(){return D.disposalSignal},dispose:()=>{N.cancel(),N.dispose(),D.dispose()},get disposed(){return D.disposed},goTo(e){let t=m>0?w(e,C(m,o)):l(e,`source.goTo`,`target`);return t===s?Promise.resolve():(s=t,L())},goToLast(){let e=C(m,o);return s===e?Promise.resolve():(s=e,L())},get meta(){return S},next(){let e=C(m,o);return s>=e?Promise.resolve():(s++,L())},optimisticUpdate(e,t){if(b?.active)throw new u(`An optimistic update is already active. Rollback the previous update before starting another.`);let n=p,r=m;b={active:!0,prevItems:n,prevTotal:r};try{p=e(p)}catch(e){throw b=null,e}return m=t?.total??m,M(),()=>{b?.active&&(b.active=!1,p=n,m=r,b=null,M())}},patch(e){let t=!1;if(e.limit!==void 0){let n=l(e.limit,`source.patch`,`limit`);n!==o&&(o=n,t=!0)}if(`filter`in e&&(d=e.filter,t=!0),`sort`in e&&(f=e.sort,t=!0),`search`in e&&(e.search!==c||D.core.isScheduled)&&(c=e.search??``,t=!0),e.page!==void 0){let n=m>0?w(e.page,C(m,o)):l(e.page,`source.patch`,`page`);n!==s&&(s=n,t=!0)}return t?(N.cancel(),(e.limit!==void 0||`filter`in e||`sort`in e||`search`in e)&&e.page===void 0&&(s=1),L()):Promise.resolve()},prev(){return s<=1?Promise.resolve():(s--,L())},get query(){return{...d!==void 0&&{filter:d},...f!==void 0&&{sort:f},...c&&{search:c},limit:o,page:s}},ready(e){return D.ready(e)},refresh(){return L()},reset(){return N.cancel(),c=``,s=1,d=t.filter,f=t.sort,L()},search(e,t){return t?.immediate?e===c&&!D.core.isScheduled?Promise.resolve():(N.cancel(),c=e,s=1,L()):e===c?Promise.resolve():(c=e,s=1,N.schedule(()=>void L(),k))},subscribe:e=>D.core.subscribe(e),[Symbol.dispose]:()=>{N.cancel(),N.dispose(),D.dispose()}}}var N=e=>{let t=e.query;return{items:e.current,...t.search&&{search:t.search},page:e.meta.pageNumber,total:e.meta.totalItems}};async function P(e){let t=M({...e,autoFetch:!1});try{if(await t.refresh(),t.meta.error)throw t.meta.error;return N(t)}finally{t.dispose()}}async function F(e){let t=M({...e,autoFetch:!1});if(await t.refresh(),t.meta.error)throw t.dispose(),t.meta.error;return{snapshot:N(t),source:t}}var I=e=>{if(e==null)return``;if(typeof e==`bigint`||typeof e==`boolean`||typeof e==`number`||typeof e==`string`)return String(e);if(e instanceof Date)return e.toISOString();try{return JSON.stringify(e)??``}catch{return String(e)}},L=(e,t,n=!1)=>{let r=n?t:t.toLowerCase();return t=>{let i=e(t)??``;return(n?i:i.toLowerCase()).includes(r)}},R=(e,t)=>n=>Object.is(e(n),t),z=(e,t)=>{let n=e=>e instanceof Date?e.getTime():e,r=t.min===void 0?void 0:n(t.min),i=t.max===void 0?void 0:n(t.max);return t=>{let a=n(e(t));return!(r!==void 0&&a<r||i!==void 0&&a>i)}},B=(e,t=`asc`)=>{let n=t===`asc`?1:-1;return(t,r)=>{let i=e(t),a=e(r);return i instanceof Date&&a instanceof Date?(i.getTime()-a.getTime())*n:i<a?-1*n:i>a?1*n:0}},V=(e,t={})=>{let n=Array.isArray(e)?e:[e],r=t.caseSensitive===!0;return(e,t)=>{if(t.length===0)return e;let i=r?t:t.toLowerCase();return e.filter(e=>n.some(t=>{let n=I(t(e));return(r?n:n.toLowerCase()).includes(i)}))}};function H(e){return e.meta.isLoading||e.meta.isSearchPending?{status:`loading`}:e.meta.error?{error:e.meta.error,status:`error`}:{items:e.current,status:`success`}}exports.SourcererDisposedError=f,exports.SourcererError=u,exports.SourcererTimeoutError=d,exports.createCursorSource=y,exports.createInfiniteSource=x,exports.createLocalSource=A,exports.createRemoteSource=M,exports.decodeQuery=m,exports.deriveSource=b,exports.encodeQuery=p,exports.filterContains=L,exports.filterEquals=R,exports.filterRange=z,exports.itemRange=E,exports.mergeSource=j,exports.prefetchSource=P,exports.prefetchSourceAndKeep=F,exports.searchBy=V,exports.sortBy=B,exports.sourceState=H;
|
|
2
2
|
//# sourceMappingURL=sourcerer.cjs.map
|