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