@kanzo-tech/graph 0.2.0 → 0.4.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/README.md +15 -7
- package/dist/bounded.d.ts +8 -33
- package/dist/bounded.d.ts.map +1 -1
- package/dist/bounded.js.map +1 -1
- package/dist/duck-source.d.ts +105 -74
- package/dist/duck-source.d.ts.map +1 -1
- package/dist/duck-source.js +264 -296
- package/dist/duck-source.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -14
- package/dist/index.js.map +1 -1
- package/dist/use-graph.d.ts +0 -2
- package/dist/use-graph.d.ts.map +1 -1
- package/dist/use-graph.js +26 -26
- package/dist/use-graph.js.map +1 -1
- package/dist/use-query-loop.d.ts +2 -4
- package/dist/use-query-loop.d.ts.map +1 -1
- package/dist/use-query-loop.js +104 -125
- package/dist/use-query-loop.js.map +1 -1
- package/package.json +11 -5
- package/dist/memory-source.d.ts +0 -32
- package/dist/memory-source.d.ts.map +0 -1
- package/dist/memory-source.js +0 -141
- package/dist/memory-source.js.map +0 -1
package/dist/duck-source.js
CHANGED
|
@@ -1,118 +1,72 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
2
|
+
import { open as le, PAYLOAD_COORDINATES as v, PAYLOAD_IDENTITY as ue, PAYLOAD_ADDRESS as de } from "@fossil-lang/corpus";
|
|
3
|
+
import { numbers as I, clausePoints as Ee, fillColumn as _, column as pe } from "@kanzo-tech/mosaic";
|
|
4
|
+
import { SliceRead as k } from "./slice-client.js";
|
|
5
|
+
import { typeOf as ye, denseOf as X, vertexId as me } from "./resident.js";
|
|
6
|
+
const Z = 0;
|
|
7
|
+
function Ae(e, t) {
|
|
6
8
|
return {
|
|
7
|
-
points: new
|
|
8
|
-
links: new
|
|
9
|
-
meta: new
|
|
9
|
+
points: new k(e, t),
|
|
10
|
+
links: new k(e, t),
|
|
11
|
+
meta: new k(e)
|
|
10
12
|
};
|
|
11
13
|
}
|
|
12
|
-
function
|
|
13
|
-
let
|
|
14
|
+
function $e(e) {
|
|
15
|
+
let t = Promise.resolve();
|
|
14
16
|
return (n) => {
|
|
15
|
-
const s =
|
|
16
|
-
return
|
|
17
|
+
const s = t.then(() => e.ask(() => n));
|
|
18
|
+
return t = s.catch(() => {
|
|
17
19
|
}), s;
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
|
-
function
|
|
21
|
-
if (
|
|
22
|
-
const n = (Array.isArray(
|
|
22
|
+
function q(e) {
|
|
23
|
+
if (e == null) return "";
|
|
24
|
+
const n = (Array.isArray(e) ? e : [e]).filter((s) => s != null).map((s) => String(s));
|
|
23
25
|
return n.length > 0 ? n.map((s) => `(${s})`).join(" AND ") : "";
|
|
24
26
|
}
|
|
25
|
-
function
|
|
26
|
-
return
|
|
27
|
+
function K(e, t) {
|
|
28
|
+
return e ? t ? `(${e}) AND (${t})` : e : t || "TRUE";
|
|
27
29
|
}
|
|
28
|
-
function
|
|
29
|
-
const { coordinator: e, edges: n, filterBy: s, nodes: r, typeIndex: i } = t, c = {
|
|
30
|
-
id: t.idField ?? "id",
|
|
31
|
-
subject: t.subjectField,
|
|
32
|
-
x: t.xField ?? "x",
|
|
33
|
-
y: t.yField ?? "y",
|
|
34
|
-
source: t.sourceField ?? "source",
|
|
35
|
-
target: t.targetField ?? "target"
|
|
36
|
-
}, l = et(e, s), E = nt(l.meta), y = it(l);
|
|
37
|
-
return {
|
|
38
|
-
...y.api,
|
|
39
|
-
publish(p) {
|
|
40
|
-
ot(l, s, c.id, p);
|
|
41
|
-
},
|
|
42
|
-
async total() {
|
|
43
|
-
const p = await E(`SELECT count(*) AS n FROM ${r}`);
|
|
44
|
-
return Number(k(p, "n")[0] ?? 0);
|
|
45
|
-
},
|
|
46
|
-
/**
|
|
47
|
-
* Four aggregates, so the canvas can frame what is actually there.
|
|
48
|
-
*
|
|
49
|
-
* One scan of two columns, once — against a first paint that otherwise opens on the renderer's
|
|
50
|
-
* default box and finds the corpus occupying a corner of it.
|
|
51
|
-
*/
|
|
52
|
-
async extent() {
|
|
53
|
-
const p = await E(
|
|
54
|
-
`SELECT min(${c.x}) AS x0, max(${c.x}) AS x1,
|
|
55
|
-
min(${c.y}) AS y0, max(${c.y}) AS y1
|
|
56
|
-
FROM ${r}`
|
|
57
|
-
), x = (f) => Number(k(p, f)[0] ?? 0);
|
|
58
|
-
return { xMin: x("x0"), yMin: x("y0"), xMax: x("x1"), yMax: x("y1") };
|
|
59
|
-
},
|
|
60
|
-
/**
|
|
61
|
-
* Regions only, and it says so by **not having** `explore`.
|
|
62
|
-
*
|
|
63
|
-
* This source is two relations and a spatial predicate — it has no adjacency index, so a
|
|
64
|
-
* neighbourhood query would mean recursive joins over the whole edge table, which is the
|
|
65
|
-
* unbounded pattern wearing a bounded interface. It used to say that with a predicate and a
|
|
66
|
-
* throw; now the absence is the statement, and asking is a compile error.
|
|
67
|
-
*/
|
|
68
|
-
async slice(p) {
|
|
69
|
-
const { fill: x, limit: f, minLinkPixels: N, perPixel: $, pinned: O, r: g, view: F } = p, A = { ...c, category: x, size: g };
|
|
70
|
-
return y.run(
|
|
71
|
-
rt(r, n, A, F, f, i, O, $, N, void 0)
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
function St(t, e) {
|
|
30
|
+
function Se(e, t) {
|
|
77
31
|
const s = [
|
|
78
|
-
[
|
|
79
|
-
[
|
|
80
|
-
[
|
|
81
|
-
[
|
|
82
|
-
].filter(([,
|
|
32
|
+
[e.x, t.xMin, ">="],
|
|
33
|
+
[e.x, t.xMax, "<="],
|
|
34
|
+
[e.y, t.yMin, ">="],
|
|
35
|
+
[e.y, t.yMax, "<="]
|
|
36
|
+
].filter(([, a]) => Number.isFinite(a)).map(([a, i, c]) => `${a} ${c} ${i}`);
|
|
83
37
|
return s.length > 0 ? s.join(" AND ") : "TRUE";
|
|
84
38
|
}
|
|
85
|
-
const
|
|
86
|
-
function
|
|
87
|
-
const i =
|
|
39
|
+
const fe = (e) => `greatest(1, CAST(ceil(matched / ${e}.0) AS BIGINT))`;
|
|
40
|
+
function V(e, t, n, s, a = !0) {
|
|
41
|
+
const i = t.size ? `, ${t.size} AS size` : "", c = t.subject ? `, ${t.subject} AS subject` : "", p = t.category ? "(dense_rank() OVER (ORDER BY cat) - 1)::INTEGER AS category" : "0::INTEGER AS category";
|
|
88
42
|
return `WITH pool AS (
|
|
89
|
-
SELECT ${
|
|
43
|
+
SELECT ${t.id} AS id, ${t.x} AS x, ${t.y} AS y${i}${c}${t.category ? `, ${t.category} AS cat` : ""},
|
|
90
44
|
count(*) OVER () AS matched
|
|
91
|
-
FROM ${
|
|
45
|
+
FROM ${e}
|
|
92
46
|
WHERE ${n}
|
|
93
47
|
), vis AS (
|
|
94
|
-
SELECT id, x, y${
|
|
95
|
-
${
|
|
48
|
+
SELECT id, x, y${t.size ? ", size" : ""}${t.subject ? ", subject" : ""}${a ? ", matched" : ""},
|
|
49
|
+
${p},
|
|
96
50
|
(row_number() OVER (ORDER BY id) - 1)::INTEGER AS local
|
|
97
51
|
FROM pool
|
|
98
|
-
WHERE id % ${
|
|
52
|
+
WHERE id % ${fe(s)} = 0
|
|
99
53
|
LIMIT ${s}
|
|
100
54
|
)`;
|
|
101
55
|
}
|
|
102
|
-
function
|
|
56
|
+
function Te(e, t, n, s) {
|
|
103
57
|
if (n === void 0 || !Number.isFinite(n) || n <= 0) return "";
|
|
104
|
-
const
|
|
105
|
-
return `(${
|
|
58
|
+
const a = s * n;
|
|
59
|
+
return `(${e}.x - ${t}.x) * (${e}.x - ${t}.x) + (${e}.y - ${t}.y) * (${e}.y - ${t}.y) >= ${a * a}`;
|
|
106
60
|
}
|
|
107
|
-
function
|
|
108
|
-
const
|
|
61
|
+
function Ne(e, t, n, s, a, i, c) {
|
|
62
|
+
const p = K(`NOT (${s})`, a), E = Te("a", "b", i, c);
|
|
109
63
|
return `, out AS (
|
|
110
|
-
SELECT ${n.id} AS id, ${n.x} AS x, ${n.y} AS y FROM ${
|
|
64
|
+
SELECT ${n.id} AS id, ${n.x} AS x, ${n.y} AS y FROM ${e} WHERE ${p}
|
|
111
65
|
), reach AS (
|
|
112
66
|
SELECT id, x, y FROM vis UNION ALL SELECT id, x, y FROM out
|
|
113
67
|
), span AS (
|
|
114
68
|
SELECT sv.local AS src, tv.local AS dst, a.id AS src_id, b.id AS dst_id
|
|
115
|
-
FROM ${
|
|
69
|
+
FROM ${t} e
|
|
116
70
|
JOIN reach a ON e.${n.source} = a.id
|
|
117
71
|
JOIN reach b ON e.${n.target} = b.id
|
|
118
72
|
LEFT JOIN vis sv ON sv.id = a.id
|
|
@@ -126,8 +80,8 @@ function ft(t, e, n, s, r, i, c) {
|
|
|
126
80
|
UNION SELECT dst_id FROM span WHERE dst IS NULL)
|
|
127
81
|
)`;
|
|
128
82
|
}
|
|
129
|
-
function
|
|
130
|
-
const
|
|
83
|
+
function he(e, t, n, s, a, i, c, p) {
|
|
84
|
+
const E = Se(n, s), h = (i ?? []).filter((u) => ye(u) === Z).map(X), b = h.length > 0 ? ` OR ${n.id} IN (${h.join(",")})` : "", S = `(${E})${b}`, y = (u) => K(S, q(u)), f = n.size ? ", size" : "", w = n.subject ? ", subject" : "", T = (u) => Ne(e, t, n, S, q(u), c, p);
|
|
131
85
|
return {
|
|
132
86
|
/**
|
|
133
87
|
* The marks, then the anchors, in one answer — because they are one buffer.
|
|
@@ -136,30 +90,26 @@ function rt(t, e, n, s, r, i, c, l, E, y) {
|
|
|
136
90
|
* and continues past it over the anchors, so ordering by it puts every mark before every anchor
|
|
137
91
|
* and makes `marks` a prefix length. `matched` is then still read off row zero.
|
|
138
92
|
*/
|
|
139
|
-
points: (u) => `${
|
|
140
|
-
SELECT local, id, x, y, category, matched, TRUE AS mark${
|
|
93
|
+
points: (u) => `${V(e, n, y(u), a)}${T(u)}
|
|
94
|
+
SELECT local, id, x, y, category, matched, TRUE AS mark${f}${w} FROM vis
|
|
141
95
|
UNION ALL
|
|
142
|
-
SELECT local, id, x, y, 0::INTEGER, NULL::BIGINT, FALSE AS mark${n.size ? ", CAST(NULL AS DOUBLE)" : ""}${n.subject ? ", CAST(NULL AS VARCHAR)" : ""} FROM anchor
|
|
96
|
+
SELECT local, id, x, y, 0::INTEGER, NULL::BIGINT, FALSE AS mark${n.size ? ", CAST(NULL AS DOUBLE)" : ""}${n.subject ? ", CAST(NULL AS VARCHAR)" : ""} FROM anchor
|
|
143
97
|
ORDER BY local`,
|
|
144
98
|
/**
|
|
145
|
-
* One end drawn and both ends positioned
|
|
99
|
+
* One end drawn and both ends positioned.
|
|
146
100
|
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
101
|
+
* There was a second form here — both ends drawn, edges leaving the window dropped — for a source
|
|
102
|
+
* that fetched no bytes beyond the rectangle and therefore had no position to put a far end at.
|
|
103
|
+
* It went with that source, and `longEnough` with it — the length predicate lives in `anchorCte`
|
|
104
|
+
* now, on the same span, which is where it has to sit once the join runs over the held rows
|
|
105
|
+
* rather than over the visible ones.
|
|
151
106
|
*/
|
|
152
|
-
links: (u) =>
|
|
107
|
+
links: (u) => `${V(e, n, y(u), a, !1)}${T(u)}
|
|
153
108
|
SELECT coalesce(sp.src, sa.local) AS src, coalesce(sp.dst, da.local) AS dst
|
|
154
109
|
FROM span sp
|
|
155
110
|
LEFT JOIN anchor sa ON sa.id = sp.src_id
|
|
156
|
-
LEFT JOIN anchor da ON da.id = sp.dst_id
|
|
157
|
-
|
|
158
|
-
FROM ${e} e
|
|
159
|
-
JOIN vis s ON e.${n.source} = s.id
|
|
160
|
-
JOIN vis t ON e.${n.target} = t.id${F ? `
|
|
161
|
-
WHERE ${F}` : ""}`,
|
|
162
|
-
assemble: (u, D) => ({
|
|
111
|
+
LEFT JOIN anchor da ON da.id = sp.dst_id`,
|
|
112
|
+
assemble: (u, R) => ({
|
|
163
113
|
/**
|
|
164
114
|
* How many matched, separately from how many came back.
|
|
165
115
|
*
|
|
@@ -168,17 +118,17 @@ function rt(t, e, n, s, r, i, c, l, E, y) {
|
|
|
168
118
|
* has been about. Read off the first row rather than asked for: `matched` is constant down the
|
|
169
119
|
* column, and an empty answer has no row and no matches, which agree.
|
|
170
120
|
*/
|
|
171
|
-
n: Number(
|
|
172
|
-
...
|
|
121
|
+
n: Number(I(u, "matched")[0] ?? 0),
|
|
122
|
+
...xe(u, R, n.size ? "size" : void 0, n.subject !== void 0)
|
|
173
123
|
})
|
|
174
124
|
};
|
|
175
125
|
}
|
|
176
|
-
function
|
|
177
|
-
let
|
|
178
|
-
const s = /* @__PURE__ */ new Map(),
|
|
179
|
-
if (!
|
|
180
|
-
const
|
|
181
|
-
s.clear(), n(
|
|
126
|
+
function Re(e) {
|
|
127
|
+
let t = null, n = null;
|
|
128
|
+
const s = /* @__PURE__ */ new Map(), a = (i) => (c) => {
|
|
129
|
+
if (!t || !n || (s.set(i, c), s.size < 2)) return;
|
|
130
|
+
const p = s.get("points"), E = s.get("links");
|
|
131
|
+
s.clear(), n(t.assemble(p, E));
|
|
182
132
|
};
|
|
183
133
|
return {
|
|
184
134
|
api: {
|
|
@@ -190,223 +140,241 @@ function it(t) {
|
|
|
190
140
|
* again would run the same two queries a second time to learn what is in hand.
|
|
191
141
|
*/
|
|
192
142
|
watch(i) {
|
|
193
|
-
return n = i,
|
|
194
|
-
n = null, s.clear(),
|
|
143
|
+
return n = i, e.points.onAnswer = a("points"), e.links.onAnswer = a("links"), () => {
|
|
144
|
+
n = null, s.clear(), t = null, e.points.release(), e.links.release(), e.meta.release();
|
|
195
145
|
};
|
|
196
146
|
}
|
|
197
147
|
},
|
|
198
148
|
async run(i) {
|
|
199
|
-
|
|
200
|
-
const [c,
|
|
201
|
-
|
|
202
|
-
|
|
149
|
+
t = i, s.clear();
|
|
150
|
+
const [c, p] = await Promise.all([
|
|
151
|
+
e.points.ask(i.points),
|
|
152
|
+
e.links.ask(i.links)
|
|
203
153
|
]);
|
|
204
|
-
return i.assemble(c,
|
|
154
|
+
return i.assemble(c, p);
|
|
205
155
|
}
|
|
206
156
|
};
|
|
207
157
|
}
|
|
208
|
-
function
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
source:
|
|
212
|
-
clients: /* @__PURE__ */ new Set([
|
|
158
|
+
function Oe(e, t, n, s) {
|
|
159
|
+
t && t.update(
|
|
160
|
+
Ee([n], s == null ? void 0 : s.map((a) => [X(a)]), {
|
|
161
|
+
source: e.points,
|
|
162
|
+
clients: /* @__PURE__ */ new Set([e.points, e.links])
|
|
213
163
|
})
|
|
214
164
|
);
|
|
215
165
|
}
|
|
216
|
-
function
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
let
|
|
222
|
-
for (;
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
const
|
|
226
|
-
for (let
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
let
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
return
|
|
234
|
-
marks:
|
|
235
|
-
vertices:
|
|
236
|
-
subjects:
|
|
237
|
-
positions:
|
|
238
|
-
links:
|
|
239
|
-
categories:
|
|
240
|
-
sizes:
|
|
166
|
+
function xe(e, t, n, s = !1) {
|
|
167
|
+
const a = J(e, "x"), i = new Float32Array(a * 2), c = _(e, "x", i, 0, 2);
|
|
168
|
+
_(e, "y", i, 1, 2);
|
|
169
|
+
const p = new Int32Array(a);
|
|
170
|
+
_(e, "mark", p);
|
|
171
|
+
let E = 0;
|
|
172
|
+
for (; E < c && p[E] !== 0; ) E++;
|
|
173
|
+
const h = new Float64Array(c);
|
|
174
|
+
_(e, "id", h);
|
|
175
|
+
const b = new BigUint64Array(c);
|
|
176
|
+
for (let R = 0; R < c; R++) b[R] = me(Z, h[R]);
|
|
177
|
+
const S = new Uint16Array(c);
|
|
178
|
+
_(e, "category", S);
|
|
179
|
+
const y = s ? pe(e, "subject") : void 0;
|
|
180
|
+
let f;
|
|
181
|
+
n && (f = new Float32Array(c), _(e, n, f));
|
|
182
|
+
const w = J(t, "src"), T = new Float32Array(w * 2), u = _(t, "src", T, 0, 2);
|
|
183
|
+
return _(t, "dst", T, 1, 2), {
|
|
184
|
+
marks: E,
|
|
185
|
+
vertices: b,
|
|
186
|
+
subjects: y,
|
|
187
|
+
positions: i.subarray(0, c * 2),
|
|
188
|
+
links: T.subarray(0, u * 2),
|
|
189
|
+
categories: S,
|
|
190
|
+
sizes: f
|
|
241
191
|
};
|
|
242
192
|
}
|
|
243
|
-
function
|
|
244
|
-
var
|
|
245
|
-
const n =
|
|
193
|
+
function J(e, t) {
|
|
194
|
+
var a;
|
|
195
|
+
const n = e == null ? void 0 : e.numRows;
|
|
246
196
|
if (typeof n == "number") return n;
|
|
247
|
-
const s = (
|
|
248
|
-
return s ? s.length : Array.from(
|
|
249
|
-
}
|
|
250
|
-
function I(t, e) {
|
|
251
|
-
const n = t.split(`
|
|
252
|
-
`).find((s) => s.startsWith(`${e}:`));
|
|
253
|
-
return n == null ? void 0 : n.slice(e.length + 1).trim().replace(/^['"]|['"]$/g, "");
|
|
197
|
+
const s = (a = e == null ? void 0 : e.getChild) == null ? void 0 : a.call(e, t);
|
|
198
|
+
return s ? s.length : Array.from(e).length;
|
|
254
199
|
}
|
|
255
|
-
function
|
|
256
|
-
const n =
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
200
|
+
function Le(e, t) {
|
|
201
|
+
const n = [], s = [];
|
|
202
|
+
for (const a of e) {
|
|
203
|
+
const i = { edgeType: a.edgeType, srcType: a.srcType, dstType: a.dstType };
|
|
204
|
+
if (a.srcType !== t || a.dstType !== t) {
|
|
205
|
+
s.push({ ...i, reason: "other-space" });
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const c = a.adjacency("src");
|
|
209
|
+
if (c === null) {
|
|
210
|
+
s.push({ ...i, reason: "not-declared" });
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
n.push({
|
|
214
|
+
...i,
|
|
215
|
+
address: a,
|
|
216
|
+
adjacency: c,
|
|
217
|
+
view: `corpus_${a.srcType}_${a.edgeType}_${a.dstType}`
|
|
218
|
+
});
|
|
263
219
|
}
|
|
264
|
-
return
|
|
220
|
+
return { drawn: n, undrawn: s };
|
|
265
221
|
}
|
|
266
|
-
async function
|
|
267
|
-
const
|
|
268
|
-
if (!
|
|
269
|
-
return
|
|
222
|
+
async function ge(e) {
|
|
223
|
+
const t = await fetch(e);
|
|
224
|
+
if (!t.ok) throw new Error(`corpus: ${e} is not readable (${t.status})`);
|
|
225
|
+
return t.text();
|
|
270
226
|
}
|
|
271
|
-
async function
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
throw new Error(`corpus: ${n} declares no usable type, prefix and chunk_size`);
|
|
280
|
-
const A = (await Promise.all(x.map((a) => P(n, a)))).find((a) => I(a, "src_type") === $), u = A ? I(A, "prefix") : void 0;
|
|
281
|
-
let D = null, G;
|
|
282
|
-
const j = (a) => `'${n}/${O}chunk${a}.parquet'`, ct = (a) => `'${n}/${u}by_source/tile${a}.parquet'`, lt = async () => {
|
|
283
|
-
var o;
|
|
284
|
-
const a = (o = e.databaseConnector) == null ? void 0 : o.call(e);
|
|
285
|
-
if (!(a != null && a.getDuckDB)) return null;
|
|
227
|
+
async function Fe(e) {
|
|
228
|
+
var z, G, P;
|
|
229
|
+
const { coordinator: t, dest: n, filterBy: s, readText: a = ge, subjects: i = !1, vertexType: c, wasmUrl: p } = e, E = Ae(t, s), h = $e(E.meta), b = Re(E), S = await le(n, { readText: a, wasmUrl: p }), y = S.vertexType(c), { drawn: f, undrawn: w } = Le(S.incident(y.type), y.type), T = f.map((o) => o.adjacency);
|
|
230
|
+
let u = null;
|
|
231
|
+
const R = async () => {
|
|
232
|
+
var r;
|
|
233
|
+
const o = (r = t.databaseConnector) == null ? void 0 : r.call(t);
|
|
234
|
+
if (!(o != null && o.getDuckDB)) return null;
|
|
286
235
|
try {
|
|
287
|
-
return await
|
|
236
|
+
return await o.getDuckDB();
|
|
288
237
|
} catch {
|
|
289
238
|
return null;
|
|
290
239
|
}
|
|
291
|
-
},
|
|
292
|
-
let
|
|
293
|
-
const
|
|
294
|
-
async function
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
const _ = await fetch(
|
|
304
|
-
if (!
|
|
305
|
-
|
|
306
|
-
|
|
240
|
+
}, C = /* @__PURE__ */ new Map(), F = /* @__PURE__ */ new Map();
|
|
241
|
+
let M = 0;
|
|
242
|
+
const Q = 64 * 1024 * 1024, ee = 256 * 1024;
|
|
243
|
+
async function j(o) {
|
|
244
|
+
if (o.length === 0) return [];
|
|
245
|
+
const r = await R();
|
|
246
|
+
if (!r) return o.map((l) => `'${l}'`);
|
|
247
|
+
const d = await Promise.all(
|
|
248
|
+
o.map(async (l) => {
|
|
249
|
+
const m = F.get(l);
|
|
250
|
+
if (m !== void 0 && (m.startsWith("'") || C.has(m)))
|
|
251
|
+
return m;
|
|
252
|
+
const O = `corpus_${l.replace(/[^A-Za-z0-9]+/g, "_")}`, x = await fetch(l, { method: "HEAD" }), A = Number(x.headers.get("content-length"));
|
|
253
|
+
if (!x.ok || !Number.isFinite(A) || A > ee) {
|
|
254
|
+
const L = `'${l}'`;
|
|
255
|
+
return F.set(l, L), L;
|
|
256
|
+
}
|
|
257
|
+
const N = await fetch(l);
|
|
258
|
+
if (!N.ok) return `'${l}'`;
|
|
259
|
+
const $ = new Uint8Array(await N.arrayBuffer());
|
|
260
|
+
return await r.registerFileBuffer(O, $), C.set(O, $.byteLength), F.set(l, O), M += $.byteLength, O;
|
|
307
261
|
})
|
|
308
262
|
);
|
|
309
|
-
for (;
|
|
310
|
-
const [
|
|
311
|
-
if (
|
|
312
|
-
|
|
263
|
+
for (; M > Q && C.size > 0; ) {
|
|
264
|
+
const [l, m] = C.entries().next().value;
|
|
265
|
+
if (d.includes(l)) break;
|
|
266
|
+
C.delete(l), M -= m, await r.dropFile(l);
|
|
313
267
|
}
|
|
314
|
-
return
|
|
268
|
+
return d.map((l) => l.startsWith("'") ? l : `'${l}'`);
|
|
315
269
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
max(CASE WHEN path_in_schema = 'x' THEN coalesce(stats_max_value, stats_max)::DOUBLE END) AS x1,
|
|
335
|
-
min(CASE WHEN path_in_schema = 'y' THEN coalesce(stats_min_value, stats_min)::DOUBLE END) AS y0,
|
|
336
|
-
max(CASE WHEN path_in_schema = 'y' THEN coalesce(stats_max_value, stats_max)::DOUBLE END) AS y1
|
|
337
|
-
FROM parquet_metadata([${m}])
|
|
338
|
-
WHERE path_in_schema IN ('x', 'y') GROUP BY 1 ORDER BY 1`
|
|
339
|
-
), b = k(S, "tile"), [w, T, _, R] = ["x0", "x1", "y0", "y1"].map((h) => k(S, h));
|
|
340
|
-
return b.map((h, L) => ({
|
|
341
|
-
tile: h,
|
|
342
|
-
x0: w == null ? void 0 : w[L],
|
|
343
|
-
x1: T == null ? void 0 : T[L],
|
|
344
|
-
y0: _ == null ? void 0 : _[L],
|
|
345
|
-
y1: R == null ? void 0 : R[L]
|
|
270
|
+
const H = y.files(), D = (o) => o.map((r) => `'${r.replace(/'/g, "''")}'`).join(", ");
|
|
271
|
+
function B() {
|
|
272
|
+
return u ?? (u = (async () => {
|
|
273
|
+
const o = D(H), [r, d] = v, l = S.container === "rowgroups" ? "row_group_id" : `list_position([${o}], file_name) - 1`, m = await h(
|
|
274
|
+
`SELECT ${l} AS tile,
|
|
275
|
+
min(CASE WHEN path_in_schema = '${r}' THEN coalesce(stats_min_value, stats_min)::DOUBLE END) AS x0,
|
|
276
|
+
max(CASE WHEN path_in_schema = '${r}' THEN coalesce(stats_max_value, stats_max)::DOUBLE END) AS x1,
|
|
277
|
+
min(CASE WHEN path_in_schema = '${d}' THEN coalesce(stats_min_value, stats_min)::DOUBLE END) AS y0,
|
|
278
|
+
max(CASE WHEN path_in_schema = '${d}' THEN coalesce(stats_max_value, stats_max)::DOUBLE END) AS y1
|
|
279
|
+
FROM parquet_metadata([${o}])
|
|
280
|
+
WHERE path_in_schema IN ('${r}', '${d}') GROUP BY 1 ORDER BY 1`
|
|
281
|
+
), O = I(m, "tile"), [x, A, N, $] = ["x0", "x1", "y0", "y1"].map((L) => I(m, L));
|
|
282
|
+
return O.map((L, g) => ({
|
|
283
|
+
tile: L,
|
|
284
|
+
x0: x == null ? void 0 : x[g],
|
|
285
|
+
x1: A == null ? void 0 : A[g],
|
|
286
|
+
y0: N == null ? void 0 : N[g],
|
|
287
|
+
y1: $ == null ? void 0 : $[g]
|
|
346
288
|
}));
|
|
347
|
-
})()),
|
|
289
|
+
})()), u;
|
|
348
290
|
}
|
|
349
|
-
function
|
|
350
|
-
return
|
|
291
|
+
function te(o, r) {
|
|
292
|
+
return o.filter((d) => d.x1 >= r.xMin && d.x0 <= r.xMax && d.y1 >= r.yMin && d.y0 <= r.yMax).map((d) => d.tile);
|
|
351
293
|
}
|
|
352
|
-
const
|
|
353
|
-
id:
|
|
354
|
-
subject:
|
|
355
|
-
x:
|
|
356
|
-
y:
|
|
357
|
-
source: "src_dense",
|
|
358
|
-
target: "dst_dense"
|
|
359
|
-
},
|
|
360
|
-
|
|
361
|
-
`CREATE OR REPLACE VIEW ${
|
|
362
|
-
)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
294
|
+
const W = {
|
|
295
|
+
id: de[0],
|
|
296
|
+
subject: i ? ue[0] : void 0,
|
|
297
|
+
x: v[0],
|
|
298
|
+
y: v[1],
|
|
299
|
+
source: ((z = T[0]) == null ? void 0 : z.column) ?? "src_dense",
|
|
300
|
+
target: ((P = (G = f[0]) == null ? void 0 : G.address.adjacency("dst")) == null ? void 0 : P.column) ?? "dst_dense"
|
|
301
|
+
}, U = `corpus_${y.type}`;
|
|
302
|
+
await t.exec(
|
|
303
|
+
`CREATE OR REPLACE VIEW ${U} AS SELECT * FROM read_parquet([${D(H)}])`
|
|
304
|
+
);
|
|
305
|
+
for (const o of f)
|
|
306
|
+
await t.exec(
|
|
307
|
+
`CREATE OR REPLACE VIEW ${o.view} AS
|
|
308
|
+
SELECT * FROM read_parquet([${D(o.address.projectionFiles(1, "src"))}])`
|
|
309
|
+
);
|
|
310
|
+
return {
|
|
311
|
+
source: {
|
|
312
|
+
...b.api,
|
|
313
|
+
publish(o) {
|
|
314
|
+
Oe(E, s, W.id, o);
|
|
315
|
+
},
|
|
316
|
+
/**
|
|
317
|
+
* How many vertices there are — **read, not probed.**
|
|
318
|
+
*
|
|
319
|
+
* The manifest declares `vertex_count`. What stood here was a note saying no manifest carries
|
|
320
|
+
* it, and a doubling-then-bisecting `HEAD` search for the last chunk plus a
|
|
321
|
+
* `parquet_file_metadata` read of its row count — about a dozen requests and a query, per
|
|
322
|
+
* corpus, for a number already in hand.
|
|
323
|
+
*/
|
|
324
|
+
async total() {
|
|
325
|
+
if (y.count !== null) return Number(y.count);
|
|
326
|
+
const o = await h(`SELECT count(*) AS n FROM ${U}`);
|
|
327
|
+
return Number(I(o, "n")[0] ?? 0);
|
|
328
|
+
},
|
|
329
|
+
async extent() {
|
|
330
|
+
const o = await B();
|
|
388
331
|
return {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
links: new Float32Array(0),
|
|
394
|
-
categories: new Uint16Array(0)
|
|
332
|
+
xMin: Math.min(...o.map((r) => r.x0)),
|
|
333
|
+
yMin: Math.min(...o.map((r) => r.y0)),
|
|
334
|
+
xMax: Math.max(...o.map((r) => r.x1)),
|
|
335
|
+
yMax: Math.max(...o.map((r) => r.y1))
|
|
395
336
|
};
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
337
|
+
},
|
|
338
|
+
// Regions only, and it says so by being the only method there is. A neighbourhood needs
|
|
339
|
+
// adjacency this source does not index; `ExploringSource` declared the second question here and
|
|
340
|
+
// was deleted with it — `index.test.ts` carries why, and fossil's `expand` is what answers it.
|
|
341
|
+
async slice(o) {
|
|
342
|
+
const { fill: r, limit: d, minLinkPixels: l, perPixel: m, pinned: O, r: x, signal: A, view: N } = o, $ = { ...W, category: r, size: x }, L = await B(), g = te(L, N);
|
|
343
|
+
if (g.length === 0)
|
|
344
|
+
return {
|
|
345
|
+
n: 0,
|
|
346
|
+
marks: 0,
|
|
347
|
+
vertices: new BigUint64Array(0),
|
|
348
|
+
positions: new Float32Array(0),
|
|
349
|
+
links: new Float32Array(0),
|
|
350
|
+
categories: new Uint16Array(0)
|
|
351
|
+
};
|
|
352
|
+
const ne = S.tilesFor({
|
|
353
|
+
type: y.type,
|
|
354
|
+
tiles: g,
|
|
355
|
+
directions: ["src"]
|
|
356
|
+
}), se = [
|
|
357
|
+
...new Set(T.flatMap((ie) => g.map((ce) => ie.tileUrl(ce))))
|
|
358
|
+
], [ae, Y] = await Promise.all([
|
|
359
|
+
j(ne.vertexUrls),
|
|
360
|
+
j(se)
|
|
361
|
+
]);
|
|
362
|
+
if (A != null && A.aborted) throw A.reason;
|
|
363
|
+
const oe = `read_parquet([${ae.join(", ")}])`, re = Y.length > 0 ? `read_parquet([${Y.join(", ")}])` : `(SELECT NULL::BIGINT AS ${$.source}, NULL::BIGINT AS ${$.target} WHERE FALSE)`;
|
|
364
|
+
return b.run(he(oe, re, $, N, d, O, m, l));
|
|
365
|
+
}
|
|
366
|
+
},
|
|
367
|
+
nodes: U,
|
|
368
|
+
edges: f.map(({ edgeType: o, srcType: r, dstType: d, view: l }) => ({
|
|
369
|
+
edgeType: o,
|
|
370
|
+
srcType: r,
|
|
371
|
+
dstType: d,
|
|
372
|
+
view: l
|
|
373
|
+
})),
|
|
374
|
+
undrawn: w
|
|
375
|
+
};
|
|
407
376
|
}
|
|
408
377
|
export {
|
|
409
|
-
|
|
410
|
-
Tt as openCorpus
|
|
378
|
+
Fe as openCorpus
|
|
411
379
|
};
|
|
412
380
|
//# sourceMappingURL=duck-source.js.map
|