@qaecy/cue-sdk 0.0.26 → 0.0.28
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 +130 -0
- package/{cue-BjbRXItA.js → cue-BR7V1Nem.js} +982 -854
- package/index.d.ts +2 -0
- package/index.js +17 -16
- package/lib/api.d.ts +3 -0
- package/lib/auth.d.ts +2 -0
- package/lib/documents.d.ts +59 -0
- package/lib/entities.d.ts +22 -0
- package/lib/extraction.d.ts +48 -0
- package/node.js +19 -18
- package/package.json +1 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { getApps as
|
|
2
|
-
import { ref as _, getDownloadURL as
|
|
3
|
-
import { Writer as
|
|
4
|
-
import { getFirestore as
|
|
5
|
-
import { getAuth as
|
|
6
|
-
import { v5 as
|
|
1
|
+
import { getApps as be, initializeApp as ve } from "firebase/app";
|
|
2
|
+
import { ref as _, getDownloadURL as K, getMetadata as M, getBlob as re, updateMetadata as _e, uploadBytesResumable as ft, uploadBytes as st, StringFormat as ke, uploadString as Ee, listAll as z, getStorage as T, connectStorageEmulator as Q } from "firebase/storage";
|
|
3
|
+
import { Writer as xe, DataFactory as j } from "n3";
|
|
4
|
+
import { getFirestore as Ie, connectFirestoreEmulator as Ce, collection as yt, getDocs as Te, query as Se, where as Re, limit as Ae, doc as bt, getDoc as Pe, setDoc as Oe, serverTimestamp as De, increment as Le } from "firebase/firestore";
|
|
5
|
+
import { getAuth as qe, connectAuthEmulator as je, onIdTokenChanged as Ue, getIdTokenResult as at, signInWithEmailAndPassword as Me, GoogleAuthProvider as it, OAuthProvider as nt, signInWithPopup as ze, signInWithRedirect as Ne, getRedirectResult as $e, signInWithCustomToken as vt, signOut as Fe, onAuthStateChanged as Be, fetchSignInMethodsForEmail as Ge, linkWithPopup as He, unlink as We, reauthenticateWithCredential as _t, EmailAuthProvider as X, updatePassword as Ve, linkWithCredential as Ke, verifyBeforeUpdateEmail as Qe, sendEmailVerification as Xe } from "firebase/auth";
|
|
6
|
+
import { v5 as Ye } from "uuid";
|
|
7
7
|
import "spark-md5";
|
|
8
|
-
import { getFunctions as
|
|
9
|
-
class
|
|
8
|
+
import { getFunctions as se, connectFunctionsEmulator as ae, httpsCallable as F } from "firebase/functions";
|
|
9
|
+
class ht {
|
|
10
10
|
queryEndpoint;
|
|
11
11
|
updateEndpoint;
|
|
12
12
|
baseHeaders;
|
|
@@ -18,7 +18,7 @@ class lt {
|
|
|
18
18
|
constructor(t) {
|
|
19
19
|
this.queryEndpoint = t.queryEndpoint, this.updateEndpoint = t.updateEndpoint, this.baseHeaders = Object.fromEntries(
|
|
20
20
|
Object.entries(t.originalHeaders || {}).filter(
|
|
21
|
-
([e]) =>
|
|
21
|
+
([e]) => ht.RELEVANT_HEADER_KEYS.includes(e)
|
|
22
22
|
)
|
|
23
23
|
), t.authHeader !== void 0 && (this.baseHeaders.Authorization = t.authHeader);
|
|
24
24
|
}
|
|
@@ -81,7 +81,7 @@ class lt {
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
class
|
|
84
|
+
class Y extends Error {
|
|
85
85
|
constructor(t) {
|
|
86
86
|
super(`QLever is locked (rebuild in progress): ${t}`), this.name = "QLeverLockedError";
|
|
87
87
|
}
|
|
@@ -119,7 +119,7 @@ class R {
|
|
|
119
119
|
try {
|
|
120
120
|
return await t();
|
|
121
121
|
} catch (a) {
|
|
122
|
-
if (r = a, a instanceof
|
|
122
|
+
if (r = a, a instanceof Y && s < e) {
|
|
123
123
|
const n = 0.5 + Math.random(), p = o * Math.pow(2, s) * n;
|
|
124
124
|
await new Promise((c) => setTimeout(c, p));
|
|
125
125
|
continue;
|
|
@@ -184,7 +184,7 @@ class R {
|
|
|
184
184
|
});
|
|
185
185
|
if (!e.ok) {
|
|
186
186
|
const o = await e.text();
|
|
187
|
-
throw e.status === 423 ? new
|
|
187
|
+
throw e.status === 423 ? new Y(o) : new Error(`SPARQL update failed (HTTP ${e.status}): ${o}`);
|
|
188
188
|
}
|
|
189
189
|
return await e.json();
|
|
190
190
|
});
|
|
@@ -204,7 +204,7 @@ class R {
|
|
|
204
204
|
await this._postToDataEndpoint(t, `${this.dataEndpoint}/delete`);
|
|
205
205
|
}
|
|
206
206
|
async _postToDataEndpoint(t, e) {
|
|
207
|
-
const o = await this._quadsToNQuads(t), r = await
|
|
207
|
+
const o = await this._quadsToNQuads(t), r = await Ze(Buffer.from(o, "utf-8"));
|
|
208
208
|
await R._retryOnLocked(async () => {
|
|
209
209
|
const s = await fetch(e, {
|
|
210
210
|
method: "POST",
|
|
@@ -217,18 +217,18 @@ class R {
|
|
|
217
217
|
});
|
|
218
218
|
if (!s.ok) {
|
|
219
219
|
const a = await s.text();
|
|
220
|
-
throw s.status === 423 ? new
|
|
220
|
+
throw s.status === 423 ? new Y(a) : new Error(`QLever data POST failed (HTTP ${s.status}): ${a}`);
|
|
221
221
|
}
|
|
222
222
|
});
|
|
223
223
|
}
|
|
224
224
|
_quadsToNQuads(t) {
|
|
225
225
|
return new Promise((e, o) => {
|
|
226
|
-
const r = new
|
|
226
|
+
const r = new xe({ format: "application/n-quads" });
|
|
227
227
|
r.addQuads(t), r.end((s, a) => s ? o(s) : e(a));
|
|
228
228
|
});
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
-
async function
|
|
231
|
+
async function Ze(i) {
|
|
232
232
|
const t = new CompressionStream("gzip"), e = t.writable.getWriter();
|
|
233
233
|
e.write(new Uint8Array(i)), e.close();
|
|
234
234
|
const o = [], r = t.readable.getReader();
|
|
@@ -243,14 +243,14 @@ async function Ye(i) {
|
|
|
243
243
|
a.set(p, n), n += p.byteLength;
|
|
244
244
|
return a.buffer;
|
|
245
245
|
}
|
|
246
|
-
class
|
|
246
|
+
class Je {
|
|
247
247
|
constructor(t) {
|
|
248
248
|
switch (this.options = t, this.options.graphType) {
|
|
249
249
|
case "qlever":
|
|
250
250
|
this._db = new R(this.options);
|
|
251
251
|
break;
|
|
252
252
|
case "fuseki":
|
|
253
|
-
this._db = new
|
|
253
|
+
this._db = new ht(this.options);
|
|
254
254
|
break;
|
|
255
255
|
default:
|
|
256
256
|
throw new Error(`Unsupported graph type: ${this.options.graphType}`);
|
|
@@ -298,7 +298,7 @@ class Ze {
|
|
|
298
298
|
return this.options.graphType === "qlever" ? this._db.deleteData(t) : Promise.reject(new Error("deleteData not supported for Fuseki — use update() with SPARQL DELETE DATA"));
|
|
299
299
|
}
|
|
300
300
|
}
|
|
301
|
-
class
|
|
301
|
+
class kt {
|
|
302
302
|
constructor(t) {
|
|
303
303
|
this.options = t;
|
|
304
304
|
}
|
|
@@ -327,7 +327,7 @@ class vt {
|
|
|
327
327
|
async getDownloadURL(t, e) {
|
|
328
328
|
const o = _(this._bucket(t), e);
|
|
329
329
|
try {
|
|
330
|
-
return await
|
|
330
|
+
return await K(o);
|
|
331
331
|
} catch (r) {
|
|
332
332
|
if (r?.code === "storage/object-not-found") return;
|
|
333
333
|
throw r;
|
|
@@ -343,7 +343,7 @@ class vt {
|
|
|
343
343
|
const r = _(this._bucket(t), e);
|
|
344
344
|
try {
|
|
345
345
|
const s = await M(r);
|
|
346
|
-
return `${await
|
|
346
|
+
return `${await K(r)}&t=${encodeURIComponent(s.updated)}`;
|
|
347
347
|
} catch (s) {
|
|
348
348
|
if (s?.code === "storage/object-not-found" || s?.status === 404) {
|
|
349
349
|
this._knownMissing.add(o), console.debug(`[CueBlobStorage] ${e} not found (404 OK — optional cache file)`);
|
|
@@ -356,7 +356,7 @@ class vt {
|
|
|
356
356
|
async getFile(t, e) {
|
|
357
357
|
const o = _(this._bucket(t), e);
|
|
358
358
|
try {
|
|
359
|
-
return await
|
|
359
|
+
return await re(o);
|
|
360
360
|
} catch (r) {
|
|
361
361
|
if (r?.code === "storage/object-not-found") return;
|
|
362
362
|
throw r;
|
|
@@ -382,7 +382,7 @@ class vt {
|
|
|
382
382
|
]);
|
|
383
383
|
try {
|
|
384
384
|
const [a, n] = await Promise.all([
|
|
385
|
-
s(
|
|
385
|
+
s(K(e)),
|
|
386
386
|
s(M(e))
|
|
387
387
|
]), p = `${a}&t=${encodeURIComponent(n.updated)}`, c = await fetch(p, { signal: o.signal });
|
|
388
388
|
if (!c.ok) throw new Error(`HTTP ${c.status}`);
|
|
@@ -414,7 +414,7 @@ class vt {
|
|
|
414
414
|
/** Update custom metadata on an existing file. */
|
|
415
415
|
async setMetadata(t, e, o) {
|
|
416
416
|
const r = _(this._bucket(t), e);
|
|
417
|
-
await
|
|
417
|
+
await _e(r, { customMetadata: o });
|
|
418
418
|
}
|
|
419
419
|
// ─── Uploads ──────────────────────────────────────────────────────────────
|
|
420
420
|
/**
|
|
@@ -423,7 +423,7 @@ class vt {
|
|
|
423
423
|
* upload progress needs to be surfaced in the UI.
|
|
424
424
|
*/
|
|
425
425
|
uploadResumable(t, e, o, r) {
|
|
426
|
-
const s = _(this._bucket(t), e), a =
|
|
426
|
+
const s = _(this._bucket(t), e), a = ft(s, o, r ? { customMetadata: r } : void 0);
|
|
427
427
|
return {
|
|
428
428
|
complete: () => new Promise((n, p) => a.then(() => n(), p)),
|
|
429
429
|
pause: () => a.pause(),
|
|
@@ -443,12 +443,12 @@ class vt {
|
|
|
443
443
|
*/
|
|
444
444
|
async uploadBytes(t, e, o, r) {
|
|
445
445
|
const s = _(this._bucket(t), e);
|
|
446
|
-
await
|
|
446
|
+
await st(s, o, r ? { customMetadata: r } : void 0);
|
|
447
447
|
}
|
|
448
448
|
/** Upload a string or base64-encoded value. */
|
|
449
|
-
async uploadString(t, e, o, r =
|
|
449
|
+
async uploadString(t, e, o, r = ke.RAW, s) {
|
|
450
450
|
const a = _(this._bucket(t), e);
|
|
451
|
-
await
|
|
451
|
+
await Ee(a, o, r, s ? { customMetadata: s } : void 0);
|
|
452
452
|
}
|
|
453
453
|
// ─── Listing ──────────────────────────────────────────────────────────────
|
|
454
454
|
/** List all item names directly under `prefix` in the given bucket. */
|
|
@@ -499,7 +499,7 @@ class vt {
|
|
|
499
499
|
d(new DOMException("Upload cancelled", "AbortError"));
|
|
500
500
|
return;
|
|
501
501
|
}
|
|
502
|
-
const g =
|
|
502
|
+
const g = ft(n, e, { customMetadata: o }), w = () => {
|
|
503
503
|
g.cancel(), d(new DOMException("Upload cancelled", "AbortError"));
|
|
504
504
|
};
|
|
505
505
|
s?.addEventListener("abort", w, { once: !0 }), g.on(
|
|
@@ -532,7 +532,7 @@ class vt {
|
|
|
532
532
|
*/
|
|
533
533
|
async uploadProcessed(t, e, o) {
|
|
534
534
|
const r = _(this.options.storageProcessed, t);
|
|
535
|
-
return await M(r).catch(() => null) ? !1 : (await
|
|
535
|
+
return await M(r).catch(() => null) ? !1 : (await st(r, e, { customMetadata: o }), !0);
|
|
536
536
|
}
|
|
537
537
|
/** List all blob names directly under `prefix` in the raw bucket. */
|
|
538
538
|
async listRaw(t) {
|
|
@@ -540,7 +540,7 @@ class vt {
|
|
|
540
540
|
return (await z(e)).items.map((r) => r.name);
|
|
541
541
|
}
|
|
542
542
|
}
|
|
543
|
-
const
|
|
543
|
+
const Et = {
|
|
544
544
|
ä: "ae",
|
|
545
545
|
ä: "ae",
|
|
546
546
|
Ä: "AE",
|
|
@@ -576,15 +576,15 @@ const _t = {
|
|
|
576
576
|
};
|
|
577
577
|
function D(i, t = !1) {
|
|
578
578
|
const e = "daca0510-72b5-48ba-9091-b918ca18136b";
|
|
579
|
-
return i =
|
|
579
|
+
return i = to(i, t), Ye(i, e);
|
|
580
580
|
}
|
|
581
|
-
function
|
|
581
|
+
function to(i, t = !1) {
|
|
582
582
|
let e = i;
|
|
583
|
-
for (const o in
|
|
584
|
-
e = e.replace(new RegExp(o, "g"),
|
|
583
|
+
for (const o in Et)
|
|
584
|
+
e = e.replace(new RegExp(o, "g"), Et[o]);
|
|
585
585
|
return t && e !== i && console.info(`${i} -> ${e}`), e;
|
|
586
586
|
}
|
|
587
|
-
function
|
|
587
|
+
function eo(i, t = "") {
|
|
588
588
|
return D(`${t}${i}`);
|
|
589
589
|
}
|
|
590
590
|
class k {
|
|
@@ -608,7 +608,7 @@ class k {
|
|
|
608
608
|
return this;
|
|
609
609
|
}
|
|
610
610
|
}
|
|
611
|
-
function
|
|
611
|
+
function dt(i, t) {
|
|
612
612
|
const e = /* @__PURE__ */ new Set();
|
|
613
613
|
let o = t(), r = !1;
|
|
614
614
|
const s = [], a = () => {
|
|
@@ -630,7 +630,7 @@ function ct(i, t) {
|
|
|
630
630
|
}
|
|
631
631
|
};
|
|
632
632
|
}
|
|
633
|
-
async function
|
|
633
|
+
async function gt(i, t, e, o) {
|
|
634
634
|
const r = D(i);
|
|
635
635
|
let s;
|
|
636
636
|
if (o) {
|
|
@@ -642,12 +642,12 @@ async function ht(i, t, e, o) {
|
|
|
642
642
|
(p) => console.error("[staleWhileRevalidate] Cache write failed:", p)
|
|
643
643
|
), a;
|
|
644
644
|
}
|
|
645
|
-
const
|
|
645
|
+
const Z = {
|
|
646
646
|
apiKey: "AIzaSyAiW42QBx9HS4Khu88pCW7MV66IhBAQul0",
|
|
647
647
|
appId: "1:151132927589:web:d2ffdb377dfadfd23ab88c",
|
|
648
648
|
measurementId: "G-YT4PK6HGZD"
|
|
649
|
-
},
|
|
650
|
-
class
|
|
649
|
+
}, xt = "qaecy-mvp-406413", oo = "734737865998", ie = "europe-west6", It = "projects", Ct = "spaces_chats_eu_west6", Tt = "spaces_raw_eu_west6", St = "spaces_processed_eu_west6", Rt = "spaces_logs_eu_west6", At = "cue_public_eu_west6", Pt = "db_persistence_eu_west6", ro = "/data-views/admin/consumption", so = "/data-views/admin/profile/organizations", Ot = "/data-views/admin/profile/api-keys", Dt = "/commands/admin/profile/api-keys", ao = "/commands/admin/profile/terms", io = (i) => `/data-views/admin/organizations/${i}/members`, no = "/commands/admin/project", po = (i) => `/commands/admin/project/${i}`, lo = "/assistant/search", ne = "/triplestore/query", co = "/triplestore/update", ho = "/triplestore/shacl", pe = "/qlever-server/qlever/query", go = "/qlever-server/qlever/update", uo = "/qlever-server/qlever/shacl", Lt = "/commands/file-system-structure/batch", qt = "microsoft.com", jt = "superadmin", ut = "https://cue.qaecy.com/r/";
|
|
650
|
+
class Ut {
|
|
651
651
|
_auth;
|
|
652
652
|
_endpoints;
|
|
653
653
|
_userSignal = new k(null);
|
|
@@ -664,19 +664,19 @@ class qt {
|
|
|
664
664
|
/** All unique UIDs for the current user (Firebase UID + linked provider UIDs). */
|
|
665
665
|
userIds;
|
|
666
666
|
constructor(t, e = !1, o) {
|
|
667
|
-
this._auth =
|
|
667
|
+
this._auth = qe(t), this._endpoints = o, e && je(this._auth, o.authEmulatorUrl, {
|
|
668
668
|
disableWarnings: !0
|
|
669
|
-
}), this.user = this._userSignal.asReadonly(), this.token = this._tokenSignal.asReadonly(), this.isSuperAdmin = this._isSuperAdminSignal.asReadonly(), this._userIdsSignal =
|
|
669
|
+
}), this.user = this._userSignal.asReadonly(), this.token = this._tokenSignal.asReadonly(), this.isSuperAdmin = this._isSuperAdminSignal.asReadonly(), this._userIdsSignal = dt([this._userSignal], () => {
|
|
670
670
|
const r = this._userSignal.get();
|
|
671
671
|
if (!r) return [];
|
|
672
672
|
const s = /* @__PURE__ */ new Set([r.uid]);
|
|
673
673
|
return r.providerData.forEach((a) => s.add(a.uid)), Array.from(s);
|
|
674
|
-
}), this.userIds = this._userIdsSignal, this._stopTokenListener =
|
|
674
|
+
}), this.userIds = this._userIdsSignal, this._stopTokenListener = Ue(this._auth, async (r) => {
|
|
675
675
|
if (this._userSignal.set(r), r) {
|
|
676
676
|
const s = await r.getIdToken();
|
|
677
677
|
this._tokenSignal.set(s);
|
|
678
|
-
const a = await
|
|
679
|
-
this._isSuperAdminSignal.set(a.claims.role ===
|
|
678
|
+
const a = await at(r);
|
|
679
|
+
this._isSuperAdminSignal.set(a.claims.role === jt);
|
|
680
680
|
} else
|
|
681
681
|
this._tokenSignal.set(null), this._isSuperAdminSignal.set(!1);
|
|
682
682
|
});
|
|
@@ -689,14 +689,14 @@ class qt {
|
|
|
689
689
|
if (t === "password") {
|
|
690
690
|
if (!e)
|
|
691
691
|
throw new Error("credentials are required for password sign-in");
|
|
692
|
-
return (await
|
|
692
|
+
return (await Me(
|
|
693
693
|
this._auth,
|
|
694
694
|
e.email,
|
|
695
695
|
e.password
|
|
696
696
|
)).user;
|
|
697
697
|
}
|
|
698
|
-
const o = t === "google" ? new
|
|
699
|
-
return (await
|
|
698
|
+
const o = t === "google" ? new it() : new nt(qt);
|
|
699
|
+
return (await ze(this._auth, o)).user;
|
|
700
700
|
}
|
|
701
701
|
/**
|
|
702
702
|
* Initiate a redirect-based sign-in (mobile / iframe contexts where popups
|
|
@@ -704,8 +704,8 @@ class qt {
|
|
|
704
704
|
* retrieve the result.
|
|
705
705
|
*/
|
|
706
706
|
async signInWithRedirect(t) {
|
|
707
|
-
const e = t === "google" ? new
|
|
708
|
-
await
|
|
707
|
+
const e = t === "google" ? new it() : new nt(qt);
|
|
708
|
+
await Ne(this._auth, e);
|
|
709
709
|
}
|
|
710
710
|
/**
|
|
711
711
|
* Retrieve the result of a redirect sign-in. Returns the signed-in `User`
|
|
@@ -713,7 +713,7 @@ class qt {
|
|
|
713
713
|
* Call this once on app startup before showing a sign-in UI.
|
|
714
714
|
*/
|
|
715
715
|
async checkRedirectResult() {
|
|
716
|
-
return (await
|
|
716
|
+
return (await $e(this._auth))?.user ?? null;
|
|
717
717
|
}
|
|
718
718
|
/**
|
|
719
719
|
* One-shot async check — returns `true` if the current user has the
|
|
@@ -722,7 +722,7 @@ class qt {
|
|
|
722
722
|
*/
|
|
723
723
|
async checkSuperAdmin() {
|
|
724
724
|
const t = this._auth.currentUser;
|
|
725
|
-
return t ? (await
|
|
725
|
+
return t ? (await at(t)).claims.role === jt : !1;
|
|
726
726
|
}
|
|
727
727
|
/** Sign in with a Cue API key. `projectId` is optional — omit it when no project context is available (e.g. admin flows). */
|
|
728
728
|
async signInWithApiKey(t, e) {
|
|
@@ -735,11 +735,15 @@ class qt {
|
|
|
735
735
|
if (!r.ok)
|
|
736
736
|
throw new Error(`Failed to fetch custom token: ${r.statusText}`);
|
|
737
737
|
const { token: s } = await r.json();
|
|
738
|
-
return (await
|
|
738
|
+
return (await vt(this._auth, s)).user;
|
|
739
|
+
}
|
|
740
|
+
/** Sign in with a Firebase custom token (e.g. minted server-side for MCP/OAuth flows). */
|
|
741
|
+
async signInWithCustomToken(t) {
|
|
742
|
+
return (await vt(this._auth, t)).user;
|
|
739
743
|
}
|
|
740
744
|
/** Sign out the current user */
|
|
741
745
|
async signOut() {
|
|
742
|
-
await
|
|
746
|
+
await Fe(this._auth);
|
|
743
747
|
}
|
|
744
748
|
/**
|
|
745
749
|
* Register a new user by name and email.
|
|
@@ -769,7 +773,7 @@ class qt {
|
|
|
769
773
|
}
|
|
770
774
|
/** Subscribe to authentication state changes. Returns an unsubscribe function. */
|
|
771
775
|
onAuthStateChanged(t) {
|
|
772
|
-
return
|
|
776
|
+
return Be(this._auth, t);
|
|
773
777
|
}
|
|
774
778
|
/** Get the Firebase ID token for the current user, or null if not authenticated */
|
|
775
779
|
async getToken(t = !1) {
|
|
@@ -801,7 +805,7 @@ class qt {
|
|
|
801
805
|
return this._auth;
|
|
802
806
|
}
|
|
803
807
|
}
|
|
804
|
-
class
|
|
808
|
+
class Mt {
|
|
805
809
|
constructor(t) {
|
|
806
810
|
this._blob = t;
|
|
807
811
|
}
|
|
@@ -837,8 +841,8 @@ class jt {
|
|
|
837
841
|
return e;
|
|
838
842
|
}
|
|
839
843
|
}
|
|
840
|
-
const
|
|
841
|
-
class
|
|
844
|
+
const mo = "/data-views/tables", wo = "/commands/tables";
|
|
845
|
+
class fo {
|
|
842
846
|
constructor(t, e) {
|
|
843
847
|
this._auth = t, this._gatewayUrl = e;
|
|
844
848
|
}
|
|
@@ -846,7 +850,7 @@ class wo {
|
|
|
846
850
|
_gatewayUrl;
|
|
847
851
|
async listTables(t) {
|
|
848
852
|
const e = await this._auth.authenticatedFetch(
|
|
849
|
-
`${this._gatewayUrl}${
|
|
853
|
+
`${this._gatewayUrl}${mo}`,
|
|
850
854
|
{
|
|
851
855
|
headers: {
|
|
852
856
|
"Content-Type": "application/json",
|
|
@@ -861,7 +865,7 @@ class wo {
|
|
|
861
865
|
}
|
|
862
866
|
async saveTables(t, e) {
|
|
863
867
|
const o = await this._auth.authenticatedFetch(
|
|
864
|
-
`${this._gatewayUrl}${
|
|
868
|
+
`${this._gatewayUrl}${wo}`,
|
|
865
869
|
{
|
|
866
870
|
method: "PUT",
|
|
867
871
|
headers: {
|
|
@@ -876,15 +880,56 @@ class wo {
|
|
|
876
880
|
throw new Error(`Failed to save tables: ${o.status} ${o.statusText}`);
|
|
877
881
|
}
|
|
878
882
|
}
|
|
879
|
-
|
|
883
|
+
const yo = "/semantic-extraction/extract";
|
|
884
|
+
class bo {
|
|
885
|
+
constructor(t, e) {
|
|
886
|
+
this._auth = t, this._gatewayUrl = e;
|
|
887
|
+
}
|
|
888
|
+
_auth;
|
|
889
|
+
_gatewayUrl;
|
|
890
|
+
/**
|
|
891
|
+
* Run semantic extraction on a document page image.
|
|
892
|
+
*
|
|
893
|
+
* Sends a multipart/form-data POST to `/semantic-extraction/extract`.
|
|
894
|
+
* Always requests JSON-LD so the result can be displayed directly in
|
|
895
|
+
* `cue-rdf-graph` without any further parsing.
|
|
896
|
+
*/
|
|
897
|
+
async extract(t) {
|
|
898
|
+
const e = t.rdfFormat ?? "json-ld", o = new FormData();
|
|
899
|
+
o.append("file", t.image, "page.png"), o.append("template", JSON.stringify(t.template)), o.append("space_id", t.projectId), o.append("rdf_format", e), t.category && o.append("category", t.category), t.text && o.append("text", t.text);
|
|
900
|
+
const r = await this._auth.authenticatedFetch(
|
|
901
|
+
`${this._gatewayUrl}${yo}`,
|
|
902
|
+
{
|
|
903
|
+
method: "POST",
|
|
904
|
+
// Do NOT set Content-Type; browser sets it with the correct boundary.
|
|
905
|
+
headers: {
|
|
906
|
+
Accept: "application/ld+json",
|
|
907
|
+
"x-project-id": t.projectId,
|
|
908
|
+
"cue-project-id": t.projectId
|
|
909
|
+
},
|
|
910
|
+
body: o
|
|
911
|
+
}
|
|
912
|
+
);
|
|
913
|
+
if (!r.ok) {
|
|
914
|
+
const a = await r.text().catch(() => "");
|
|
915
|
+
throw new Error(
|
|
916
|
+
`Extraction failed: ${r.status} ${r.statusText}${a ? " — " + a.slice(0, 300) : ""}`
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
return { jsonld: await r.json() };
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
class zt {
|
|
880
923
|
constructor(t, e, o, r) {
|
|
881
|
-
this._auth = t, this._gatewayUrl = e, this.projects = o, this.sync = r, this.tables = new
|
|
924
|
+
this._auth = t, this._gatewayUrl = e, this.projects = o, this.sync = r, this.tables = new fo(t, e), this.extraction = new bo(t, e);
|
|
882
925
|
}
|
|
883
926
|
_auth;
|
|
884
927
|
_gatewayUrl;
|
|
885
928
|
projects;
|
|
886
929
|
sync;
|
|
887
930
|
tables;
|
|
931
|
+
/** Semantic extraction client — call document pages against a SemanticTemplate. */
|
|
932
|
+
extraction;
|
|
888
933
|
/** Active language used for language-sensitive SPARQL queries across all project classes. */
|
|
889
934
|
language = "en";
|
|
890
935
|
/** Updates the active language. All project classes (`CueProjectSchema`, `CueProjectDocuments`, `CueProjectEntities`) read this at query time. */
|
|
@@ -910,7 +955,7 @@ class Ut {
|
|
|
910
955
|
*/
|
|
911
956
|
async search(t) {
|
|
912
957
|
const e = await this._auth.authenticatedFetch(
|
|
913
|
-
`${this._gatewayUrl}${
|
|
958
|
+
`${this._gatewayUrl}${lo}`,
|
|
914
959
|
{
|
|
915
960
|
method: "POST",
|
|
916
961
|
headers: { "Content-Type": "application/json", "cue-project-id": t.projectId },
|
|
@@ -933,7 +978,7 @@ class Ut {
|
|
|
933
978
|
*/
|
|
934
979
|
async sparql(t, e, o) {
|
|
935
980
|
o || (o = (await this.projects.getProject(e))?.projectSettings?.graph?.type ?? "qlever");
|
|
936
|
-
const r = o === "fuseki" ?
|
|
981
|
+
const r = o === "fuseki" ? ne : pe;
|
|
937
982
|
console.log(`Executing SPARQL query against ${r} for project ${e} with graph type ${o}`);
|
|
938
983
|
const s = new URLSearchParams();
|
|
939
984
|
s.append("query", t);
|
|
@@ -970,7 +1015,7 @@ class Ut {
|
|
|
970
1015
|
const r = o?.format ?? "json-ld", s = r === "turtle" ? "text/turtle" : "application/ld+json";
|
|
971
1016
|
if (o?.graphType === "fuseki") {
|
|
972
1017
|
const c = await this._auth.authenticatedFetch(
|
|
973
|
-
`${this._gatewayUrl}${
|
|
1018
|
+
`${this._gatewayUrl}${ho}`,
|
|
974
1019
|
{
|
|
975
1020
|
method: "POST",
|
|
976
1021
|
headers: {
|
|
@@ -988,7 +1033,7 @@ class Ut {
|
|
|
988
1033
|
}
|
|
989
1034
|
return r === "turtle" ? c.text() : c.json();
|
|
990
1035
|
}
|
|
991
|
-
const a = `${this._gatewayUrl}${
|
|
1036
|
+
const a = `${this._gatewayUrl}${uo}${o?.verbose ? "?verbose=true" : ""}`, n = new URLSearchParams({ shape: t }), p = await this._auth.authenticatedFetch(a, {
|
|
992
1037
|
method: "POST",
|
|
993
1038
|
headers: {
|
|
994
1039
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -1006,7 +1051,7 @@ class Ut {
|
|
|
1006
1051
|
}
|
|
1007
1052
|
async getConsumption(t) {
|
|
1008
1053
|
const e = await this._auth.authenticatedFetch(
|
|
1009
|
-
`${this._gatewayUrl}${
|
|
1054
|
+
`${this._gatewayUrl}${ro}`,
|
|
1010
1055
|
{
|
|
1011
1056
|
headers: {
|
|
1012
1057
|
"Content-Type": "application/json",
|
|
@@ -1022,7 +1067,7 @@ class Ut {
|
|
|
1022
1067
|
return e.json();
|
|
1023
1068
|
}
|
|
1024
1069
|
}
|
|
1025
|
-
const
|
|
1070
|
+
const pt = [
|
|
1026
1071
|
"building",
|
|
1027
1072
|
"cadastre",
|
|
1028
1073
|
"zone",
|
|
@@ -1033,13 +1078,13 @@ const nt = [
|
|
|
1033
1078
|
"railway",
|
|
1034
1079
|
"natural",
|
|
1035
1080
|
"manmade"
|
|
1036
|
-
],
|
|
1081
|
+
], le = [
|
|
1037
1082
|
"address",
|
|
1038
1083
|
"poi",
|
|
1039
1084
|
"railway",
|
|
1040
1085
|
"natural",
|
|
1041
1086
|
"manmade"
|
|
1042
|
-
],
|
|
1087
|
+
], vo = {
|
|
1043
1088
|
address: {
|
|
1044
1089
|
category: "address",
|
|
1045
1090
|
label: "Address",
|
|
@@ -1102,9 +1147,9 @@ const nt = [
|
|
|
1102
1147
|
}
|
|
1103
1148
|
};
|
|
1104
1149
|
function S(i) {
|
|
1105
|
-
return
|
|
1150
|
+
return vo[i];
|
|
1106
1151
|
}
|
|
1107
|
-
const
|
|
1152
|
+
const _o = {
|
|
1108
1153
|
"land-use-plan": "#f59e0b",
|
|
1109
1154
|
// amber – primary zoning
|
|
1110
1155
|
"local-plan": "#ec4899",
|
|
@@ -1135,7 +1180,7 @@ const yo = {
|
|
|
1135
1180
|
function N(i, t) {
|
|
1136
1181
|
return i[0] < t[2] && i[2] > t[0] && i[1] < t[3] && i[3] > t[1];
|
|
1137
1182
|
}
|
|
1138
|
-
const
|
|
1183
|
+
const ko = "https://nominatim.openstreetmap.org", Eo = "cue-gis/0.0.1", xo = {
|
|
1139
1184
|
address: "street",
|
|
1140
1185
|
poi: "shop",
|
|
1141
1186
|
railway: "station",
|
|
@@ -1150,7 +1195,7 @@ const bo = "https://nominatim.openstreetmap.org", vo = "cue-gis/0.0.1", _o = {
|
|
|
1150
1195
|
function B(i) {
|
|
1151
1196
|
return `${L}:${i}`;
|
|
1152
1197
|
}
|
|
1153
|
-
function
|
|
1198
|
+
function Io(i) {
|
|
1154
1199
|
const t = S(i);
|
|
1155
1200
|
return {
|
|
1156
1201
|
id: B(i),
|
|
@@ -1165,17 +1210,17 @@ function ko(i) {
|
|
|
1165
1210
|
descriptionKey: `gis.layer.${L}.${i}.description`
|
|
1166
1211
|
};
|
|
1167
1212
|
}
|
|
1168
|
-
class
|
|
1213
|
+
class Co {
|
|
1169
1214
|
baseUrl;
|
|
1170
1215
|
userAgent;
|
|
1171
1216
|
email;
|
|
1172
1217
|
limit;
|
|
1173
1218
|
constructor(t = {}) {
|
|
1174
|
-
this.baseUrl = t.baseUrl ??
|
|
1219
|
+
this.baseUrl = t.baseUrl ?? ko, this.userAgent = t.userAgent ?? Eo, this.email = t.email, this.limit = Math.min(t.limit ?? 40, 40);
|
|
1175
1220
|
}
|
|
1176
1221
|
async listFeatureCategoryDescriptors(t) {
|
|
1177
1222
|
return (await Promise.allSettled(
|
|
1178
|
-
|
|
1223
|
+
le.map(async (o) => {
|
|
1179
1224
|
const r = await this.search(t, o);
|
|
1180
1225
|
return { category: o, hasResults: r.length > 0 };
|
|
1181
1226
|
})
|
|
@@ -1184,10 +1229,10 @@ class Eo {
|
|
|
1184
1229
|
).map((o) => S(o.value.category));
|
|
1185
1230
|
}
|
|
1186
1231
|
async listAvailableLayers(t) {
|
|
1187
|
-
return (await this.listFeatureCategoryDescriptors(t)).map((o) =>
|
|
1232
|
+
return (await this.listFeatureCategoryDescriptors(t)).map((o) => Io(o.category));
|
|
1188
1233
|
}
|
|
1189
1234
|
async getFeaturesForLayer(t, e) {
|
|
1190
|
-
const o =
|
|
1235
|
+
const o = pt.find((r) => B(r) === e);
|
|
1191
1236
|
return o ? this.search(t, o) : [];
|
|
1192
1237
|
}
|
|
1193
1238
|
async listFeatureCategories(t) {
|
|
@@ -1201,7 +1246,7 @@ class Eo {
|
|
|
1201
1246
|
* so bounded viewbox searches return meaningful results.
|
|
1202
1247
|
*/
|
|
1203
1248
|
async search(t, e) {
|
|
1204
|
-
const [o, r, s, a] = t, n = e ?
|
|
1249
|
+
const [o, r, s, a] = t, n = e ? xo[e] : "place", p = new URLSearchParams({
|
|
1205
1250
|
q: n,
|
|
1206
1251
|
format: "jsonv2",
|
|
1207
1252
|
viewbox: `${o},${a},${s},${r}`,
|
|
@@ -1244,7 +1289,7 @@ class Eo {
|
|
|
1244
1289
|
};
|
|
1245
1290
|
}
|
|
1246
1291
|
}
|
|
1247
|
-
const
|
|
1292
|
+
const Nt = {
|
|
1248
1293
|
// 100s – Residential
|
|
1249
1294
|
110: "residential",
|
|
1250
1295
|
120: "residential",
|
|
@@ -1323,7 +1368,7 @@ const Mt = {
|
|
|
1323
1368
|
960: "agricultural",
|
|
1324
1369
|
970: "agricultural",
|
|
1325
1370
|
990: "other"
|
|
1326
|
-
},
|
|
1371
|
+
}, $t = {
|
|
1327
1372
|
1010: "residential",
|
|
1328
1373
|
1020: "mixed",
|
|
1329
1374
|
1030: "residential",
|
|
@@ -1353,7 +1398,7 @@ const Mt = {
|
|
|
1353
1398
|
1281: "infrastructure",
|
|
1354
1399
|
1282: "infrastructure",
|
|
1355
1400
|
9999: "other"
|
|
1356
|
-
},
|
|
1401
|
+
}, To = {
|
|
1357
1402
|
// Residential
|
|
1358
1403
|
1110: "residential",
|
|
1359
1404
|
// Einfamilienhaus
|
|
@@ -1415,7 +1460,7 @@ const Mt = {
|
|
|
1415
1460
|
// Empfangsgebäude Bahn/Bus
|
|
1416
1461
|
1282: "infrastructure"
|
|
1417
1462
|
// Parkhaus, Garage
|
|
1418
|
-
},
|
|
1463
|
+
}, So = [
|
|
1419
1464
|
// "Gebäude" is the Swiss AV BoFlaeche land-cover label for a building footprint.
|
|
1420
1465
|
// It does not encode the actual use type, so map it to 'other' as a safe fallback.
|
|
1421
1466
|
[/^geb[äa]ude$/i, "other"],
|
|
@@ -1429,22 +1474,22 @@ const Mt = {
|
|
|
1429
1474
|
[/gemischt|mixed|blandet/i, "mixed"]
|
|
1430
1475
|
];
|
|
1431
1476
|
function O(i) {
|
|
1432
|
-
for (const [t, e] of
|
|
1477
|
+
for (const [t, e] of So)
|
|
1433
1478
|
if (t.test(i)) return e;
|
|
1434
1479
|
}
|
|
1435
|
-
function
|
|
1480
|
+
function Ro(i, t) {
|
|
1436
1481
|
if (i == null) return;
|
|
1437
1482
|
const e = String(i).trim();
|
|
1438
|
-
return t === "swiss-gwr" ?
|
|
1483
|
+
return t === "swiss-gwr" ? To[e] ?? O(e) : t === "danish-matrikel" ? Nt[e] ?? O(e) : t === "zurich-wfs" || t === "swiss-av-wfs" ? $t[e] ?? O(e) : $t[e] ?? Nt[e] ?? O(e);
|
|
1439
1484
|
}
|
|
1440
|
-
function
|
|
1485
|
+
function Ao(i, t) {
|
|
1441
1486
|
if (i != null)
|
|
1442
1487
|
return O(String(i).trim());
|
|
1443
1488
|
}
|
|
1444
|
-
function
|
|
1489
|
+
function ce(i) {
|
|
1445
1490
|
return i.trim().toLowerCase().replace(/[\s_\-]/g, "");
|
|
1446
1491
|
}
|
|
1447
|
-
const
|
|
1492
|
+
const Po = {
|
|
1448
1493
|
// Swiss ÖREB rechtsstatus
|
|
1449
1494
|
inkraft: "in-force",
|
|
1450
1495
|
laufendeanderung: "amendment-pending",
|
|
@@ -1463,11 +1508,11 @@ const So = {
|
|
|
1463
1508
|
forslag: "proposed",
|
|
1464
1509
|
aflyst: "repealed"
|
|
1465
1510
|
};
|
|
1466
|
-
function
|
|
1511
|
+
function he(i) {
|
|
1467
1512
|
if (i)
|
|
1468
|
-
return
|
|
1513
|
+
return Po[ce(i)];
|
|
1469
1514
|
}
|
|
1470
|
-
const
|
|
1515
|
+
const Ft = {
|
|
1471
1516
|
// Swiss Nutzungsplanung (typ_gde_bezeichnung and common variants)
|
|
1472
1517
|
grundnutzungszonenplan: "land-use-plan",
|
|
1473
1518
|
nutzungszonenplan: "land-use-plan",
|
|
@@ -1521,7 +1566,7 @@ const Nt = {
|
|
|
1521
1566
|
// Danish plandata.dk
|
|
1522
1567
|
lokalplan: "local-plan",
|
|
1523
1568
|
kommuneplanramme: "municipal-plan-framework"
|
|
1524
|
-
},
|
|
1569
|
+
}, Oo = [
|
|
1525
1570
|
[/quartiererhalt/i, "neighbourhood-conservation-plan"],
|
|
1526
1571
|
[/lärmempfindlich|laermempfindlich/i, "noise-sensitivity-plan"],
|
|
1527
1572
|
[/gewässerschutz|grundwasserschutz/i, "water-protection-plan"],
|
|
@@ -1561,24 +1606,24 @@ const Nt = {
|
|
|
1561
1606
|
// Catch-all: any remaining Xzone / Xareal designation from the Grundnutzungszonenplan
|
|
1562
1607
|
[/zone$|areal$/i, "land-use-plan"]
|
|
1563
1608
|
];
|
|
1564
|
-
function
|
|
1609
|
+
function de(i) {
|
|
1565
1610
|
if (!i) return;
|
|
1566
|
-
const t =
|
|
1567
|
-
if (t in
|
|
1568
|
-
for (const [e, o] of
|
|
1611
|
+
const t = ce(i);
|
|
1612
|
+
if (t in Ft) return Ft[t];
|
|
1613
|
+
for (const [e, o] of Oo)
|
|
1569
1614
|
if (e.test(i)) return o;
|
|
1570
1615
|
console.warn(
|
|
1571
1616
|
`[cue-gis] Unknown zone plan type — add "${i}" to classifyZonePlanType: no ZonePlanType mapping found.`
|
|
1572
1617
|
);
|
|
1573
1618
|
}
|
|
1574
|
-
const
|
|
1575
|
-
function
|
|
1619
|
+
const Do = "https://maps.zh.ch/wfs/OGDZHWFS", Lo = "zurich-wfs", qo = [8.35, 47.15, 8.95, 47.7], jo = [5.9, 45.7, 10.55, 47.85];
|
|
1620
|
+
function J(i) {
|
|
1576
1621
|
return typeof i == "string" ? i : i.typeName;
|
|
1577
1622
|
}
|
|
1578
|
-
function
|
|
1623
|
+
function tt(i) {
|
|
1579
1624
|
return typeof i == "string" ? void 0 : i.cqlFilter;
|
|
1580
1625
|
}
|
|
1581
|
-
function
|
|
1626
|
+
function Uo(i) {
|
|
1582
1627
|
if (!i) return [0, 0];
|
|
1583
1628
|
const t = i.coordinates;
|
|
1584
1629
|
switch (i.type) {
|
|
@@ -1596,20 +1641,20 @@ function Lo(i) {
|
|
|
1596
1641
|
return [0, 0];
|
|
1597
1642
|
}
|
|
1598
1643
|
}
|
|
1599
|
-
function
|
|
1644
|
+
function Mo(i, t) {
|
|
1600
1645
|
if (!i) return t;
|
|
1601
1646
|
for (const e of ["plannavn", "bezeichnung", "name", "strassenname", "objektname", "title", "label"])
|
|
1602
1647
|
if (typeof i[e] == "string" && i[e]) return i[e];
|
|
1603
1648
|
return t;
|
|
1604
1649
|
}
|
|
1605
|
-
function
|
|
1650
|
+
function zo(i, t, e) {
|
|
1606
1651
|
return e ? `${i}:${t}[${e}]` : `${i}:${t}`;
|
|
1607
1652
|
}
|
|
1608
|
-
const
|
|
1609
|
-
function
|
|
1610
|
-
const r = e.replace(/^ms:/, ""), s = S(t), a =
|
|
1653
|
+
const No = /* @__PURE__ */ new Set(["building", "cadastre", "greenspace", "paved", "zone"]);
|
|
1654
|
+
function et(i, t, e, o) {
|
|
1655
|
+
const r = e.replace(/^ms:/, ""), s = S(t), a = No.has(t) ? "priority" : "raw";
|
|
1611
1656
|
return {
|
|
1612
|
-
id:
|
|
1657
|
+
id: zo(i, e, o),
|
|
1613
1658
|
sourceId: i,
|
|
1614
1659
|
sourceLayerId: e,
|
|
1615
1660
|
category: t,
|
|
@@ -1621,32 +1666,32 @@ function tt(i, t, e, o) {
|
|
|
1621
1666
|
descriptionKey: `gis.layer.${i}.${r}.description`
|
|
1622
1667
|
};
|
|
1623
1668
|
}
|
|
1624
|
-
function
|
|
1669
|
+
function $o(i, t) {
|
|
1625
1670
|
if (!i) return { featureType: "building" };
|
|
1626
1671
|
const e = i.grundflaeche ?? i.gbf ?? i.gebaeudegrundrissflaeche ?? i.flaeche ?? void 0, o = i.vollgeschosse ?? i.geschossanzahl ?? i.anzahl_geschosse ?? void 0, r = i.gebaeudefunktion ?? i.gfkode ?? i.art ?? i.objektart ?? void 0, s = i.baujahr ?? i.bauperiode ?? void 0, a = String(i.egid ?? i.gwr_egid ?? i.egris_egid ?? "").trim() || void 0;
|
|
1627
1672
|
return {
|
|
1628
1673
|
featureType: "building",
|
|
1629
1674
|
areaM2: typeof e == "number" ? e : void 0,
|
|
1630
1675
|
buildingUse: r ? String(r) : void 0,
|
|
1631
|
-
buildingUseGeneric:
|
|
1676
|
+
buildingUseGeneric: Ro(r, t),
|
|
1632
1677
|
floors: typeof o == "number" ? o : void 0,
|
|
1633
1678
|
yearBuilt: typeof s == "number" ? s : void 0,
|
|
1634
1679
|
registryId: a
|
|
1635
1680
|
};
|
|
1636
1681
|
}
|
|
1637
|
-
function
|
|
1682
|
+
function Fo(i, t) {
|
|
1638
1683
|
if (!i) return { featureType: "plot" };
|
|
1639
1684
|
const e = i.egris_egrid ?? i.egrid ?? void 0, o = i.nummer ?? void 0, r = i.nbident ?? void 0, s = o && r ? `${o}, ${r}` : o ?? void 0, a = i.flaechenmass ?? i.flaeche ?? void 0, n = i.art ?? i.nutzungsart ?? void 0;
|
|
1640
1685
|
return {
|
|
1641
1686
|
featureType: "plot",
|
|
1642
1687
|
areaM2: typeof a == "number" ? a : void 0,
|
|
1643
1688
|
plotUse: n ? String(n) : void 0,
|
|
1644
|
-
plotUseGeneric:
|
|
1689
|
+
plotUseGeneric: Ao(n),
|
|
1645
1690
|
plotId: s,
|
|
1646
1691
|
registryId: e
|
|
1647
1692
|
};
|
|
1648
1693
|
}
|
|
1649
|
-
function
|
|
1694
|
+
function Bo(i) {
|
|
1650
1695
|
if (!i) return { featureType: "greenspace" };
|
|
1651
1696
|
const t = i.flaeche ?? void 0, e = i.art ?? void 0;
|
|
1652
1697
|
return {
|
|
@@ -1655,7 +1700,7 @@ function No(i) {
|
|
|
1655
1700
|
surfaceType: e ? String(e) : void 0
|
|
1656
1701
|
};
|
|
1657
1702
|
}
|
|
1658
|
-
function
|
|
1703
|
+
function Go(i) {
|
|
1659
1704
|
if (!i) return { featureType: "paved" };
|
|
1660
1705
|
const t = i.flaeche ?? void 0, e = i.art ?? void 0;
|
|
1661
1706
|
return {
|
|
@@ -1664,9 +1709,9 @@ function $o(i) {
|
|
|
1664
1709
|
surfaceType: e ? String(e) : void 0
|
|
1665
1710
|
};
|
|
1666
1711
|
}
|
|
1667
|
-
function
|
|
1712
|
+
function Ho(i) {
|
|
1668
1713
|
if (!i) return { featureType: "zone" };
|
|
1669
|
-
const t = i.plannavn ?? i.bezeichnung ?? i.typ_bezeichnung ?? i.art ?? void 0, e = i.planid ?? i.plannummer ?? void 0, o = i.artcode ?? i.typ_code ?? i.abkuerzung ?? e ?? void 0, r = i.rechtsstatus ?? i.status ?? void 0, s =
|
|
1714
|
+
const t = i.plannavn ?? i.bezeichnung ?? i.typ_bezeichnung ?? i.art ?? void 0, e = i.planid ?? i.plannummer ?? void 0, o = i.artcode ?? i.typ_code ?? i.abkuerzung ?? e ?? void 0, r = i.rechtsstatus ?? i.status ?? void 0, s = he(r), a = i.typ_gde_bezeichnung ?? void 0, n = de(a), p = i.dagsordenpunkt_url ?? i.dokument_url ?? i.link ?? void 0, c = i.auflagedatum ?? void 0, h = i.festsetzungsdatum ?? void 0, d = i.genehmigungsdatum ?? void 0, g = i.inkraftsetzungsdatum ?? void 0, w = i.flaeche ?? i.flaeche_m2 ?? void 0;
|
|
1670
1715
|
return {
|
|
1671
1716
|
featureType: "zone",
|
|
1672
1717
|
zoneType: t ? String(t) : void 0,
|
|
@@ -1682,7 +1727,7 @@ function Fo(i) {
|
|
|
1682
1727
|
areaM2: typeof w == "number" ? w : void 0
|
|
1683
1728
|
};
|
|
1684
1729
|
}
|
|
1685
|
-
function
|
|
1730
|
+
function Wo(i) {
|
|
1686
1731
|
const t = i.match(/^(\w+)\s*=\s*'([^']+)'$/);
|
|
1687
1732
|
if (t) {
|
|
1688
1733
|
const [, o, r] = t;
|
|
@@ -1697,13 +1742,13 @@ function Bo(i) {
|
|
|
1697
1742
|
}
|
|
1698
1743
|
return () => !0;
|
|
1699
1744
|
}
|
|
1700
|
-
class
|
|
1745
|
+
class ot {
|
|
1701
1746
|
categoryMap;
|
|
1702
1747
|
baseUrl;
|
|
1703
1748
|
sourceId;
|
|
1704
1749
|
outputFormat;
|
|
1705
1750
|
constructor(t) {
|
|
1706
|
-
this.categoryMap = t.categoryMap, this.baseUrl = t.baseUrl ??
|
|
1751
|
+
this.categoryMap = t.categoryMap, this.baseUrl = t.baseUrl ?? Do, this.sourceId = t.sourceId ?? Lo, this.outputFormat = t.outputFormat ?? "application/json; subtype=geojson";
|
|
1707
1752
|
}
|
|
1708
1753
|
async listFeatureCategoryDescriptors(t) {
|
|
1709
1754
|
const e = await this.listAvailableLayers(t);
|
|
@@ -1714,20 +1759,20 @@ class et {
|
|
|
1714
1759
|
return (await Promise.allSettled(
|
|
1715
1760
|
e.flatMap(
|
|
1716
1761
|
([r, s]) => s.map(async (a) => {
|
|
1717
|
-
const n =
|
|
1762
|
+
const n = J(a), p = tt(a), c = await this._fetchFeatures(t, n, 1, p);
|
|
1718
1763
|
return { category: r, typeName: n, cqlFilter: p, hasResults: c.features.length > 0 };
|
|
1719
1764
|
})
|
|
1720
1765
|
)
|
|
1721
1766
|
)).filter(
|
|
1722
1767
|
(r) => r.status === "fulfilled" && r.value.hasResults
|
|
1723
|
-
).map((r) =>
|
|
1768
|
+
).map((r) => et(this.sourceId, r.value.category, r.value.typeName, r.value.cqlFilter));
|
|
1724
1769
|
}
|
|
1725
1770
|
async getFeaturesForLayer(t, e) {
|
|
1726
1771
|
const o = this._findLayerById(e);
|
|
1727
1772
|
return o ? this._fetchAndConvert(t, o.descriptor, o.cqlFilter) : [];
|
|
1728
1773
|
}
|
|
1729
1774
|
async _fetchAndConvert(t, e, o) {
|
|
1730
|
-
const r = await this._fetchFeatures(t, e.sourceLayerId, void 0, o), s = o ?
|
|
1775
|
+
const r = await this._fetchFeatures(t, e.sourceLayerId, void 0, o), s = o ? Wo(o) : void 0;
|
|
1731
1776
|
return (s ? r.features.filter((n) => s(n.properties)) : r.features).map((n, p) => this.toGisFeature(n, e, p));
|
|
1732
1777
|
}
|
|
1733
1778
|
/**
|
|
@@ -1742,7 +1787,7 @@ class et {
|
|
|
1742
1787
|
const o = this.categoryMap[e] ?? [];
|
|
1743
1788
|
return (await Promise.all(
|
|
1744
1789
|
o.map((s) => {
|
|
1745
|
-
const a =
|
|
1790
|
+
const a = J(s), n = tt(s), p = et(this.sourceId, e, a);
|
|
1746
1791
|
return this._fetchAndConvert(t, p, n);
|
|
1747
1792
|
})
|
|
1748
1793
|
)).flat();
|
|
@@ -1752,7 +1797,7 @@ class et {
|
|
|
1752
1797
|
const e = Object.entries(this.categoryMap);
|
|
1753
1798
|
for (const [o, r] of e)
|
|
1754
1799
|
for (const s of r) {
|
|
1755
|
-
const a =
|
|
1800
|
+
const a = J(s), n = tt(s), p = et(this.sourceId, o, a, n);
|
|
1756
1801
|
if (p.id === t)
|
|
1757
1802
|
return { descriptor: p, cqlFilter: n };
|
|
1758
1803
|
}
|
|
@@ -1776,7 +1821,7 @@ class et {
|
|
|
1776
1821
|
return g.json();
|
|
1777
1822
|
}
|
|
1778
1823
|
toGisFeature(t, e, o) {
|
|
1779
|
-
const [r, s] =
|
|
1824
|
+
const [r, s] = Uo(t.geometry), a = Mo(t.properties, `${e.sourceLayerId}[${o}]`), n = t.bbox ? [t.bbox[0], t.bbox[1], t.bbox[2], t.bbox[3]] : void 0, p = e.tier, c = p === "priority" ? this._extractNormalisedProperties(t, e) : void 0;
|
|
1780
1825
|
return {
|
|
1781
1826
|
id: t.id ?? `${e.sourceLayerId}/${o}`,
|
|
1782
1827
|
preferredColor: e.preferredColor,
|
|
@@ -1797,10 +1842,10 @@ class et {
|
|
|
1797
1842
|
};
|
|
1798
1843
|
}
|
|
1799
1844
|
_extractNormalisedProperties(t, e) {
|
|
1800
|
-
return e.category === "building" ?
|
|
1845
|
+
return e.category === "building" ? $o(t.properties, this.sourceId) : e.category === "greenspace" ? Bo(t.properties) : e.category === "paved" ? Go(t.properties) : e.category === "zone" ? Ho(t.properties) : Fo(t.properties, this.sourceId);
|
|
1801
1846
|
}
|
|
1802
1847
|
}
|
|
1803
|
-
const
|
|
1848
|
+
const ge = [8, 54.5, 15.2, 57.8], ue = {
|
|
1804
1849
|
building: [
|
|
1805
1850
|
{ source: "danish-matrikel", typename: "bbr_v001:bygning_current" }
|
|
1806
1851
|
],
|
|
@@ -1809,7 +1854,7 @@ const he = [8, 54.5, 15.2, 57.8], de = {
|
|
|
1809
1854
|
{ source: "danish-matrikel", typename: "mat_v001:samletfastejendom_current" }
|
|
1810
1855
|
]
|
|
1811
1856
|
};
|
|
1812
|
-
function
|
|
1857
|
+
function Vo(i) {
|
|
1813
1858
|
if (!i) return [0, 0];
|
|
1814
1859
|
const t = i.coordinates;
|
|
1815
1860
|
switch (i.type) {
|
|
@@ -1827,7 +1872,7 @@ function Go(i) {
|
|
|
1827
1872
|
return [0, 0];
|
|
1828
1873
|
}
|
|
1829
1874
|
}
|
|
1830
|
-
function
|
|
1875
|
+
function Ko(i, t) {
|
|
1831
1876
|
if (!i) return t;
|
|
1832
1877
|
for (const e of [
|
|
1833
1878
|
"mat:matrikelnummer",
|
|
@@ -1843,14 +1888,14 @@ function Ho(i, t) {
|
|
|
1843
1888
|
if (typeof i[e] == "string" && i[e]) return i[e];
|
|
1844
1889
|
return t;
|
|
1845
1890
|
}
|
|
1846
|
-
function
|
|
1891
|
+
function Qo(i, t, e) {
|
|
1847
1892
|
return `${i}:${t}:${e}`;
|
|
1848
1893
|
}
|
|
1849
|
-
const
|
|
1850
|
-
function
|
|
1851
|
-
const o = e.typename.replace(/^[^:]+:/, ""), r = S(t), s =
|
|
1894
|
+
const Xo = /* @__PURE__ */ new Set(["building", "cadastre", "zone"]);
|
|
1895
|
+
function rt(i, t, e) {
|
|
1896
|
+
const o = e.typename.replace(/^[^:]+:/, ""), r = S(t), s = Xo.has(t) ? "priority" : "raw";
|
|
1852
1897
|
return {
|
|
1853
|
-
id:
|
|
1898
|
+
id: Qo(i, e.source, e.typename),
|
|
1854
1899
|
sourceId: i,
|
|
1855
1900
|
sourceLayerId: e.typename,
|
|
1856
1901
|
category: t,
|
|
@@ -1862,7 +1907,7 @@ function ot(i, t, e) {
|
|
|
1862
1907
|
descriptionKey: `gis.layer.${i}.${e.source}.${o}.description`
|
|
1863
1908
|
};
|
|
1864
1909
|
}
|
|
1865
|
-
function
|
|
1910
|
+
function Yo(i, t) {
|
|
1866
1911
|
if (t === "building") {
|
|
1867
1912
|
const a = i?.byg041BebyggetAreal ?? i?.byg038SamletBygningsareal, n = i?.byg021BygningensAnvendelse, p = i?.id_lokalId, c = i?.byg026Opførelsesår;
|
|
1868
1913
|
return {
|
|
@@ -1879,8 +1924,8 @@ function Ko(i, t) {
|
|
|
1879
1924
|
featureType: "zone",
|
|
1880
1925
|
zoneType: a ?? void 0,
|
|
1881
1926
|
zoneCode: p ?? void 0,
|
|
1882
|
-
legalStatus:
|
|
1883
|
-
planType:
|
|
1927
|
+
legalStatus: he(c),
|
|
1928
|
+
planType: de(i?.typ_gde_bezeichnung),
|
|
1884
1929
|
planId: n ?? void 0,
|
|
1885
1930
|
planDocumentLink: h ?? void 0,
|
|
1886
1931
|
publicationDate: i?.auflagedatum ?? void 0,
|
|
@@ -1898,13 +1943,13 @@ function Ko(i, t) {
|
|
|
1898
1943
|
registryId: s ?? void 0
|
|
1899
1944
|
};
|
|
1900
1945
|
}
|
|
1901
|
-
class
|
|
1946
|
+
class Zo {
|
|
1902
1947
|
categoryMap;
|
|
1903
1948
|
dataViewsBaseUrl;
|
|
1904
1949
|
getHeaders;
|
|
1905
1950
|
sourceId;
|
|
1906
1951
|
constructor(t) {
|
|
1907
|
-
this.dataViewsBaseUrl = t.dataViewsBaseUrl.replace(/\/$/, ""), this.getHeaders = t.getHeaders, this.categoryMap = t.categoryMap ??
|
|
1952
|
+
this.dataViewsBaseUrl = t.dataViewsBaseUrl.replace(/\/$/, ""), this.getHeaders = t.getHeaders, this.categoryMap = t.categoryMap ?? ue, this.sourceId = t.sourceId ?? "cue-sdk-gis";
|
|
1908
1953
|
}
|
|
1909
1954
|
async listFeatureCategoryDescriptors(t) {
|
|
1910
1955
|
const e = await this.listAvailableLayers(t);
|
|
@@ -1925,7 +1970,7 @@ class Qo {
|
|
|
1925
1970
|
)
|
|
1926
1971
|
)).filter(
|
|
1927
1972
|
(r) => r.status === "fulfilled" && r.value.hasResults
|
|
1928
|
-
).map((r) =>
|
|
1973
|
+
).map((r) => rt(this.sourceId, r.value.category, r.value.entry));
|
|
1929
1974
|
}
|
|
1930
1975
|
async getFeaturesForLayer(t, e) {
|
|
1931
1976
|
const o = this._findLayerById(e);
|
|
@@ -1939,7 +1984,7 @@ class Qo {
|
|
|
1939
1984
|
const o = this.categoryMap[e] ?? [];
|
|
1940
1985
|
return (await Promise.all(
|
|
1941
1986
|
o.map((s) => {
|
|
1942
|
-
const a =
|
|
1987
|
+
const a = rt(this.sourceId, e, s);
|
|
1943
1988
|
return this.getFeaturesForLayer(t, a.id);
|
|
1944
1989
|
})
|
|
1945
1990
|
)).flat();
|
|
@@ -1948,7 +1993,7 @@ class Qo {
|
|
|
1948
1993
|
_findLayerById(t) {
|
|
1949
1994
|
for (const [e, o] of Object.entries(this.categoryMap))
|
|
1950
1995
|
for (const r of o) {
|
|
1951
|
-
const s =
|
|
1996
|
+
const s = rt(this.sourceId, e, r);
|
|
1952
1997
|
if (s.id === t) return { entry: r, descriptor: s };
|
|
1953
1998
|
}
|
|
1954
1999
|
}
|
|
@@ -1967,7 +2012,7 @@ class Qo {
|
|
|
1967
2012
|
return d.json();
|
|
1968
2013
|
}
|
|
1969
2014
|
_toGisFeature(t, e, o) {
|
|
1970
|
-
const [r, s] =
|
|
2015
|
+
const [r, s] = Vo(t.geometry), a = t.id ?? `${e.sourceLayerId}/${o}`, n = Ko(t.properties, a), p = t.bbox ? [t.bbox[0], t.bbox[1], t.bbox[2], t.bbox[3]] : void 0, c = e.tier, h = c === "priority" ? Yo(t.properties, e.category) : void 0;
|
|
1971
2016
|
return {
|
|
1972
2017
|
id: a,
|
|
1973
2018
|
sourceId: this.sourceId,
|
|
@@ -1988,7 +2033,7 @@ class Qo {
|
|
|
1988
2033
|
};
|
|
1989
2034
|
}
|
|
1990
2035
|
}
|
|
1991
|
-
const
|
|
2036
|
+
const Jo = {
|
|
1992
2037
|
address: [
|
|
1993
2038
|
"ms:ogd-0406_arv_basis_avzh_hausnummer_pos_p",
|
|
1994
2039
|
"ms:ogd-0571_afv_gv_strat_strassennetz_l"
|
|
@@ -2036,23 +2081,23 @@ const Xo = {
|
|
|
2036
2081
|
// ÖREB Überlagernde Festlegungen (Flächen) – overlaying planning constraints
|
|
2037
2082
|
"ms:ogd-0155_arv_basis_np_ul_flaeche_f"
|
|
2038
2083
|
]
|
|
2039
|
-
},
|
|
2084
|
+
}, me = [
|
|
2040
2085
|
{
|
|
2041
2086
|
name: "Canton of Zürich",
|
|
2042
|
-
coverageBBox:
|
|
2087
|
+
coverageBBox: qo,
|
|
2043
2088
|
supportedCategories: ["address", "poi", "railway", "natural", "manmade", "building", "cadastre", "greenspace", "paved", "zone"],
|
|
2044
2089
|
priority: 10,
|
|
2045
|
-
adapter: new
|
|
2046
|
-
categoryMap:
|
|
2090
|
+
adapter: new ot({
|
|
2091
|
+
categoryMap: Jo
|
|
2047
2092
|
})
|
|
2048
2093
|
},
|
|
2049
2094
|
{
|
|
2050
2095
|
name: "Switzerland (national AV cadastre)",
|
|
2051
|
-
coverageBBox:
|
|
2096
|
+
coverageBBox: jo,
|
|
2052
2097
|
supportedCategories: ["cadastre"],
|
|
2053
2098
|
priority: 5,
|
|
2054
2099
|
// Lower priority than canton-specific adapters. For ZH, the canton adapter (priority 10) wins.
|
|
2055
|
-
adapter: new
|
|
2100
|
+
adapter: new ot({
|
|
2056
2101
|
sourceId: "swiss-av-wfs",
|
|
2057
2102
|
baseUrl: "https://wfs.geodienste.ch/av_0/deu",
|
|
2058
2103
|
categoryMap: {
|
|
@@ -2076,10 +2121,10 @@ const Xo = {
|
|
|
2076
2121
|
* - `pdk:kommuneplanramme_vedtaget` – adopted municipal plan frameworks
|
|
2077
2122
|
*/
|
|
2078
2123
|
name: "Denmark (Plandata.dk – planning zones)",
|
|
2079
|
-
coverageBBox:
|
|
2124
|
+
coverageBBox: ge,
|
|
2080
2125
|
supportedCategories: ["zone"],
|
|
2081
2126
|
priority: 10,
|
|
2082
|
-
adapter: new
|
|
2127
|
+
adapter: new ot({
|
|
2083
2128
|
sourceId: "danish-plandata",
|
|
2084
2129
|
baseUrl: "https://wfs.plandata.dk/geoserver/pdk/wfs",
|
|
2085
2130
|
outputFormat: "application/json",
|
|
@@ -2094,12 +2139,12 @@ const Xo = {
|
|
|
2094
2139
|
})
|
|
2095
2140
|
}
|
|
2096
2141
|
];
|
|
2097
|
-
function
|
|
2142
|
+
function Bt(i) {
|
|
2098
2143
|
return [...i].sort(
|
|
2099
|
-
(t, e) =>
|
|
2144
|
+
(t, e) => pt.indexOf(t.category) - pt.indexOf(e.category)
|
|
2100
2145
|
);
|
|
2101
2146
|
}
|
|
2102
|
-
class
|
|
2147
|
+
class tr {
|
|
2103
2148
|
nominatim;
|
|
2104
2149
|
regions;
|
|
2105
2150
|
/**
|
|
@@ -2114,9 +2159,9 @@ class Yo {
|
|
|
2114
2159
|
zonePlanTypeColors: r,
|
|
2115
2160
|
...s
|
|
2116
2161
|
} = t;
|
|
2117
|
-
this.nominatim = new
|
|
2118
|
-
const a = o ?
|
|
2119
|
-
this.regions = e ?? a, this.zonePlanTypeColors = { ...
|
|
2162
|
+
this.nominatim = new Co(s);
|
|
2163
|
+
const a = o ? me : [];
|
|
2164
|
+
this.regions = e ?? a, this.zonePlanTypeColors = { ..._o, ...r };
|
|
2120
2165
|
}
|
|
2121
2166
|
/**
|
|
2122
2167
|
* Return the available feature categories together with UI metadata such as
|
|
@@ -2135,12 +2180,12 @@ class Yo {
|
|
|
2135
2180
|
for (const a of e)
|
|
2136
2181
|
for (const n of a.supportedCategories ?? [])
|
|
2137
2182
|
r.has(n) || (r.add(n), s.push(S(n)));
|
|
2138
|
-
for (const a of
|
|
2183
|
+
for (const a of le)
|
|
2139
2184
|
r.has(a) || s.push(S(a));
|
|
2140
|
-
return
|
|
2185
|
+
return Bt(s);
|
|
2141
2186
|
}
|
|
2142
2187
|
const o = await this._adapterFor(t).listFeatureCategoryDescriptors(t);
|
|
2143
|
-
return
|
|
2188
|
+
return Bt(o);
|
|
2144
2189
|
}
|
|
2145
2190
|
/**
|
|
2146
2191
|
* Return the feature categories that have at least one result within the
|
|
@@ -2213,7 +2258,7 @@ class Yo {
|
|
|
2213
2258
|
const { features: n, idx: p } = await Promise.race(a.values());
|
|
2214
2259
|
a.delete(p);
|
|
2215
2260
|
for (const c of n) {
|
|
2216
|
-
const h =
|
|
2261
|
+
const h = Gt(c), d = W(c), g = s.get(h);
|
|
2217
2262
|
(g === void 0 || d > g) && (s.set(h, d), yield c);
|
|
2218
2263
|
}
|
|
2219
2264
|
}
|
|
@@ -2247,9 +2292,9 @@ class Yo {
|
|
|
2247
2292
|
), a = [], n = [];
|
|
2248
2293
|
for (const d of s)
|
|
2249
2294
|
d.status === "fulfilled" && (d.value.isNominatim ? n.push(...d.value.features) : a.push(...d.value.features));
|
|
2250
|
-
const p =
|
|
2295
|
+
const p = rr(a, n), c = /* @__PURE__ */ new Map(), h = [];
|
|
2251
2296
|
for (const d of p) {
|
|
2252
|
-
const g =
|
|
2297
|
+
const g = Gt(d), w = W(d), u = c.get(g);
|
|
2253
2298
|
(u === void 0 || w > u) && (c.set(g, w), h.push(d));
|
|
2254
2299
|
}
|
|
2255
2300
|
return h;
|
|
@@ -2267,22 +2312,22 @@ function W(i) {
|
|
|
2267
2312
|
const t = i.geometry?.type;
|
|
2268
2313
|
return t === "Polygon" || t === "MultiPolygon" ? 3 : t === "LineString" || t === "MultiLineString" ? 2 : 1;
|
|
2269
2314
|
}
|
|
2270
|
-
function
|
|
2315
|
+
function Gt(i) {
|
|
2271
2316
|
const t = Math.round(i.lat * 1e3) / 1e3, e = Math.round(i.lon * 1e3) / 1e3;
|
|
2272
2317
|
return `${(i.name ?? i.id ?? "").toLowerCase().trim()}|${t}|${e}`;
|
|
2273
2318
|
}
|
|
2274
|
-
const
|
|
2275
|
-
function
|
|
2319
|
+
const er = 1e-3;
|
|
2320
|
+
function or(i, t) {
|
|
2276
2321
|
const e = i.lat - t.lat, o = i.lon - t.lon;
|
|
2277
2322
|
return Math.sqrt(e * e + o * o);
|
|
2278
2323
|
}
|
|
2279
|
-
function
|
|
2324
|
+
function rr(i, t) {
|
|
2280
2325
|
if (t.length === 0) return i;
|
|
2281
2326
|
const e = i.filter((a) => W(a) === 3), o = i.filter((a) => W(a) !== 3), r = e.map((a) => ({ feature: { ...a, originalData: { ...a.originalData } }, matched: !1 })), s = [];
|
|
2282
2327
|
for (const a of t) {
|
|
2283
|
-
let n = -1, p =
|
|
2328
|
+
let n = -1, p = er;
|
|
2284
2329
|
for (let c = 0; c < r.length; c++) {
|
|
2285
|
-
const h =
|
|
2330
|
+
const h = or(a, r[c].feature);
|
|
2286
2331
|
h < p && (p = h, n = c);
|
|
2287
2332
|
}
|
|
2288
2333
|
n >= 0 ? (r[n].feature.originalData = {
|
|
@@ -2296,8 +2341,8 @@ function tr(i, t) {
|
|
|
2296
2341
|
...s
|
|
2297
2342
|
];
|
|
2298
2343
|
}
|
|
2299
|
-
const
|
|
2300
|
-
class
|
|
2344
|
+
const sr = "/data-views", ar = 1500;
|
|
2345
|
+
class ir {
|
|
2301
2346
|
// undefined = not yet built
|
|
2302
2347
|
/** @internal — construct via `cue.gis`, not directly. */
|
|
2303
2348
|
constructor(t, e) {
|
|
@@ -2380,25 +2425,25 @@ class rr {
|
|
|
2380
2425
|
}
|
|
2381
2426
|
// ── Private ───────────────────────────────────────────────────────────────
|
|
2382
2427
|
_scheduleDebouncedQuery() {
|
|
2383
|
-
this._debounceTimer !== null && clearTimeout(this._debounceTimer), this._debounceTimer = setTimeout(() => this._queryLayers(),
|
|
2428
|
+
this._debounceTimer !== null && clearTimeout(this._debounceTimer), this._debounceTimer = setTimeout(() => this._queryLayers(), ar);
|
|
2384
2429
|
}
|
|
2385
2430
|
_getGateway() {
|
|
2386
2431
|
if (this._gatewayCache !== null && this._gatewayProjectId === this._projectId)
|
|
2387
2432
|
return this._gatewayCache;
|
|
2388
|
-
const t = this._projectId, e = [...
|
|
2433
|
+
const t = this._projectId, e = [...me];
|
|
2389
2434
|
return t && e.unshift({
|
|
2390
2435
|
name: "Cue SDK (authenticated)",
|
|
2391
|
-
coverageBBox:
|
|
2392
|
-
supportedCategories: Object.keys(
|
|
2436
|
+
coverageBBox: ge,
|
|
2437
|
+
supportedCategories: Object.keys(ue),
|
|
2393
2438
|
priority: 10,
|
|
2394
|
-
adapter: new
|
|
2395
|
-
dataViewsBaseUrl: `${this._gatewayUrl}${
|
|
2439
|
+
adapter: new Zo({
|
|
2440
|
+
dataViewsBaseUrl: `${this._gatewayUrl}${sr}`,
|
|
2396
2441
|
getHeaders: async () => ({
|
|
2397
2442
|
...await this._getAuthHeaders(),
|
|
2398
2443
|
"x-project-id": t
|
|
2399
2444
|
})
|
|
2400
2445
|
})
|
|
2401
|
-
}), this._gatewayCache = new
|
|
2446
|
+
}), this._gatewayCache = new tr({ regions: e }), this._gatewayProjectId = t, this._gatewayCache;
|
|
2402
2447
|
}
|
|
2403
2448
|
async _queryLayers() {
|
|
2404
2449
|
const t = this._bbox;
|
|
@@ -2442,11 +2487,11 @@ class rr {
|
|
|
2442
2487
|
this._loadListeners.forEach((e) => e(t));
|
|
2443
2488
|
}
|
|
2444
2489
|
}
|
|
2445
|
-
class
|
|
2490
|
+
class Ht {
|
|
2446
2491
|
constructor(t, e, o = !1, r) {
|
|
2447
|
-
if (this._auth = t, this._db =
|
|
2492
|
+
if (this._auth = t, this._db = Ie(e), this._functions = se(e, ie), this._gatewayUrl = r?.gatewayUrl ?? "", o) {
|
|
2448
2493
|
const s = r?.firestoreEmulatorHost ?? "localhost", a = r?.firestoreEmulatorPort ?? 8080;
|
|
2449
|
-
|
|
2494
|
+
Ce(this._db, s, a), ae(this._functions, "localhost", 5001);
|
|
2450
2495
|
}
|
|
2451
2496
|
}
|
|
2452
2497
|
_auth;
|
|
@@ -2463,7 +2508,7 @@ class Bt {
|
|
|
2463
2508
|
* Throws if a project with the given ID already exists.
|
|
2464
2509
|
*/
|
|
2465
2510
|
async createProject(t) {
|
|
2466
|
-
const e = await this._auth.authenticatedFetch(`${this._gatewayUrl}${
|
|
2511
|
+
const e = await this._auth.authenticatedFetch(`${this._gatewayUrl}${no}`, {
|
|
2467
2512
|
method: "POST",
|
|
2468
2513
|
headers: { "Content-Type": "application/json" },
|
|
2469
2514
|
body: JSON.stringify(t)
|
|
@@ -2479,12 +2524,12 @@ class Bt {
|
|
|
2479
2524
|
* Access is gated by Firestore rules which check membership.
|
|
2480
2525
|
*/
|
|
2481
2526
|
async listProjects() {
|
|
2482
|
-
const t = this._requireUser(), e =
|
|
2483
|
-
return (await
|
|
2527
|
+
const t = this._requireUser(), e = yt(this._db, It);
|
|
2528
|
+
return (await Te(Se(e, Re("members", "array-contains", t), Ae(100)))).docs.map((r) => r.data());
|
|
2484
2529
|
}
|
|
2485
2530
|
/** Fetch a single project by ID. Returns null if not found. */
|
|
2486
2531
|
async getProject(t) {
|
|
2487
|
-
const e = yt(
|
|
2532
|
+
const e = bt(yt(this._db, It), t), o = await Pe(e);
|
|
2488
2533
|
return o.exists() ? o.data() : null;
|
|
2489
2534
|
}
|
|
2490
2535
|
/**
|
|
@@ -2493,10 +2538,10 @@ class Bt {
|
|
|
2493
2538
|
*/
|
|
2494
2539
|
async incrementUnitsConsumed(t, e, o) {
|
|
2495
2540
|
if (e <= 0) return;
|
|
2496
|
-
const r =
|
|
2497
|
-
await
|
|
2498
|
-
unitsConsumed:
|
|
2499
|
-
lastUpdated:
|
|
2541
|
+
const r = bt(this._db, "clientSync", t);
|
|
2542
|
+
await Oe(r, {
|
|
2543
|
+
unitsConsumed: Le(e),
|
|
2544
|
+
lastUpdated: De(),
|
|
2500
2545
|
lastUserId: o
|
|
2501
2546
|
}, { merge: !0 });
|
|
2502
2547
|
}
|
|
@@ -2519,7 +2564,7 @@ class Bt {
|
|
|
2519
2564
|
*/
|
|
2520
2565
|
async deleteProject(t) {
|
|
2521
2566
|
const e = await this._auth.authenticatedFetch(
|
|
2522
|
-
`${this._gatewayUrl}${
|
|
2567
|
+
`${this._gatewayUrl}${po(t)}`,
|
|
2523
2568
|
{ method: "DELETE" }
|
|
2524
2569
|
);
|
|
2525
2570
|
if (!e.ok) {
|
|
@@ -2528,9 +2573,9 @@ class Bt {
|
|
|
2528
2573
|
}
|
|
2529
2574
|
}
|
|
2530
2575
|
}
|
|
2531
|
-
class
|
|
2576
|
+
class Wt {
|
|
2532
2577
|
constructor(t, e, o, r) {
|
|
2533
|
-
this._auth = t, this._gatewayUrl = r, this._functions =
|
|
2578
|
+
this._auth = t, this._gatewayUrl = r, this._functions = se(e, ie), o && ae(this._functions, "localhost", 5001);
|
|
2534
2579
|
}
|
|
2535
2580
|
_auth;
|
|
2536
2581
|
_gatewayUrl;
|
|
@@ -2547,13 +2592,13 @@ class Gt {
|
|
|
2547
2592
|
}
|
|
2548
2593
|
/** Whether the current user has an active API key. */
|
|
2549
2594
|
async hasAPIKey() {
|
|
2550
|
-
return await this._fetch(
|
|
2595
|
+
return await this._fetch(Ot) !== null;
|
|
2551
2596
|
}
|
|
2552
2597
|
/** Returns the sign-in methods registered for the current user's email. */
|
|
2553
2598
|
async getSignInMethods() {
|
|
2554
2599
|
const t = this._auth.currentUser;
|
|
2555
2600
|
if (!t?.email) throw new Error("User has no e-mail");
|
|
2556
|
-
return
|
|
2601
|
+
return Ge(this._auth.firebaseAuth, t.email);
|
|
2557
2602
|
}
|
|
2558
2603
|
/** Builds a human-readable label from a Firebase UserInfo provider entry. */
|
|
2559
2604
|
buildProviderLabel(t) {
|
|
@@ -2566,42 +2611,42 @@ class Gt {
|
|
|
2566
2611
|
}
|
|
2567
2612
|
/** Links a Google or Microsoft provider to the current account via popup. Returns the new provider label. */
|
|
2568
2613
|
async linkProvider(t) {
|
|
2569
|
-
const e = this._requireUser(), o = t === "google.com" ? new
|
|
2614
|
+
const e = this._requireUser(), o = t === "google.com" ? new it() : new nt(t), s = (await He(e, o)).user.providerData.find(
|
|
2570
2615
|
(a) => a.providerId === t
|
|
2571
2616
|
);
|
|
2572
2617
|
return s ? this.buildProviderLabel(s) : "-";
|
|
2573
2618
|
}
|
|
2574
2619
|
/** Unlinks a provider from the current account. */
|
|
2575
2620
|
async unlinkProvider(t) {
|
|
2576
|
-
await
|
|
2621
|
+
await We(this._requireUser(), t);
|
|
2577
2622
|
}
|
|
2578
2623
|
/** Changes the password. Reauthenticates first. */
|
|
2579
2624
|
async updatePassword(t, e) {
|
|
2580
2625
|
const o = this._requireUser();
|
|
2581
2626
|
if (!o.email) throw new Error("User has no e-mail");
|
|
2582
|
-
await
|
|
2627
|
+
await _t(
|
|
2583
2628
|
o,
|
|
2584
|
-
|
|
2585
|
-
), await
|
|
2629
|
+
X.credential(o.email, t)
|
|
2630
|
+
), await Ve(o, e);
|
|
2586
2631
|
}
|
|
2587
2632
|
/** Adds (sets) a password for an account that currently only uses SSO. */
|
|
2588
2633
|
async addPassword(t) {
|
|
2589
2634
|
const e = this._requireUser();
|
|
2590
2635
|
if (!e.email) throw new Error("User has no e-mail");
|
|
2591
|
-
await
|
|
2636
|
+
await Ke(e, X.credential(e.email, t));
|
|
2592
2637
|
}
|
|
2593
2638
|
/** Requests an e-mail change. Sends a verification e-mail to the new address. */
|
|
2594
2639
|
async updateEmail(t, e) {
|
|
2595
2640
|
const o = this._requireUser();
|
|
2596
2641
|
if (!o.email) throw new Error("User e-mail not available");
|
|
2597
|
-
await
|
|
2642
|
+
await _t(
|
|
2598
2643
|
o,
|
|
2599
|
-
|
|
2600
|
-
), await
|
|
2644
|
+
X.credential(o.email, e)
|
|
2645
|
+
), await Qe(o, t), await Xe(o);
|
|
2601
2646
|
}
|
|
2602
2647
|
/** Creates a new API key for the current user. */
|
|
2603
2648
|
async createAPIKey(t) {
|
|
2604
|
-
return this._fetch(
|
|
2649
|
+
return this._fetch(Dt, {
|
|
2605
2650
|
method: "POST",
|
|
2606
2651
|
headers: { "Content-Type": "application/json" },
|
|
2607
2652
|
body: JSON.stringify({ expiration: t })
|
|
@@ -2610,7 +2655,7 @@ class Gt {
|
|
|
2610
2655
|
/** Revokes the current user's API key. */
|
|
2611
2656
|
async revokeAPIKey() {
|
|
2612
2657
|
const t = await this._auth.authenticatedFetch(
|
|
2613
|
-
this._url(
|
|
2658
|
+
this._url(Dt),
|
|
2614
2659
|
{ method: "DELETE" }
|
|
2615
2660
|
);
|
|
2616
2661
|
if (!t.ok)
|
|
@@ -2618,17 +2663,17 @@ class Gt {
|
|
|
2618
2663
|
}
|
|
2619
2664
|
/** Fetches the current user's existing API key. */
|
|
2620
2665
|
async requestAPIKey() {
|
|
2621
|
-
const t = await this._fetch(
|
|
2666
|
+
const t = await this._fetch(Ot);
|
|
2622
2667
|
if (!t) throw new Error("No API key found");
|
|
2623
2668
|
return t;
|
|
2624
2669
|
}
|
|
2625
2670
|
/** Returns organizations the current user is a member of. */
|
|
2626
2671
|
async listOrganizations() {
|
|
2627
|
-
return this._fetch(
|
|
2672
|
+
return this._fetch(so);
|
|
2628
2673
|
}
|
|
2629
2674
|
/** Returns all members of the given organisation. Caller must be an org admin or superadmin. */
|
|
2630
2675
|
async getOrgMembers(t) {
|
|
2631
|
-
return this._fetch(
|
|
2676
|
+
return this._fetch(io(t));
|
|
2632
2677
|
}
|
|
2633
2678
|
_requireUser() {
|
|
2634
2679
|
const t = this._auth.currentUser;
|
|
@@ -2644,7 +2689,7 @@ class Gt {
|
|
|
2644
2689
|
}
|
|
2645
2690
|
/** Record that the current user has accepted the terms of service. Sets a `terms` custom claim on the token. */
|
|
2646
2691
|
async acceptTerms(t) {
|
|
2647
|
-
await this._fetch(
|
|
2692
|
+
await this._fetch(ao, {
|
|
2648
2693
|
method: "POST",
|
|
2649
2694
|
headers: { "Content-Type": "application/json" },
|
|
2650
2695
|
body: JSON.stringify({ version: t })
|
|
@@ -2658,10 +2703,10 @@ class Gt {
|
|
|
2658
2703
|
*/
|
|
2659
2704
|
async latestTermsAccepted() {
|
|
2660
2705
|
const t = this._auth.currentUser;
|
|
2661
|
-
return t ? (await
|
|
2706
|
+
return t ? (await at(t)).claims.terms ?? null : null;
|
|
2662
2707
|
}
|
|
2663
2708
|
}
|
|
2664
|
-
const
|
|
2709
|
+
const Vt = ["superadmin", "admin", "syncer", "member"], Kt = {
|
|
2665
2710
|
createEntities: "admin",
|
|
2666
2711
|
createProvider: "superadmin",
|
|
2667
2712
|
changeContentCategories: "syncer",
|
|
@@ -2677,7 +2722,7 @@ const Ht = ["superadmin", "admin", "syncer", "member"], Wt = {
|
|
|
2677
2722
|
uploadDocuments: "syncer",
|
|
2678
2723
|
viewEntities: "member"
|
|
2679
2724
|
};
|
|
2680
|
-
function
|
|
2725
|
+
function nr() {
|
|
2681
2726
|
return {
|
|
2682
2727
|
changeContentCategories: !1,
|
|
2683
2728
|
createEntities: !1,
|
|
@@ -2696,9 +2741,9 @@ function sr() {
|
|
|
2696
2741
|
viewEntities: !1
|
|
2697
2742
|
};
|
|
2698
2743
|
}
|
|
2699
|
-
class
|
|
2744
|
+
class Qt {
|
|
2700
2745
|
constructor(t) {
|
|
2701
|
-
this._isSuperAdmin = t, this._projectRoles = new k([]), this._orgRole = new k(null), this.privileges =
|
|
2746
|
+
this._isSuperAdmin = t, this._projectRoles = new k([]), this._orgRole = new k(null), this.privileges = dt(
|
|
2702
2747
|
[this._projectRoles, this._orgRole, t],
|
|
2703
2748
|
() => this._compute()
|
|
2704
2749
|
);
|
|
@@ -2735,17 +2780,17 @@ class Vt {
|
|
|
2735
2780
|
_expand(t) {
|
|
2736
2781
|
if (this._isSuperAdmin.get())
|
|
2737
2782
|
return ["superadmin", "admin", "syncer", "member"];
|
|
2738
|
-
const e =
|
|
2739
|
-
return e === -1 ? [] : Array.from(
|
|
2783
|
+
const e = Vt.findIndex((o) => t.includes(o));
|
|
2784
|
+
return e === -1 ? [] : Array.from(Vt.slice(e));
|
|
2740
2785
|
}
|
|
2741
2786
|
_compute() {
|
|
2742
|
-
const t = this._projectRoles.get(), e = this._isSuperAdmin.get(), o =
|
|
2743
|
-
for (const r of Object.keys(
|
|
2744
|
-
o[r] = t.includes(
|
|
2787
|
+
const t = this._projectRoles.get(), e = this._isSuperAdmin.get(), o = nr();
|
|
2788
|
+
for (const r of Object.keys(Kt))
|
|
2789
|
+
o[r] = t.includes(Kt[r]);
|
|
2745
2790
|
return o.createProject = e || this._orgRole.get() === "admin", o;
|
|
2746
2791
|
}
|
|
2747
2792
|
}
|
|
2748
|
-
class
|
|
2793
|
+
class Xt {
|
|
2749
2794
|
constructor(t) {
|
|
2750
2795
|
this._storage = t;
|
|
2751
2796
|
}
|
|
@@ -2778,7 +2823,7 @@ class Kt {
|
|
|
2778
2823
|
// ── Internal helpers ───────────────────────────────────────────────────────
|
|
2779
2824
|
async _get(t, e) {
|
|
2780
2825
|
try {
|
|
2781
|
-
const r = await (await
|
|
2826
|
+
const r = await (await re(_(this._storage, `${t}/${e}.json.gz`))).arrayBuffer(), s = new DecompressionStream("gzip"), a = s.writable.getWriter(), n = s.readable.getReader();
|
|
2782
2827
|
a.write(new Uint8Array(r)), a.close();
|
|
2783
2828
|
const p = [];
|
|
2784
2829
|
let c = await n.read();
|
|
@@ -2790,7 +2835,7 @@ class Kt {
|
|
|
2790
2835
|
d.set(w, g), g += w.length;
|
|
2791
2836
|
return JSON.parse(new TextDecoder().decode(d));
|
|
2792
2837
|
} catch (o) {
|
|
2793
|
-
if (
|
|
2838
|
+
if (pr(o)) return;
|
|
2794
2839
|
throw o;
|
|
2795
2840
|
}
|
|
2796
2841
|
}
|
|
@@ -2805,17 +2850,17 @@ class Kt {
|
|
|
2805
2850
|
let g = 0;
|
|
2806
2851
|
for (const w of p)
|
|
2807
2852
|
d.set(w, g), g += w.length;
|
|
2808
|
-
await
|
|
2853
|
+
await st(
|
|
2809
2854
|
_(this._storage, `${t}/${e}.json.gz`),
|
|
2810
2855
|
d,
|
|
2811
2856
|
{ contentType: "application/gzip" }
|
|
2812
2857
|
);
|
|
2813
2858
|
}
|
|
2814
2859
|
}
|
|
2815
|
-
function
|
|
2860
|
+
function pr(i) {
|
|
2816
2861
|
return typeof i == "object" && i !== null && "code" in i && i.code === "storage/object-not-found";
|
|
2817
2862
|
}
|
|
2818
|
-
const
|
|
2863
|
+
const y = {
|
|
2819
2864
|
qcy: "https://dev.qaecy.com/ont#",
|
|
2820
2865
|
"qcy-e": "https://dev.qaecy.com/enum#",
|
|
2821
2866
|
"qcy-l": "https://dev.qaecy.com/logs#",
|
|
@@ -6063,12 +6108,12 @@ const b = {
|
|
|
6063
6108
|
fbsp: "http://purl.obolibrary.org/obo/FBSP_",
|
|
6064
6109
|
rex: "http://purl.obolibrary.org/obo/REX_"
|
|
6065
6110
|
};
|
|
6066
|
-
class
|
|
6111
|
+
class V {
|
|
6067
6112
|
static _instance;
|
|
6068
6113
|
// Opposite map is built once
|
|
6069
6114
|
_nsMap;
|
|
6070
6115
|
static getInstance() {
|
|
6071
|
-
return this._instance ? this._instance : (this._instance = new
|
|
6116
|
+
return this._instance ? this._instance : (this._instance = new V(), this._instance);
|
|
6072
6117
|
}
|
|
6073
6118
|
compactIRI(t) {
|
|
6074
6119
|
let e = this._nsMap;
|
|
@@ -6084,17 +6129,17 @@ class gt {
|
|
|
6084
6129
|
return r === void 0 ? t : t.replace(o, `${r}:`);
|
|
6085
6130
|
}
|
|
6086
6131
|
expandIRI(t) {
|
|
6087
|
-
const e = t.split(":")[0], o = A[e] ??
|
|
6132
|
+
const e = t.split(":")[0], o = A[e] ?? y[e];
|
|
6088
6133
|
return t.replace(`${e}:`, o);
|
|
6089
6134
|
}
|
|
6090
6135
|
_buildNSMap() {
|
|
6091
6136
|
const t = {};
|
|
6092
|
-
return Object.keys(A).forEach((e) => t[A[e]] = e), Object.keys(
|
|
6093
|
-
(e) => t[
|
|
6137
|
+
return Object.keys(A).forEach((e) => t[A[e]] = e), Object.keys(y).forEach(
|
|
6138
|
+
(e) => t[y[e]] = e
|
|
6094
6139
|
), this._nsMap = t, t;
|
|
6095
6140
|
}
|
|
6096
6141
|
}
|
|
6097
|
-
class
|
|
6142
|
+
class lr {
|
|
6098
6143
|
constructor(t, e, o, r, s) {
|
|
6099
6144
|
this._api = t, this._projectId = e, this._queryCache = r, this._graphType = s, this._currentLang = o, this._api.setLanguage(o), this._contentCategories = new k([]), this._entityCategories = new k([]), this._relationships = new k([]), this.availableContentCategories = this._contentCategories.asReadonly(), this.availableEntityCategories = this._entityCategories.asReadonly(), this.availableEntityRelationships = this._relationships.asReadonly(), this.ready = this._load(o).catch(
|
|
6100
6145
|
(a) => console.error("[CueProjectSchema] Initial load failed:", a)
|
|
@@ -6150,7 +6195,7 @@ class ir {
|
|
|
6150
6195
|
return;
|
|
6151
6196
|
}
|
|
6152
6197
|
const o = this._buildCategoriesQuery(t, "ContentCategory"), r = this._buildCategoriesQuery(t, "EntityCategory"), s = this._buildRelationshipsQuery(t);
|
|
6153
|
-
await
|
|
6198
|
+
await gt(
|
|
6154
6199
|
o + r + s,
|
|
6155
6200
|
async () => {
|
|
6156
6201
|
const [a, n, p] = await Promise.all([
|
|
@@ -6173,7 +6218,7 @@ class ir {
|
|
|
6173
6218
|
return this._runCategoriesQuery(this._buildCategoriesQuery(t, e));
|
|
6174
6219
|
}
|
|
6175
6220
|
_buildCategoriesQuery(t, e) {
|
|
6176
|
-
return `PREFIX qcy: <${
|
|
6221
|
+
return `PREFIX qcy: <${y.qcy}>
|
|
6177
6222
|
PREFIX skos: <${A.skos}>
|
|
6178
6223
|
SELECT ?iri ?parent (SAMPLE(?l) AS ?label)
|
|
6179
6224
|
WHERE {
|
|
@@ -6199,7 +6244,7 @@ GROUP BY ?iri ?parent`;
|
|
|
6199
6244
|
return this._runRelationshipsQuery(this._buildRelationshipsQuery(t));
|
|
6200
6245
|
}
|
|
6201
6246
|
_buildRelationshipsQuery(t) {
|
|
6202
|
-
return `PREFIX qcy: <${
|
|
6247
|
+
return `PREFIX qcy: <${y.qcy}>
|
|
6203
6248
|
PREFIX rdfs: <${A.rdfs}>
|
|
6204
6249
|
SELECT ?iri ?parent (SAMPLE(?l) AS ?label)
|
|
6205
6250
|
WHERE {
|
|
@@ -6223,9 +6268,9 @@ GROUP BY ?iri ?parent`;
|
|
|
6223
6268
|
});
|
|
6224
6269
|
}
|
|
6225
6270
|
}
|
|
6226
|
-
const
|
|
6227
|
-
class
|
|
6228
|
-
constructor(t, e, o =
|
|
6271
|
+
const cr = "https://qlever.dev/api/osm-planet";
|
|
6272
|
+
class we {
|
|
6273
|
+
constructor(t, e, o = ut, r, s) {
|
|
6229
6274
|
this._api = t, this._projectId = e, this._queryCache = r, this._graphType = s, this.baseURL = `${o}${e}/`, this.entityInfoMap = this._entityInfoMapComputed, this.entityGraph = this._entityGraph.asReadonly(), this._entityOSMMap.subscribe(() => this._checkPendingOSMFetches()), this._fetchEntityGraph().catch(
|
|
6230
6275
|
(a) => console.error("[CueProjectEntities] Entity graph fetch failed:", a)
|
|
6231
6276
|
);
|
|
@@ -6247,7 +6292,7 @@ class ue {
|
|
|
6247
6292
|
_fetchingOSMIds = /* @__PURE__ */ new Set();
|
|
6248
6293
|
_entityGraph = new k(void 0);
|
|
6249
6294
|
// ── Derived signals ────────────────────────────────────────────────────────
|
|
6250
|
-
_entityInfoMapComputed =
|
|
6295
|
+
_entityInfoMapComputed = dt(
|
|
6251
6296
|
[
|
|
6252
6297
|
this._entityDetails,
|
|
6253
6298
|
this._entityDocuments,
|
|
@@ -6293,7 +6338,7 @@ class ue {
|
|
|
6293
6338
|
(a) => this._entityDetails.get()[a] === void 0
|
|
6294
6339
|
);
|
|
6295
6340
|
if (o.length === 0) return;
|
|
6296
|
-
const r = o.map((a) => `r:${a}`).join(" "), s = `PREFIX qcy: <${
|
|
6341
|
+
const r = o.map((a) => `r:${a}`).join(" "), s = `PREFIX qcy: <${y.qcy}>
|
|
6297
6342
|
PREFIX r: <${this.baseURL}>
|
|
6298
6343
|
SELECT ?id (SAMPLE(?val) AS ?value) (GROUP_CONCAT(DISTINCT STR(?cat); SEPARATOR=";") AS ?categories) ?mentionCount
|
|
6299
6344
|
WHERE {
|
|
@@ -6337,7 +6382,7 @@ GROUP BY ?id ?mentionCount`;
|
|
|
6337
6382
|
const o = { ...this._entityOSMMap.get() };
|
|
6338
6383
|
for (const p of e) o[p] = { direct: [], indirect: [] };
|
|
6339
6384
|
this._entityOSMMap.set(o);
|
|
6340
|
-
const r = e.map((p) => `r:${p}`).join(" "), s = `PREFIX qcy: <${
|
|
6385
|
+
const r = e.map((p) => `r:${p}`).join(" "), s = `PREFIX qcy: <${y.qcy}>
|
|
6341
6386
|
PREFIX r: <${this.baseURL}>
|
|
6342
6387
|
SELECT ?id ?osm ?direct ?rels ?entityUUID
|
|
6343
6388
|
WHERE {
|
|
@@ -6408,7 +6453,7 @@ WHERE {
|
|
|
6408
6453
|
async fetchEntityDocuments(t) {
|
|
6409
6454
|
const e = t.replace(/^.*\/([^/]*)$/, "$1");
|
|
6410
6455
|
this._entityDocuments.set({ ...this._entityDocuments.get(), [e]: [] }), this._entityDetails.get()[e] === void 0 && this.requestEntityData([e]);
|
|
6411
|
-
const o = `PREFIX qcy: <${
|
|
6456
|
+
const o = `PREFIX qcy: <${y.qcy}>
|
|
6412
6457
|
SELECT DISTINCT ?id
|
|
6413
6458
|
WHERE {
|
|
6414
6459
|
BIND(<${t}> AS ?iri)
|
|
@@ -6428,7 +6473,7 @@ WHERE {
|
|
|
6428
6473
|
* falls back to an untagged label when no match is found.
|
|
6429
6474
|
*/
|
|
6430
6475
|
async contentCategoriesInProject(t = !0) {
|
|
6431
|
-
const e = this._api.language, o = `PREFIX qcy: <${
|
|
6476
|
+
const e = this._api.language, o = `PREFIX qcy: <${y.qcy}>
|
|
6432
6477
|
PREFIX skos: <${A.skos}>
|
|
6433
6478
|
SELECT ?iri (SAMPLE(?l) AS ?label) ?count
|
|
6434
6479
|
WHERE {
|
|
@@ -6452,8 +6497,44 @@ ORDER BY ${t ? "DESC(?count)" : "ASC(?label)"}`;
|
|
|
6452
6497
|
};
|
|
6453
6498
|
});
|
|
6454
6499
|
}
|
|
6500
|
+
async entitiesByCategory(t, e = !1) {
|
|
6501
|
+
if (t.length === 0) return [];
|
|
6502
|
+
const o = V.getInstance(), r = (p) => p.startsWith("http://") || p.startsWith("https://") ? p : o.expandIRI(p), s = t.map((p) => `<${r(p)}>`).join(" "), a = e ? `PREFIX qcy: <${y.qcy}>
|
|
6503
|
+
SELECT ?iri ?id (SAMPLE(?val) AS ?value) (GROUP_CONCAT(DISTINCT STR(?allCat); SEPARATOR=";") AS ?categories)
|
|
6504
|
+
WHERE {
|
|
6505
|
+
VALUES ?filterCat { ${s} }
|
|
6506
|
+
?iri a qcy:CanonicalEntity ;
|
|
6507
|
+
qcy:hasEntityCategory ?filterCat ;
|
|
6508
|
+
qcy:value ?val ;
|
|
6509
|
+
qcy:hasEntityCategory ?allCat .
|
|
6510
|
+
BIND(REPLACE(STR(?iri), "^.*/([^/]*)$", "$1") AS ?id)
|
|
6511
|
+
}
|
|
6512
|
+
GROUP BY ?iri ?id` : `PREFIX qcy: <${y.qcy}>
|
|
6513
|
+
SELECT DISTINCT ?iri ?id
|
|
6514
|
+
WHERE {
|
|
6515
|
+
VALUES ?filterCat { ${s} }
|
|
6516
|
+
?iri a qcy:CanonicalEntity ;
|
|
6517
|
+
qcy:hasEntityCategory ?filterCat .
|
|
6518
|
+
BIND(REPLACE(STR(?iri), "^.*/([^/]*)$", "$1") AS ?id)
|
|
6519
|
+
}`;
|
|
6520
|
+
return (await this._api.sparql(
|
|
6521
|
+
a,
|
|
6522
|
+
this._projectId,
|
|
6523
|
+
this._graphType
|
|
6524
|
+
)).results.bindings.filter((p) => p.iri && p.id).map(
|
|
6525
|
+
(p) => e ? {
|
|
6526
|
+
iri: p.iri.value,
|
|
6527
|
+
uuid: p.id.value,
|
|
6528
|
+
value: p.value?.value ?? "",
|
|
6529
|
+
categories: p.categories?.value?.split(";").filter(Boolean) ?? []
|
|
6530
|
+
} : {
|
|
6531
|
+
iri: p.iri.value,
|
|
6532
|
+
uuid: p.id.value
|
|
6533
|
+
}
|
|
6534
|
+
);
|
|
6535
|
+
}
|
|
6455
6536
|
async buildSummaryGraph(t) {
|
|
6456
|
-
const e = `PREFIX qcy: <${
|
|
6537
|
+
const e = `PREFIX qcy: <${y.qcy}>
|
|
6457
6538
|
SELECT
|
|
6458
6539
|
?sourceCat
|
|
6459
6540
|
?predicate
|
|
@@ -6488,7 +6569,7 @@ ORDER BY DESC(?weight)`, o = await this._api.sparql(
|
|
|
6488
6569
|
};
|
|
6489
6570
|
}
|
|
6490
6571
|
if (t === "md") {
|
|
6491
|
-
const s =
|
|
6572
|
+
const s = V.getInstance(), a = r.map((h) => ({
|
|
6492
6573
|
src: s.compactIRI(h.sourceCat.value),
|
|
6493
6574
|
pred: s.compactIRI(h.predicate.value),
|
|
6494
6575
|
tgt: s.compactIRI(h.targetCat.value),
|
|
@@ -6525,8 +6606,8 @@ ORDER BY DESC(?weight)`, o = await this._api.sparql(
|
|
|
6525
6606
|
const x = s[f];
|
|
6526
6607
|
if (x)
|
|
6527
6608
|
for (const I of E) {
|
|
6528
|
-
const v = `${I}:${m}`,
|
|
6529
|
-
|
|
6609
|
+
const v = `${I}:${m}`, b = u.get(v) ?? { geometries: [], entityUUID: m };
|
|
6610
|
+
b.geometries.some((C) => C.osmIRI === f) || (b.geometries.push({ osmIRI: f, wkt: x }), u.set(v, b));
|
|
6530
6611
|
}
|
|
6531
6612
|
}
|
|
6532
6613
|
u.size > 0 && (g = Array.from(u.entries()).map(
|
|
@@ -6550,7 +6631,7 @@ ORDER BY DESC(?weight)`, o = await this._api.sparql(
|
|
|
6550
6631
|
return n;
|
|
6551
6632
|
}
|
|
6552
6633
|
async _fetchOutgoingRelationships(t) {
|
|
6553
|
-
const e = `PREFIX qcy: <${
|
|
6634
|
+
const e = `PREFIX qcy: <${y.qcy}>
|
|
6554
6635
|
SELECT ?rel ?related (SAMPLE(?val) AS ?nodeValue) (GROUP_CONCAT(STR(?cat); SEPARATOR=";") AS ?categories)
|
|
6555
6636
|
WHERE {
|
|
6556
6637
|
BIND(<${t}> AS ?s)
|
|
@@ -6582,7 +6663,7 @@ GROUP BY ?rel ?related`, o = await this._api.sparql(
|
|
|
6582
6663
|
}), this._entityDetails.set(s), r;
|
|
6583
6664
|
}
|
|
6584
6665
|
async _fetchIncomingRelationships(t) {
|
|
6585
|
-
const e = `PREFIX qcy: <${
|
|
6666
|
+
const e = `PREFIX qcy: <${y.qcy}>
|
|
6586
6667
|
SELECT ?rel ?relating (SAMPLE(?val) AS ?nodeValue) (GROUP_CONCAT(STR(?cat); SEPARATOR=";") AS ?categories)
|
|
6587
6668
|
WHERE {
|
|
6588
6669
|
BIND(<${t}> AS ?s)
|
|
@@ -6614,7 +6695,7 @@ GROUP BY ?rel ?relating`, o = await this._api.sparql(
|
|
|
6614
6695
|
}), this._entityDetails.set(s), r;
|
|
6615
6696
|
}
|
|
6616
6697
|
async _fetchEntityGraph() {
|
|
6617
|
-
const t = `PREFIX qcy: <${
|
|
6698
|
+
const t = `PREFIX qcy: <${y.qcy}>
|
|
6618
6699
|
SELECT ?e1Cat ?e2Cat (COUNT(?e1) AS ?e1Count) (COUNT(?e2) AS ?e2Count)
|
|
6619
6700
|
WHERE {
|
|
6620
6701
|
?e1 a qcy:CanonicalEntity ;
|
|
@@ -6623,7 +6704,7 @@ WHERE {
|
|
|
6623
6704
|
?e2 qcy:hasEntityCategory ?e2Cat
|
|
6624
6705
|
}
|
|
6625
6706
|
GROUP BY ?e1Cat ?e2Cat`;
|
|
6626
|
-
await
|
|
6707
|
+
await gt(
|
|
6627
6708
|
t,
|
|
6628
6709
|
async () => {
|
|
6629
6710
|
const e = await this._api.sparql(
|
|
@@ -6663,7 +6744,7 @@ GROUP BY ?e1Cat ?e2Cat`;
|
|
|
6663
6744
|
const o = e.map((n) => `<${n}>`).join(" "), r = `PREFIX geo: <${A.geo}>
|
|
6664
6745
|
SELECT * WHERE {
|
|
6665
6746
|
VALUES ?s { ${o} }
|
|
6666
|
-
SERVICE <${
|
|
6747
|
+
SERVICE <${cr}> {
|
|
6667
6748
|
?s geo:hasGeometry/geo:asWKT ?wkt
|
|
6668
6749
|
}
|
|
6669
6750
|
}`, s = await this._api.sparql(
|
|
@@ -6676,500 +6757,8 @@ SELECT * WHERE {
|
|
|
6676
6757
|
}), this._osmWKTMap.set(a);
|
|
6677
6758
|
}
|
|
6678
6759
|
}
|
|
6679
|
-
class pt {
|
|
6680
|
-
constructor(t, e, o, r = dt, s, a) {
|
|
6681
|
-
this._api = t, this._projectId = e, this._queryCache = s, this._graphType = a, this.baseURL = `${r}${e}/`, this._currentLang = o ?? this._api.language, this.documentInfoMap = this._documentInfoMap.asReadonly(), this.projectDocumentsData = this._projectDocumentsData.asReadonly();
|
|
6682
|
-
}
|
|
6683
|
-
_api;
|
|
6684
|
-
_projectId;
|
|
6685
|
-
_queryCache;
|
|
6686
|
-
_graphType;
|
|
6687
|
-
/** Full RDF base URL for this project, e.g. `https://cue.qaecy.com/r/{pid}/` */
|
|
6688
|
-
baseURL;
|
|
6689
|
-
/** Tracks the language for which `_documentInfoMap` is currently populated. */
|
|
6690
|
-
_currentLang;
|
|
6691
|
-
_documentInfoMap = new k({});
|
|
6692
|
-
_projectDocumentsData = new k({
|
|
6693
|
-
duplicateCount: 0,
|
|
6694
|
-
documentsBySuffix: {},
|
|
6695
|
-
documentsByContentCategory: {}
|
|
6696
|
-
});
|
|
6697
|
-
/** Lazily populated per-document detail map. */
|
|
6698
|
-
documentInfoMap;
|
|
6699
|
-
/** Project-level document overview (grouped counts + sizes). */
|
|
6700
|
-
projectDocumentsData;
|
|
6701
|
-
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
6702
|
-
/**
|
|
6703
|
-
* Resets all document state. Call when the active project changes.
|
|
6704
|
-
* Follow with `fetchOverview()` once the triplestore is ready.
|
|
6705
|
-
*/
|
|
6706
|
-
reset() {
|
|
6707
|
-
this._documentInfoMap.set({}), this._projectDocumentsData.set({
|
|
6708
|
-
duplicateCount: 0,
|
|
6709
|
-
documentsBySuffix: {},
|
|
6710
|
-
documentsByContentCategory: {}
|
|
6711
|
-
});
|
|
6712
|
-
}
|
|
6713
|
-
/**
|
|
6714
|
-
* Updates the active language and clears the document info map so that
|
|
6715
|
-
* language-sensitive fields (subject, summary) are re-fetched on the next
|
|
6716
|
-
* `requestDocumentData()` call.
|
|
6717
|
-
*/
|
|
6718
|
-
setLanguage(t) {
|
|
6719
|
-
this._currentLang !== t && (this._currentLang = t, this._api.setLanguage(t), this._documentInfoMap.set({}));
|
|
6720
|
-
}
|
|
6721
|
-
// ── Public API ─────────────────────────────────────────────────────────────
|
|
6722
|
-
/**
|
|
6723
|
-
* Fetches the three-part project overview (by suffix, by content category,
|
|
6724
|
-
* duplicate count) in parallel and writes them as a single atomic update to
|
|
6725
|
-
* `projectDocumentsData`. Safe to call again to refresh.
|
|
6726
|
-
*/
|
|
6727
|
-
async fetchOverview() {
|
|
6728
|
-
this._projectDocumentsData.set({
|
|
6729
|
-
duplicateCount: 0,
|
|
6730
|
-
documentsBySuffix: {},
|
|
6731
|
-
documentsByContentCategory: {}
|
|
6732
|
-
});
|
|
6733
|
-
const t = this._buildDocumentsBySuffixQuery(), e = this._buildDocumentsByContentCategoryQuery(), o = this._buildDuplicateCountQuery();
|
|
6734
|
-
await ht(
|
|
6735
|
-
t + e + o,
|
|
6736
|
-
async () => {
|
|
6737
|
-
const [r, s, a] = await Promise.all([
|
|
6738
|
-
this._runDocumentsBySuffixQuery(t),
|
|
6739
|
-
this._runDocumentsByContentCategoryQuery(e),
|
|
6740
|
-
this._runDuplicateCountQuery(o)
|
|
6741
|
-
]);
|
|
6742
|
-
return { duplicateCount: a, documentsBySuffix: r, documentsByContentCategory: s };
|
|
6743
|
-
},
|
|
6744
|
-
(r) => this._projectDocumentsData.set(r),
|
|
6745
|
-
this._queryCache
|
|
6746
|
-
);
|
|
6747
|
-
}
|
|
6748
|
-
/**
|
|
6749
|
-
* Lazily batch-fetches core metadata for the given document UUIDs.
|
|
6750
|
-
* Already-cached UUIDs are skipped. Data is merged into `documentInfoMap`
|
|
6751
|
-
* once the SPARQL response arrives.
|
|
6752
|
-
*/
|
|
6753
|
-
requestDocumentData(t) {
|
|
6754
|
-
const e = t.filter((o) => this._documentInfoMap.get()[o] === void 0);
|
|
6755
|
-
e.length !== 0 && this._fetchDocumentInfoBatch(e).catch(
|
|
6756
|
-
(o) => console.error("[CueProjectDocuments] requestDocumentData failed:", o)
|
|
6757
|
-
);
|
|
6758
|
-
}
|
|
6759
|
-
/**
|
|
6760
|
-
* Promise-based alternative to {@link requestDocumentData} for non-reactive contexts.
|
|
6761
|
-
*
|
|
6762
|
-
* Resolves with the `DocumentInfo` entries for every requested UUID once the
|
|
6763
|
-
* SPARQL response arrives. UUIDs already present in the cache are returned
|
|
6764
|
-
* immediately without a network request. The result is also written into
|
|
6765
|
-
* `documentInfoMap` so reactive consumers stay in sync.
|
|
6766
|
-
*
|
|
6767
|
-
* UUIDs not found in the triplestore are omitted from the returned map.
|
|
6768
|
-
*
|
|
6769
|
-
* @example
|
|
6770
|
-
* ```ts
|
|
6771
|
-
* const docs = await cueProjectDocs.fetchDocumentData(['uuid1', 'uuid2']);
|
|
6772
|
-
* console.log(docs['uuid1'].subject);
|
|
6773
|
-
* ```
|
|
6774
|
-
*/
|
|
6775
|
-
async fetchDocumentData(t) {
|
|
6776
|
-
const e = this._documentInfoMap.get(), o = t.filter((s) => e[s] === void 0);
|
|
6777
|
-
o.length > 0 && await this._fetchDocumentInfoBatch(o);
|
|
6778
|
-
const r = this._documentInfoMap.get();
|
|
6779
|
-
return Object.fromEntries(
|
|
6780
|
-
t.filter((s) => r[s] !== void 0).map((s) => [s, r[s]])
|
|
6781
|
-
);
|
|
6782
|
-
}
|
|
6783
|
-
/**
|
|
6784
|
-
* Fetches a lightweight document metadata shape (id/path/suffix/size) for
|
|
6785
|
-
* the given UUIDs and merges the results into `documentInfoMap`.
|
|
6786
|
-
*
|
|
6787
|
-
* This is useful for list/table contexts that do not need language-tagged
|
|
6788
|
-
* fields (`subject`, `summary`) or category/tag enrichment.
|
|
6789
|
-
*
|
|
6790
|
-
* UUIDs already present in `documentInfoMap` are skipped.
|
|
6791
|
-
*/
|
|
6792
|
-
async fetchDocumentDataSimple(t) {
|
|
6793
|
-
const e = this._documentInfoMap.get(), o = t.filter((s) => e[s] === void 0);
|
|
6794
|
-
o.length > 0 && await this._fetchSimpleDocumentInfoBatch(o);
|
|
6795
|
-
const r = this._documentInfoMap.get();
|
|
6796
|
-
return Object.fromEntries(
|
|
6797
|
-
t.filter((s) => r[s] !== void 0).map((s) => [s, r[s]])
|
|
6798
|
-
);
|
|
6799
|
-
}
|
|
6800
|
-
/**
|
|
6801
|
-
* Returns the alternative representations of the given document UUID.
|
|
6802
|
-
*
|
|
6803
|
-
* Alternative representations are derived artefacts stored under
|
|
6804
|
-
* `qcy:alternativeRepresentation` in the triplestore — for example a
|
|
6805
|
-
* `.fragments` BIM tile derived from an `.ifc` source file.
|
|
6806
|
-
*
|
|
6807
|
-
* The returned `DocumentInfo` entries are also merged into
|
|
6808
|
-
* `documentInfoMap` so reactive consumers stay in sync.
|
|
6809
|
-
*
|
|
6810
|
-
* @example
|
|
6811
|
-
* ```ts
|
|
6812
|
-
* const alts = await docs.fetchAlternativeRepresentations('abc-123');
|
|
6813
|
-
* // alts[0].suffix => '.fragments'
|
|
6814
|
-
* ```
|
|
6815
|
-
*/
|
|
6816
|
-
async fetchAlternativeRepresentations(t) {
|
|
6817
|
-
const e = `PREFIX qcy: <${b.qcy}>
|
|
6818
|
-
PREFIX r: <${this.baseURL}>
|
|
6819
|
-
SELECT ?altId ?contentIRI ?suffix ?rrp
|
|
6820
|
-
WHERE {
|
|
6821
|
-
r:${t} qcy:alternativeRepresentation ?contentIRI .
|
|
6822
|
-
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?altId)
|
|
6823
|
-
?contentIRI qcy:hasFileLocation ?loc .
|
|
6824
|
-
?loc qcy:suffix ?suffix .
|
|
6825
|
-
OPTIONAL { ?loc qcy:remoteRelativePath ?rrp }
|
|
6826
|
-
}`, o = await this._api.sparql(e, this._projectId, this._graphType), r = { ...this._documentInfoMap.get() }, s = [];
|
|
6827
|
-
return o.results.bindings.forEach((a) => {
|
|
6828
|
-
if (!a.altId || !a.contentIRI) return;
|
|
6829
|
-
const n = a.altId.value, p = {
|
|
6830
|
-
id: n,
|
|
6831
|
-
contentIRI: a.contentIRI.value,
|
|
6832
|
-
path: "",
|
|
6833
|
-
suffix: a.suffix?.value ?? "",
|
|
6834
|
-
size: 0,
|
|
6835
|
-
tags: [],
|
|
6836
|
-
categories: [],
|
|
6837
|
-
remoteRelativePath: a.rrp?.value
|
|
6838
|
-
};
|
|
6839
|
-
r[n] = p, s.push(p);
|
|
6840
|
-
}), this._documentInfoMap.set(r), s;
|
|
6841
|
-
}
|
|
6842
|
-
/**
|
|
6843
|
-
* Returns a single arbitrary file path from the project's triplestore.
|
|
6844
|
-
* Useful for pre-filling path-based query inputs with a realistic example.
|
|
6845
|
-
*/
|
|
6846
|
-
async randomFilePath() {
|
|
6847
|
-
const t = `PREFIX qcy: <${b.qcy}>
|
|
6848
|
-
SELECT ?path
|
|
6849
|
-
WHERE {
|
|
6850
|
-
?fl a qcy:FileLocation ;
|
|
6851
|
-
qcy:filePath ?path .
|
|
6852
|
-
}
|
|
6853
|
-
LIMIT 1`;
|
|
6854
|
-
return (await this._api.sparql(t, this._projectId, this._graphType)).results.bindings[0]?.path?.value ?? null;
|
|
6855
|
-
}
|
|
6856
|
-
// ── Private helpers ────────────────────────────────────────────────────────
|
|
6857
|
-
/** Executes the document-info SPARQL query for the given UUIDs, merges results
|
|
6858
|
-
* into `documentInfoMap`, and returns the newly fetched entries. */
|
|
6859
|
-
async _fetchDocumentInfoBatch(t) {
|
|
6860
|
-
const e = t.map((p) => `r:${p}`).join(" "), o = this._api.language, r = `PREFIX qcy: <${b.qcy}>
|
|
6861
|
-
PREFIX r: <${this.baseURL}>
|
|
6862
|
-
SELECT ?id ?contentIRI ?suffix ?size ?subject ?summary
|
|
6863
|
-
(SAMPLE(?fp) AS ?path)
|
|
6864
|
-
(GROUP_CONCAT(DISTINCT ?tag; SEPARATOR=";") AS ?tags)
|
|
6865
|
-
(GROUP_CONCAT(DISTINCT STR(?cat); SEPARATOR=";") AS ?categories)
|
|
6866
|
-
WHERE {
|
|
6867
|
-
VALUES ?contentIRI { ${e} }
|
|
6868
|
-
?contentIRI qcy:sizeBytes ?size ;
|
|
6869
|
-
qcy:hasFileLocation ?loc .
|
|
6870
|
-
?loc qcy:filePath ?fp ;
|
|
6871
|
-
qcy:suffix ?suffix .
|
|
6872
|
-
OPTIONAL { ?contentIRI qcy:hasContentCategory ?cat }
|
|
6873
|
-
OPTIONAL { ?contentIRI qcy:tag ?tag }
|
|
6874
|
-
OPTIONAL { ?loc qcy:remoteProviderId ?pid }
|
|
6875
|
-
|
|
6876
|
-
OPTIONAL { ?contentIRI qcy:subject ?lang_subj FILTER(LANG(?lang_subj) = "${o}") }
|
|
6877
|
-
OPTIONAL { ?contentIRI qcy:subject ?no_lang_subj }
|
|
6878
|
-
BIND(COALESCE(?lang_subj, ?no_lang_subj) AS ?subject)
|
|
6879
|
-
|
|
6880
|
-
OPTIONAL { ?contentIRI qcy:textSummary ?lang_summary FILTER(LANG(?lang_summary) = "${o}") }
|
|
6881
|
-
OPTIONAL { ?contentIRI qcy:textSummary ?no_lang_summary }
|
|
6882
|
-
BIND(COALESCE(?lang_summary, ?no_lang_summary) AS ?summary)
|
|
6883
|
-
|
|
6884
|
-
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?id)
|
|
6885
|
-
}
|
|
6886
|
-
GROUP BY ?id ?contentIRI ?suffix ?size ?subject ?summary`, s = await this._api.sparql(r, this._projectId), a = { ...this._documentInfoMap.get() }, n = {};
|
|
6887
|
-
return s.results.bindings.forEach((p) => {
|
|
6888
|
-
if (!p.id || !p.contentIRI) return;
|
|
6889
|
-
const c = p.id.value, h = {
|
|
6890
|
-
id: c,
|
|
6891
|
-
contentIRI: p.contentIRI.value,
|
|
6892
|
-
path: p.path?.value ?? "",
|
|
6893
|
-
suffix: p.suffix?.value ?? "",
|
|
6894
|
-
size: p.size ? parseInt(p.size.value, 10) : 0,
|
|
6895
|
-
tags: p.tags?.value?.split(";").filter(Boolean) ?? [],
|
|
6896
|
-
categories: p.categories?.value?.split(";").filter(Boolean) ?? [],
|
|
6897
|
-
subject: p.subject?.value,
|
|
6898
|
-
summary: p.summary?.value,
|
|
6899
|
-
providerId: p.pid?.value
|
|
6900
|
-
};
|
|
6901
|
-
a[c] = h, n[c] = h;
|
|
6902
|
-
}), this._documentInfoMap.set(a), n;
|
|
6903
|
-
}
|
|
6904
|
-
/** Executes a reduced document-info query (id/path/suffix/size only), merges
|
|
6905
|
-
* into `documentInfoMap`, and returns newly fetched entries. */
|
|
6906
|
-
async _fetchSimpleDocumentInfoBatch(t) {
|
|
6907
|
-
const e = t.map((n) => `r:${n}`).join(" "), o = `PREFIX qcy: <${b.qcy}>
|
|
6908
|
-
PREFIX r: <${this.baseURL}>
|
|
6909
|
-
SELECT ?id ?contentIRI ?suffix ?size (SAMPLE(?fp) AS ?path)
|
|
6910
|
-
WHERE {
|
|
6911
|
-
VALUES ?contentIRI { ${e} }
|
|
6912
|
-
?contentIRI qcy:sizeBytes ?size ;
|
|
6913
|
-
qcy:hasFileLocation ?loc .
|
|
6914
|
-
?loc qcy:filePath ?fp ;
|
|
6915
|
-
qcy:suffix ?suffix .
|
|
6916
|
-
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?id)
|
|
6917
|
-
}
|
|
6918
|
-
GROUP BY ?id ?contentIRI ?suffix ?size`, r = await this._api.sparql(o, this._projectId, this._graphType), s = { ...this._documentInfoMap.get() }, a = {};
|
|
6919
|
-
return r.results.bindings.forEach((n) => {
|
|
6920
|
-
if (!n.id) return;
|
|
6921
|
-
const p = n.id.value, c = s[p], h = {
|
|
6922
|
-
id: p,
|
|
6923
|
-
contentIRI: n.contentIRI?.value ?? c?.contentIRI ?? p,
|
|
6924
|
-
path: n.path?.value ?? c?.path ?? p,
|
|
6925
|
-
suffix: n.suffix?.value ?? c?.suffix ?? "",
|
|
6926
|
-
size: n.size ? parseInt(n.size.value, 10) : c?.size ?? 0,
|
|
6927
|
-
tags: c?.tags ?? [],
|
|
6928
|
-
categories: c?.categories ?? [],
|
|
6929
|
-
subject: c?.subject,
|
|
6930
|
-
summary: c?.summary,
|
|
6931
|
-
providerId: c?.providerId
|
|
6932
|
-
};
|
|
6933
|
-
s[p] = h, a[p] = h;
|
|
6934
|
-
}), this._documentInfoMap.set(s), a;
|
|
6935
|
-
}
|
|
6936
|
-
async _fetchDocumentsBySuffix() {
|
|
6937
|
-
return this._runDocumentsBySuffixQuery(this._buildDocumentsBySuffixQuery());
|
|
6938
|
-
}
|
|
6939
|
-
_buildDocumentsBySuffixQuery() {
|
|
6940
|
-
return `PREFIX qcy: <${b.qcy}>
|
|
6941
|
-
SELECT ?ext (SUM(?size) AS ?totalSize) (COUNT(*) AS ?docCount)
|
|
6942
|
-
WHERE {
|
|
6943
|
-
{
|
|
6944
|
-
SELECT DISTINCT ?fc ?ext ?size
|
|
6945
|
-
WHERE {
|
|
6946
|
-
?fc a qcy:FileContent ;
|
|
6947
|
-
qcy:sizeBytes ?size ;
|
|
6948
|
-
qcy:hasFileLocation/qcy:suffix ?ext .
|
|
6949
|
-
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?fc }
|
|
6950
|
-
}
|
|
6951
|
-
}
|
|
6952
|
-
}
|
|
6953
|
-
GROUP BY ?ext
|
|
6954
|
-
ORDER BY DESC(?docCount)`;
|
|
6955
|
-
}
|
|
6956
|
-
async _runDocumentsBySuffixQuery(t) {
|
|
6957
|
-
const e = await this._api.sparql(t, this._projectId, this._graphType), o = {};
|
|
6958
|
-
return e.results.bindings.forEach((r) => {
|
|
6959
|
-
r.ext && (o[r.ext.value] = {
|
|
6960
|
-
size: r.totalSize ? parseInt(r.totalSize.value, 10) : 0,
|
|
6961
|
-
count: r.docCount ? parseInt(r.docCount.value, 10) : 0
|
|
6962
|
-
});
|
|
6963
|
-
}), o;
|
|
6964
|
-
}
|
|
6965
|
-
async _fetchDocumentsByContentCategory() {
|
|
6966
|
-
return this._runDocumentsByContentCategoryQuery(this._buildDocumentsByContentCategoryQuery());
|
|
6967
|
-
}
|
|
6968
|
-
_buildDocumentsByContentCategoryQuery() {
|
|
6969
|
-
return `PREFIX qcy: <${b.qcy}>
|
|
6970
|
-
SELECT ?cat (SUM(?size) AS ?totalSize) (COUNT(*) AS ?docCount)
|
|
6971
|
-
WHERE {
|
|
6972
|
-
{
|
|
6973
|
-
SELECT DISTINCT ?fc ?cat ?size
|
|
6974
|
-
WHERE {
|
|
6975
|
-
?fc a qcy:FileContent ;
|
|
6976
|
-
qcy:hasContentCategory ?cat ;
|
|
6977
|
-
qcy:sizeBytes ?size .
|
|
6978
|
-
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?fc }
|
|
6979
|
-
}
|
|
6980
|
-
}
|
|
6981
|
-
}
|
|
6982
|
-
GROUP BY ?cat
|
|
6983
|
-
ORDER BY DESC(?docCount)`;
|
|
6984
|
-
}
|
|
6985
|
-
async _runDocumentsByContentCategoryQuery(t) {
|
|
6986
|
-
const e = await this._api.sparql(t, this._projectId, this._graphType), o = {};
|
|
6987
|
-
return e.results.bindings.forEach((r) => {
|
|
6988
|
-
r.cat && (o[r.cat.value] = {
|
|
6989
|
-
size: r.totalSize ? parseInt(r.totalSize.value, 10) : 0,
|
|
6990
|
-
count: r.docCount ? parseInt(r.docCount.value, 10) : 0
|
|
6991
|
-
});
|
|
6992
|
-
}), o;
|
|
6993
|
-
}
|
|
6994
|
-
async _fetchDuplicateCount() {
|
|
6995
|
-
return this._runDuplicateCountQuery(this._buildDuplicateCountQuery());
|
|
6996
|
-
}
|
|
6997
|
-
_buildDuplicateCountQuery() {
|
|
6998
|
-
return `PREFIX qcy: <${b.qcy}>
|
|
6999
|
-
SELECT (COUNT(*) AS ?count)
|
|
7000
|
-
WHERE {
|
|
7001
|
-
SELECT ?fc
|
|
7002
|
-
WHERE {
|
|
7003
|
-
?fc a qcy:FileContent ;
|
|
7004
|
-
qcy:hasFileLocation ?fl .
|
|
7005
|
-
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?fc }
|
|
7006
|
-
}
|
|
7007
|
-
GROUP BY ?fc
|
|
7008
|
-
HAVING (COUNT(?fl) > 1)
|
|
7009
|
-
}`;
|
|
7010
|
-
}
|
|
7011
|
-
async _runDuplicateCountQuery(t) {
|
|
7012
|
-
const o = (await this._api.sparql(t, this._projectId, this._graphType)).results.bindings[0];
|
|
7013
|
-
return o?.count ? parseInt(o.count.value, 10) : 0;
|
|
7014
|
-
}
|
|
7015
|
-
}
|
|
7016
|
-
class pr {
|
|
7017
|
-
constructor(t, e, { language: o, queryCache: r, rdfBase: s = dt, graphType: a }) {
|
|
7018
|
-
this._api = t, this._projectId = e, this.schema = new ir(t, e, o, r, a), this.entities = new ue(t, e, s, r, a), this.documents = new pt(t, e, o, s, r, a), this.availableContentCategories = this.schema.availableContentCategories, this.availableEntityCategories = this.schema.availableEntityCategories, this.availableEntityRelationships = this.schema.availableEntityRelationships, this.schemaReady = this.schema.ready, this.entityInfoMap = this.entities.entityInfoMap, this.entityGraph = this.entities.entityGraph, this.documentInfoMap = this.documents.documentInfoMap, this.projectDocumentsData = this.documents.projectDocumentsData, this.searchResults = this._searchResults.asReadonly(), this.documents.fetchOverview().catch((n) => console.error("[CueProjectView] fetchOverview failed:", n));
|
|
7019
|
-
}
|
|
7020
|
-
_api;
|
|
7021
|
-
_projectId;
|
|
7022
|
-
/** Direct access to the schema data class (available categories / relationships). */
|
|
7023
|
-
schema;
|
|
7024
|
-
/** Direct access to the entity data class. */
|
|
7025
|
-
entities;
|
|
7026
|
-
/** Direct access to the document data class. */
|
|
7027
|
-
documents;
|
|
7028
|
-
// ── Proxied signals ────────────────────────────────────────────────────────
|
|
7029
|
-
/** Available content category definitions for this project. Auto-fetched on init. */
|
|
7030
|
-
availableContentCategories;
|
|
7031
|
-
/** Available entity category definitions for this project. Auto-fetched on init. */
|
|
7032
|
-
availableEntityCategories;
|
|
7033
|
-
/** Available entity relationship types. Auto-fetched on init. */
|
|
7034
|
-
availableEntityRelationships;
|
|
7035
|
-
/**
|
|
7036
|
-
* Resolves when the initial schema load has completed. Await before reading
|
|
7037
|
-
* schema signal values imperatively.
|
|
7038
|
-
*/
|
|
7039
|
-
schemaReady;
|
|
7040
|
-
/** Merged per-entity detail map. Populated lazily via `requestEntityData()` etc. */
|
|
7041
|
-
entityInfoMap;
|
|
7042
|
-
/** Project-level entity co-occurrence graph. Fetched once on init. */
|
|
7043
|
-
entityGraph;
|
|
7044
|
-
/** Per-document info map. Populated lazily via `requestDocumentData()`. */
|
|
7045
|
-
documentInfoMap;
|
|
7046
|
-
/** Project document overview (counts by suffix and category). Fetched on init. */
|
|
7047
|
-
projectDocumentsData;
|
|
7048
|
-
// ── Search state ───────────────────────────────────────────────────────────
|
|
7049
|
-
_searchResults = new k(void 0);
|
|
7050
|
-
/** The result of the most recent `search()` call. `undefined` before first search. */
|
|
7051
|
-
searchResults;
|
|
7052
|
-
_destroyed = !1;
|
|
7053
|
-
// ── Entity methods ─────────────────────────────────────────────────────────
|
|
7054
|
-
/**
|
|
7055
|
-
* Lazily batch-fetch core data (label + categories) for the given entity UUIDs.
|
|
7056
|
-
* Already-fetched UUIDs are skipped. Populates `entityInfoMap`.
|
|
7057
|
-
*/
|
|
7058
|
-
requestEntityData(t, e = !1) {
|
|
7059
|
-
this._destroyed || this.entities.requestEntityData(t, e);
|
|
7060
|
-
}
|
|
7061
|
-
/**
|
|
7062
|
-
* Lazily fetch OSM location data for the given entity UUIDs.
|
|
7063
|
-
* Already-fetched UUIDs are skipped. Populates `entityInfoMap` geometry fields.
|
|
7064
|
-
*/
|
|
7065
|
-
async requestEntityLocations(t) {
|
|
7066
|
-
if (!this._destroyed)
|
|
7067
|
-
return this.entities.requestEntityLocations(t);
|
|
7068
|
-
}
|
|
7069
|
-
/**
|
|
7070
|
-
* Fetch incoming and outgoing relationships for a single entity IRI.
|
|
7071
|
-
* Result is stored in `entityInfoMap[uuid].relationshipData`.
|
|
7072
|
-
*/
|
|
7073
|
-
async fetchEntityRelationships(t) {
|
|
7074
|
-
if (this._destroyed) throw new Error("CueProjectView is destroyed");
|
|
7075
|
-
return this.entities.fetchEntityRelationships(t);
|
|
7076
|
-
}
|
|
7077
|
-
/**
|
|
7078
|
-
* Fetch UUIDs of documents that reference the given entity IRI.
|
|
7079
|
-
* Result is stored in `entityInfoMap[uuid].documentRefs`.
|
|
7080
|
-
*/
|
|
7081
|
-
async fetchEntityDocuments(t) {
|
|
7082
|
-
if (this._destroyed) throw new Error("CueProjectView is destroyed");
|
|
7083
|
-
return this.entities.fetchEntityDocuments(t);
|
|
7084
|
-
}
|
|
7085
|
-
/** Constructs the full RDF IRI for an entity UUID. */
|
|
7086
|
-
entityIri(t) {
|
|
7087
|
-
return this.entities.entityIri(t);
|
|
7088
|
-
}
|
|
7089
|
-
// ── Document methods ───────────────────────────────────────────────────────
|
|
7090
|
-
/**
|
|
7091
|
-
* Lazily batch-fetch document info for the given UUIDs.
|
|
7092
|
-
* Already-fetched UUIDs are skipped. Populates `documentInfoMap`.
|
|
7093
|
-
*/
|
|
7094
|
-
requestDocumentData(t) {
|
|
7095
|
-
this._destroyed || this.documents.requestDocumentData(t);
|
|
7096
|
-
}
|
|
7097
|
-
// ── Search ─────────────────────────────────────────────────────────────────
|
|
7098
|
-
/**
|
|
7099
|
-
* Run a natural-language search against the project.
|
|
7100
|
-
* The result is stored in `searchResults` and replaces any previous result.
|
|
7101
|
-
*/
|
|
7102
|
-
async search(t, e) {
|
|
7103
|
-
if (this._destroyed) return;
|
|
7104
|
-
const o = await this._api.search({
|
|
7105
|
-
term: t,
|
|
7106
|
-
projectId: this._projectId,
|
|
7107
|
-
categories: e?.categories
|
|
7108
|
-
});
|
|
7109
|
-
this._destroyed || this._searchResults.set(o);
|
|
7110
|
-
}
|
|
7111
|
-
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
7112
|
-
/**
|
|
7113
|
-
* Switch the active language for schema labels and document text fields.
|
|
7114
|
-
* Schema responses are cached per language (instant if previously loaded).
|
|
7115
|
-
* The document info map is cleared and lazily re-populated on next access.
|
|
7116
|
-
*/
|
|
7117
|
-
setLanguage(t) {
|
|
7118
|
-
this._destroyed || (this.schema.setLanguage(t), this.documents.setLanguage(t));
|
|
7119
|
-
}
|
|
7120
|
-
/**
|
|
7121
|
-
* Reset all entity and document state and re-fetch the project overview.
|
|
7122
|
-
* Prefer creating a fresh `CueProjectView` when switching projects.
|
|
7123
|
-
* Use `reset()` only when the same project's data needs to be invalidated.
|
|
7124
|
-
*/
|
|
7125
|
-
reset() {
|
|
7126
|
-
this._destroyed || (this.entities.reset(), this.documents.reset(), this._searchResults.set(void 0), this.documents.fetchOverview().catch((t) => console.error("[CueProjectView] fetchOverview failed after reset:", t)));
|
|
7127
|
-
}
|
|
7128
|
-
/**
|
|
7129
|
-
* Tear down this view instance. Clears all reactive state and blocks further
|
|
7130
|
-
* updates. Call from the Angular adapter's `ngOnDestroy` or equivalent.
|
|
7131
|
-
*/
|
|
7132
|
-
destroy() {
|
|
7133
|
-
this._destroyed = !0, this._searchResults.set(void 0);
|
|
7134
|
-
}
|
|
7135
|
-
}
|
|
7136
|
-
function Qt(i, t) {
|
|
7137
|
-
return new Promise((e) => {
|
|
7138
|
-
const o = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
7139
|
-
for (const m of i)
|
|
7140
|
-
o.has(m.contentUUID) || o.set(m.contentUUID, []), o.get(m.contentUUID)?.push(m), r.set(m.locationUUID, m);
|
|
7141
|
-
const s = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
7142
|
-
for (const m of t)
|
|
7143
|
-
s.has(m.contentUUID) || s.set(m.contentUUID, []), s.get(m.contentUUID)?.push(m), m.locationUUID && a.set(m.locationUUID, m);
|
|
7144
|
-
const n = [], p = [];
|
|
7145
|
-
for (const m of i)
|
|
7146
|
-
s.has(m.contentUUID) ? (s.get(m.contentUUID) || []).some((v) => v.locationUUID === m.locationUUID) || p.push(m) : n.push(m);
|
|
7147
|
-
const c = [], h = [];
|
|
7148
|
-
for (const m of t) {
|
|
7149
|
-
const x = o.get(m.contentUUID);
|
|
7150
|
-
x ? x.some((v) => v.locationUUID === m.locationUUID) || h.push(m) : c.push(m);
|
|
7151
|
-
}
|
|
7152
|
-
const d = i.length - n.length - p.length, g = i.length, w = g > 0 ? d / g : 1;
|
|
7153
|
-
let u = 0, f = 0;
|
|
7154
|
-
for (const m of i)
|
|
7155
|
-
f += m.size || 0, (s.get(m.contentUUID) || []).some((v) => v.locationUUID === m.locationUUID) && (u += m.size || 0);
|
|
7156
|
-
const E = f > 0 ? u / f : 1;
|
|
7157
|
-
e({
|
|
7158
|
-
localNotOnRemote: n,
|
|
7159
|
-
localNotOnRemotePathOnly: p,
|
|
7160
|
-
remoteNotOnLocal: c,
|
|
7161
|
-
remoteNotOnLocalPathOnly: h,
|
|
7162
|
-
syncCount: d,
|
|
7163
|
-
totalCount: g,
|
|
7164
|
-
syncSize: u,
|
|
7165
|
-
totalSize: f,
|
|
7166
|
-
synctPctSize: E,
|
|
7167
|
-
synctPctCount: w
|
|
7168
|
-
});
|
|
7169
|
-
});
|
|
7170
|
-
}
|
|
7171
6760
|
var l = /* @__PURE__ */ ((i) => (i.AUTOMATION = "automation", i.ARCHIVE = "archive", i.AUDIO = "audio", i.BACKUP = "backup", i.BINARY = "binary", i.BIM = "bim", i.CAD = "cad", i.DATA = "data", i.EMAIL = "email", i.FONT = "font", i.GEOSPATIAL = "geospatial", i.IMAGE = "image", i.INSTALLER = "installer", i.MARKUP = "markup", i.MULTIMEDIA = "multimedia", i.PLANNING = "planning", i.PRESENTATION = "presentation", i.SCRIPT = "script", i.SPREADSHEET = "spreadsheet", i.TEXT = "text", i.THREE_D = "3d", i.UNKNOWN = "unknown", i.VIDEO = "video", i))(l || {});
|
|
7172
|
-
const
|
|
6761
|
+
const lt = {
|
|
7173
6762
|
".aac": {
|
|
7174
6763
|
type: l.AUDIO,
|
|
7175
6764
|
open: !0,
|
|
@@ -8028,24 +7617,562 @@ const lr = {
|
|
|
8028
7617
|
suffix: ".fragments",
|
|
8029
7618
|
mime: "application/octet-stream"
|
|
8030
7619
|
}
|
|
8031
|
-
};
|
|
8032
|
-
l.AUDIO + "", l.VIDEO + "", l.IMAGE + "", l.TEXT + "", l.MARKUP + "", l.SCRIPT + "", l.DATA + "", l.ARCHIVE + "", l.INSTALLER + "", l.BINARY + "", l.BACKUP + "", l.AUTOMATION + "", l.PRESENTATION + "", l.SPREADSHEET + "", l.FONT + "", l.GEOSPATIAL + "", l.THREE_D + "", l.CAD + "", l.BIM + "", l.PLANNING + "", l.EMAIL + "", l.MULTIMEDIA + "", l.UNKNOWN + "";
|
|
8033
|
-
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
7620
|
+
};
|
|
7621
|
+
l.AUDIO + "", l.VIDEO + "", l.IMAGE + "", l.TEXT + "", l.MARKUP + "", l.SCRIPT + "", l.DATA + "", l.ARCHIVE + "", l.INSTALLER + "", l.BINARY + "", l.BACKUP + "", l.AUTOMATION + "", l.PRESENTATION + "", l.SPREADSHEET + "", l.FONT + "", l.GEOSPATIAL + "", l.THREE_D + "", l.CAD + "", l.BIM + "", l.PLANNING + "", l.EMAIL + "", l.MULTIMEDIA + "", l.UNKNOWN + "";
|
|
7622
|
+
class ct {
|
|
7623
|
+
constructor(t, e, o, r = ut, s, a) {
|
|
7624
|
+
this._api = t, this._projectId = e, this._queryCache = s, this._graphType = a, this.baseURL = `${r}${e}/`, this._currentLang = o ?? this._api.language, this.documentInfoMap = this._documentInfoMap.asReadonly(), this.projectDocumentsData = this._projectDocumentsData.asReadonly();
|
|
7625
|
+
}
|
|
7626
|
+
_api;
|
|
7627
|
+
_projectId;
|
|
7628
|
+
_queryCache;
|
|
7629
|
+
_graphType;
|
|
7630
|
+
/** Full RDF base URL for this project, e.g. `https://cue.qaecy.com/r/{pid}/` */
|
|
7631
|
+
baseURL;
|
|
7632
|
+
/** Tracks the language for which `_documentInfoMap` is currently populated. */
|
|
7633
|
+
_currentLang;
|
|
7634
|
+
_documentInfoMap = new k({});
|
|
7635
|
+
_projectDocumentsData = new k({
|
|
7636
|
+
duplicateCount: 0,
|
|
7637
|
+
documentsBySuffix: {},
|
|
7638
|
+
documentsByContentCategory: {}
|
|
7639
|
+
});
|
|
7640
|
+
/** Lazily populated per-document detail map. */
|
|
7641
|
+
documentInfoMap;
|
|
7642
|
+
/** Project-level document overview (grouped counts + sizes). */
|
|
7643
|
+
projectDocumentsData;
|
|
7644
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
7645
|
+
/**
|
|
7646
|
+
* Resets all document state. Call when the active project changes.
|
|
7647
|
+
* Follow with `fetchOverview()` once the triplestore is ready.
|
|
7648
|
+
*/
|
|
7649
|
+
reset() {
|
|
7650
|
+
this._documentInfoMap.set({}), this._projectDocumentsData.set({
|
|
7651
|
+
duplicateCount: 0,
|
|
7652
|
+
documentsBySuffix: {},
|
|
7653
|
+
documentsByContentCategory: {}
|
|
7654
|
+
});
|
|
7655
|
+
}
|
|
7656
|
+
/**
|
|
7657
|
+
* Updates the active language and clears the document info map so that
|
|
7658
|
+
* language-sensitive fields (subject, summary) are re-fetched on the next
|
|
7659
|
+
* `requestDocumentData()` call.
|
|
7660
|
+
*/
|
|
7661
|
+
setLanguage(t) {
|
|
7662
|
+
this._currentLang !== t && (this._currentLang = t, this._api.setLanguage(t), this._documentInfoMap.set({}));
|
|
7663
|
+
}
|
|
7664
|
+
// ── Public API ─────────────────────────────────────────────────────────────
|
|
7665
|
+
/**
|
|
7666
|
+
* Fetches the three-part project overview (by suffix, by content category,
|
|
7667
|
+
* duplicate count) in parallel and writes them as a single atomic update to
|
|
7668
|
+
* `projectDocumentsData`. Safe to call again to refresh.
|
|
7669
|
+
*/
|
|
7670
|
+
async fetchOverview() {
|
|
7671
|
+
this._projectDocumentsData.set({
|
|
7672
|
+
duplicateCount: 0,
|
|
7673
|
+
documentsBySuffix: {},
|
|
7674
|
+
documentsByContentCategory: {}
|
|
7675
|
+
});
|
|
7676
|
+
const t = this._buildDocumentsBySuffixQuery(), e = this._buildDocumentsByContentCategoryQuery(), o = this._buildDuplicateCountQuery();
|
|
7677
|
+
await gt(
|
|
7678
|
+
t + e + o,
|
|
7679
|
+
async () => {
|
|
7680
|
+
const [r, s, a] = await Promise.all([
|
|
7681
|
+
this._runDocumentsBySuffixQuery(t),
|
|
7682
|
+
this._runDocumentsByContentCategoryQuery(e),
|
|
7683
|
+
this._runDuplicateCountQuery(o)
|
|
7684
|
+
]);
|
|
7685
|
+
return { duplicateCount: a, documentsBySuffix: r, documentsByContentCategory: s };
|
|
7686
|
+
},
|
|
7687
|
+
(r) => this._projectDocumentsData.set(r),
|
|
7688
|
+
this._queryCache
|
|
7689
|
+
);
|
|
7690
|
+
}
|
|
7691
|
+
/**
|
|
7692
|
+
* Lazily batch-fetches core metadata for the given document UUIDs.
|
|
7693
|
+
* Already-cached UUIDs are skipped. Data is merged into `documentInfoMap`
|
|
7694
|
+
* once the SPARQL response arrives.
|
|
7695
|
+
*/
|
|
7696
|
+
requestDocumentData(t) {
|
|
7697
|
+
const e = t.filter((o) => this._documentInfoMap.get()[o] === void 0);
|
|
7698
|
+
e.length !== 0 && this._fetchDocumentInfoBatch(e).catch(
|
|
7699
|
+
(o) => console.error("[CueProjectDocuments] requestDocumentData failed:", o)
|
|
7700
|
+
);
|
|
7701
|
+
}
|
|
7702
|
+
/**
|
|
7703
|
+
* Promise-based alternative to {@link requestDocumentData} for non-reactive contexts.
|
|
7704
|
+
*
|
|
7705
|
+
* Resolves with the `DocumentInfo` entries for every requested UUID once the
|
|
7706
|
+
* SPARQL response arrives. UUIDs already present in the cache are returned
|
|
7707
|
+
* immediately without a network request. The result is also written into
|
|
7708
|
+
* `documentInfoMap` so reactive consumers stay in sync.
|
|
7709
|
+
*
|
|
7710
|
+
* UUIDs not found in the triplestore are omitted from the returned map.
|
|
7711
|
+
*
|
|
7712
|
+
* @example
|
|
7713
|
+
* ```ts
|
|
7714
|
+
* const docs = await cueProjectDocs.fetchDocumentData(['uuid1', 'uuid2']);
|
|
7715
|
+
* console.log(docs['uuid1'].subject);
|
|
7716
|
+
* ```
|
|
7717
|
+
*/
|
|
7718
|
+
async fetchDocumentData(t) {
|
|
7719
|
+
const e = this._documentInfoMap.get(), o = t.filter((s) => e[s] === void 0);
|
|
7720
|
+
o.length > 0 && await this._fetchDocumentInfoBatch(o);
|
|
7721
|
+
const r = this._documentInfoMap.get();
|
|
7722
|
+
return Object.fromEntries(
|
|
7723
|
+
t.filter((s) => r[s] !== void 0).map((s) => [s, r[s]])
|
|
7724
|
+
);
|
|
7725
|
+
}
|
|
7726
|
+
/**
|
|
7727
|
+
* Fetches a lightweight document metadata shape (id/path/suffix/size) for
|
|
7728
|
+
* the given UUIDs and merges the results into `documentInfoMap`.
|
|
7729
|
+
*
|
|
7730
|
+
* This is useful for list/table contexts that do not need language-tagged
|
|
7731
|
+
* fields (`subject`, `summary`) or category/tag enrichment.
|
|
7732
|
+
*
|
|
7733
|
+
* UUIDs already present in `documentInfoMap` are skipped.
|
|
7734
|
+
*/
|
|
7735
|
+
async fetchDocumentDataSimple(t) {
|
|
7736
|
+
const e = this._documentInfoMap.get(), o = t.filter((s) => e[s] === void 0);
|
|
7737
|
+
o.length > 0 && await this._fetchSimpleDocumentInfoBatch(o);
|
|
7738
|
+
const r = this._documentInfoMap.get();
|
|
7739
|
+
return Object.fromEntries(
|
|
7740
|
+
t.filter((s) => r[s] !== void 0).map((s) => [s, r[s]])
|
|
7741
|
+
);
|
|
7742
|
+
}
|
|
7743
|
+
/**
|
|
7744
|
+
* Returns the alternative representations of the given document UUID.
|
|
7745
|
+
*
|
|
7746
|
+
* Alternative representations are derived artefacts stored under
|
|
7747
|
+
* `qcy:alternativeRepresentation` in the triplestore — for example a
|
|
7748
|
+
* `.fragments` BIM tile derived from an `.ifc` source file.
|
|
7749
|
+
*
|
|
7750
|
+
* The returned `DocumentInfo` entries are also merged into
|
|
7751
|
+
* `documentInfoMap` so reactive consumers stay in sync.
|
|
7752
|
+
*
|
|
7753
|
+
* @example
|
|
7754
|
+
* ```ts
|
|
7755
|
+
* const alts = await docs.fetchAlternativeRepresentations('abc-123');
|
|
7756
|
+
* // alts[0].suffix => '.fragments'
|
|
7757
|
+
* ```
|
|
7758
|
+
*/
|
|
7759
|
+
async fetchAlternativeRepresentations(t) {
|
|
7760
|
+
const e = `PREFIX qcy: <${y.qcy}>
|
|
7761
|
+
PREFIX r: <${this.baseURL}>
|
|
7762
|
+
SELECT ?altId ?contentIRI ?suffix ?rrp
|
|
7763
|
+
WHERE {
|
|
7764
|
+
r:${t} qcy:alternativeRepresentation ?contentIRI .
|
|
7765
|
+
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?altId)
|
|
7766
|
+
?contentIRI qcy:hasFileLocation ?loc .
|
|
7767
|
+
?loc qcy:suffix ?suffix .
|
|
7768
|
+
OPTIONAL { ?loc qcy:remoteRelativePath ?rrp }
|
|
7769
|
+
}`, o = await this._api.sparql(e, this._projectId, this._graphType), r = { ...this._documentInfoMap.get() }, s = [];
|
|
7770
|
+
return o.results.bindings.forEach((a) => {
|
|
7771
|
+
if (!a.altId || !a.contentIRI) return;
|
|
7772
|
+
const n = a.altId.value, p = {
|
|
7773
|
+
id: n,
|
|
7774
|
+
contentIRI: a.contentIRI.value,
|
|
7775
|
+
path: "",
|
|
7776
|
+
suffix: a.suffix?.value ?? "",
|
|
7777
|
+
size: 0,
|
|
7778
|
+
tags: [],
|
|
7779
|
+
categories: [],
|
|
7780
|
+
remoteRelativePath: a.rrp?.value
|
|
7781
|
+
};
|
|
7782
|
+
r[n] = p, s.push(p);
|
|
7783
|
+
}), this._documentInfoMap.set(r), s;
|
|
7784
|
+
}
|
|
7785
|
+
/**
|
|
7786
|
+
* Returns a single arbitrary file path from the project's triplestore.
|
|
7787
|
+
* Useful for pre-filling path-based query inputs with a realistic example.
|
|
7788
|
+
*/
|
|
7789
|
+
async randomFilePath() {
|
|
7790
|
+
const t = `PREFIX qcy: <${y.qcy}>
|
|
7791
|
+
SELECT ?path
|
|
7792
|
+
WHERE {
|
|
7793
|
+
?fl a qcy:FileLocation ;
|
|
7794
|
+
qcy:filePath ?path .
|
|
7795
|
+
}
|
|
7796
|
+
LIMIT 1`;
|
|
7797
|
+
return (await this._api.sparql(t, this._projectId, this._graphType)).results.bindings[0]?.path?.value ?? null;
|
|
7798
|
+
}
|
|
7799
|
+
async documentsBySuffix(t, e = !1) {
|
|
7800
|
+
if (t.length === 0) return [];
|
|
7801
|
+
const r = t.map(
|
|
7802
|
+
(n) => (n.startsWith(".") ? n : `.${n}`).toLowerCase()
|
|
7803
|
+
).map((n) => `"${n}"`).join(" "), s = e ? `PREFIX qcy: <${y.qcy}>
|
|
7804
|
+
SELECT ?iri ?id (SAMPLE(?fp) AS ?path) ?suffix (MAX(?sz) AS ?size)
|
|
7805
|
+
WHERE {
|
|
7806
|
+
VALUES ?suffix { ${r} }
|
|
7807
|
+
?iri a qcy:FileContent ;
|
|
7808
|
+
qcy:sizeBytes ?sz ;
|
|
7809
|
+
qcy:hasFileLocation ?loc .
|
|
7810
|
+
?loc qcy:suffix ?suffix ;
|
|
7811
|
+
qcy:filePath ?fp .
|
|
7812
|
+
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?iri }
|
|
7813
|
+
BIND(REPLACE(STR(?iri), "^.*/([^/]*)$", "$1") AS ?id)
|
|
7814
|
+
}
|
|
7815
|
+
GROUP BY ?iri ?id ?suffix` : `PREFIX qcy: <${y.qcy}>
|
|
7816
|
+
SELECT DISTINCT ?iri ?id
|
|
7817
|
+
WHERE {
|
|
7818
|
+
VALUES ?suffix { ${r} }
|
|
7819
|
+
?iri a qcy:FileContent ;
|
|
7820
|
+
qcy:hasFileLocation/qcy:suffix ?suffix .
|
|
7821
|
+
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?iri }
|
|
7822
|
+
BIND(REPLACE(STR(?iri), "^.*/([^/]*)$", "$1") AS ?id)
|
|
7823
|
+
}`;
|
|
7824
|
+
return (await this._api.sparql(s, this._projectId, this._graphType)).results.bindings.filter((n) => n.iri && n.id).map(
|
|
7825
|
+
(n) => e ? {
|
|
7826
|
+
iri: n.iri.value,
|
|
7827
|
+
uuid: n.id.value,
|
|
7828
|
+
path: n.path?.value ?? "",
|
|
7829
|
+
suffix: n.suffix?.value ?? "",
|
|
7830
|
+
size: n.size ? parseInt(n.size.value, 10) : 0
|
|
7831
|
+
} : {
|
|
7832
|
+
iri: n.iri.value,
|
|
7833
|
+
uuid: n.id.value
|
|
7834
|
+
}
|
|
7835
|
+
);
|
|
7836
|
+
}
|
|
7837
|
+
documentsByFileType(t, e = !1) {
|
|
7838
|
+
const o = new Set(t), r = Object.values(lt).filter((s) => o.has(s.type)).map((s) => s.suffix);
|
|
7839
|
+
return this.documentsBySuffix(r, e);
|
|
7840
|
+
}
|
|
7841
|
+
documentsByMime(t, e = !1) {
|
|
7842
|
+
const o = new Set(t), r = Object.values(lt).filter((s) => o.has(s.mime)).map((s) => s.suffix);
|
|
7843
|
+
return this.documentsBySuffix(r, e);
|
|
7844
|
+
}
|
|
7845
|
+
// ── Private helpers ────────────────────────────────────────────────────────
|
|
7846
|
+
/** Executes the document-info SPARQL query for the given UUIDs, merges results
|
|
7847
|
+
* into `documentInfoMap`, and returns the newly fetched entries. */
|
|
7848
|
+
async _fetchDocumentInfoBatch(t) {
|
|
7849
|
+
const e = t.map((p) => `r:${p}`).join(" "), o = this._api.language, r = `PREFIX qcy: <${y.qcy}>
|
|
7850
|
+
PREFIX r: <${this.baseURL}>
|
|
7851
|
+
SELECT ?id ?contentIRI ?suffix ?size ?subject ?summary
|
|
7852
|
+
(SAMPLE(?fp) AS ?path)
|
|
7853
|
+
(GROUP_CONCAT(DISTINCT ?tag; SEPARATOR=";") AS ?tags)
|
|
7854
|
+
(GROUP_CONCAT(DISTINCT STR(?cat); SEPARATOR=";") AS ?categories)
|
|
7855
|
+
WHERE {
|
|
7856
|
+
VALUES ?contentIRI { ${e} }
|
|
7857
|
+
?contentIRI qcy:sizeBytes ?size ;
|
|
7858
|
+
qcy:hasFileLocation ?loc .
|
|
7859
|
+
?loc qcy:filePath ?fp ;
|
|
7860
|
+
qcy:suffix ?suffix .
|
|
7861
|
+
OPTIONAL { ?contentIRI qcy:hasContentCategory ?cat }
|
|
7862
|
+
OPTIONAL { ?contentIRI qcy:tag ?tag }
|
|
7863
|
+
OPTIONAL { ?loc qcy:remoteProviderId ?pid }
|
|
7864
|
+
|
|
7865
|
+
OPTIONAL { ?contentIRI qcy:subject ?lang_subj FILTER(LANG(?lang_subj) = "${o}") }
|
|
7866
|
+
OPTIONAL { ?contentIRI qcy:subject ?no_lang_subj }
|
|
7867
|
+
BIND(COALESCE(?lang_subj, ?no_lang_subj) AS ?subject)
|
|
7868
|
+
|
|
7869
|
+
OPTIONAL { ?contentIRI qcy:textSummary ?lang_summary FILTER(LANG(?lang_summary) = "${o}") }
|
|
7870
|
+
OPTIONAL { ?contentIRI qcy:textSummary ?no_lang_summary }
|
|
7871
|
+
BIND(COALESCE(?lang_summary, ?no_lang_summary) AS ?summary)
|
|
7872
|
+
|
|
7873
|
+
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?id)
|
|
7874
|
+
}
|
|
7875
|
+
GROUP BY ?id ?contentIRI ?suffix ?size ?subject ?summary`, s = await this._api.sparql(r, this._projectId), a = { ...this._documentInfoMap.get() }, n = {};
|
|
7876
|
+
return s.results.bindings.forEach((p) => {
|
|
7877
|
+
if (!p.id || !p.contentIRI) return;
|
|
7878
|
+
const c = p.id.value, h = {
|
|
7879
|
+
id: c,
|
|
7880
|
+
contentIRI: p.contentIRI.value,
|
|
7881
|
+
path: p.path?.value ?? "",
|
|
7882
|
+
suffix: p.suffix?.value ?? "",
|
|
7883
|
+
size: p.size ? parseInt(p.size.value, 10) : 0,
|
|
7884
|
+
tags: p.tags?.value?.split(";").filter(Boolean) ?? [],
|
|
7885
|
+
categories: p.categories?.value?.split(";").filter(Boolean) ?? [],
|
|
7886
|
+
subject: p.subject?.value,
|
|
7887
|
+
summary: p.summary?.value,
|
|
7888
|
+
providerId: p.pid?.value
|
|
7889
|
+
};
|
|
7890
|
+
a[c] = h, n[c] = h;
|
|
7891
|
+
}), this._documentInfoMap.set(a), n;
|
|
7892
|
+
}
|
|
7893
|
+
/** Executes a reduced document-info query (id/path/suffix/size only), merges
|
|
7894
|
+
* into `documentInfoMap`, and returns newly fetched entries. */
|
|
7895
|
+
async _fetchSimpleDocumentInfoBatch(t) {
|
|
7896
|
+
const e = t.map((n) => `r:${n}`).join(" "), o = `PREFIX qcy: <${y.qcy}>
|
|
7897
|
+
PREFIX r: <${this.baseURL}>
|
|
7898
|
+
SELECT ?id ?contentIRI ?suffix ?size (SAMPLE(?fp) AS ?path)
|
|
7899
|
+
WHERE {
|
|
7900
|
+
VALUES ?contentIRI { ${e} }
|
|
7901
|
+
?contentIRI qcy:sizeBytes ?size ;
|
|
7902
|
+
qcy:hasFileLocation ?loc .
|
|
7903
|
+
?loc qcy:filePath ?fp ;
|
|
7904
|
+
qcy:suffix ?suffix .
|
|
7905
|
+
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?id)
|
|
7906
|
+
}
|
|
7907
|
+
GROUP BY ?id ?contentIRI ?suffix ?size`, r = await this._api.sparql(o, this._projectId, this._graphType), s = { ...this._documentInfoMap.get() }, a = {};
|
|
7908
|
+
return r.results.bindings.forEach((n) => {
|
|
7909
|
+
if (!n.id) return;
|
|
7910
|
+
const p = n.id.value, c = s[p], h = {
|
|
7911
|
+
id: p,
|
|
7912
|
+
contentIRI: n.contentIRI?.value ?? c?.contentIRI ?? p,
|
|
7913
|
+
path: n.path?.value ?? c?.path ?? p,
|
|
7914
|
+
suffix: n.suffix?.value ?? c?.suffix ?? "",
|
|
7915
|
+
size: n.size ? parseInt(n.size.value, 10) : c?.size ?? 0,
|
|
7916
|
+
tags: c?.tags ?? [],
|
|
7917
|
+
categories: c?.categories ?? [],
|
|
7918
|
+
subject: c?.subject,
|
|
7919
|
+
summary: c?.summary,
|
|
7920
|
+
providerId: c?.providerId
|
|
7921
|
+
};
|
|
7922
|
+
s[p] = h, a[p] = h;
|
|
7923
|
+
}), this._documentInfoMap.set(s), a;
|
|
7924
|
+
}
|
|
7925
|
+
async _fetchDocumentsBySuffix() {
|
|
7926
|
+
return this._runDocumentsBySuffixQuery(this._buildDocumentsBySuffixQuery());
|
|
7927
|
+
}
|
|
7928
|
+
_buildDocumentsBySuffixQuery() {
|
|
7929
|
+
return `PREFIX qcy: <${y.qcy}>
|
|
7930
|
+
SELECT ?ext (SUM(?size) AS ?totalSize) (COUNT(*) AS ?docCount)
|
|
7931
|
+
WHERE {
|
|
7932
|
+
{
|
|
7933
|
+
SELECT DISTINCT ?fc ?ext ?size
|
|
7934
|
+
WHERE {
|
|
7935
|
+
?fc a qcy:FileContent ;
|
|
7936
|
+
qcy:sizeBytes ?size ;
|
|
7937
|
+
qcy:hasFileLocation/qcy:suffix ?ext .
|
|
7938
|
+
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?fc }
|
|
7939
|
+
}
|
|
7940
|
+
}
|
|
7941
|
+
}
|
|
7942
|
+
GROUP BY ?ext
|
|
7943
|
+
ORDER BY DESC(?docCount)`;
|
|
7944
|
+
}
|
|
7945
|
+
async _runDocumentsBySuffixQuery(t) {
|
|
7946
|
+
const e = await this._api.sparql(t, this._projectId, this._graphType), o = {};
|
|
7947
|
+
return e.results.bindings.forEach((r) => {
|
|
7948
|
+
r.ext && (o[r.ext.value] = {
|
|
7949
|
+
size: r.totalSize ? parseInt(r.totalSize.value, 10) : 0,
|
|
7950
|
+
count: r.docCount ? parseInt(r.docCount.value, 10) : 0
|
|
7951
|
+
});
|
|
7952
|
+
}), o;
|
|
7953
|
+
}
|
|
7954
|
+
async _fetchDocumentsByContentCategory() {
|
|
7955
|
+
return this._runDocumentsByContentCategoryQuery(this._buildDocumentsByContentCategoryQuery());
|
|
7956
|
+
}
|
|
7957
|
+
_buildDocumentsByContentCategoryQuery() {
|
|
7958
|
+
return `PREFIX qcy: <${y.qcy}>
|
|
7959
|
+
SELECT ?cat (SUM(?size) AS ?totalSize) (COUNT(*) AS ?docCount)
|
|
7960
|
+
WHERE {
|
|
7961
|
+
{
|
|
7962
|
+
SELECT DISTINCT ?fc ?cat ?size
|
|
7963
|
+
WHERE {
|
|
7964
|
+
?fc a qcy:FileContent ;
|
|
7965
|
+
qcy:hasContentCategory ?cat ;
|
|
7966
|
+
qcy:sizeBytes ?size .
|
|
7967
|
+
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?fc }
|
|
7968
|
+
}
|
|
7969
|
+
}
|
|
7970
|
+
}
|
|
7971
|
+
GROUP BY ?cat
|
|
7972
|
+
ORDER BY DESC(?docCount)`;
|
|
7973
|
+
}
|
|
7974
|
+
async _runDocumentsByContentCategoryQuery(t) {
|
|
7975
|
+
const e = await this._api.sparql(t, this._projectId, this._graphType), o = {};
|
|
7976
|
+
return e.results.bindings.forEach((r) => {
|
|
7977
|
+
r.cat && (o[r.cat.value] = {
|
|
7978
|
+
size: r.totalSize ? parseInt(r.totalSize.value, 10) : 0,
|
|
7979
|
+
count: r.docCount ? parseInt(r.docCount.value, 10) : 0
|
|
7980
|
+
});
|
|
7981
|
+
}), o;
|
|
7982
|
+
}
|
|
7983
|
+
async _fetchDuplicateCount() {
|
|
7984
|
+
return this._runDuplicateCountQuery(this._buildDuplicateCountQuery());
|
|
7985
|
+
}
|
|
7986
|
+
_buildDuplicateCountQuery() {
|
|
7987
|
+
return `PREFIX qcy: <${y.qcy}>
|
|
7988
|
+
SELECT (COUNT(*) AS ?count)
|
|
7989
|
+
WHERE {
|
|
7990
|
+
SELECT ?fc
|
|
7991
|
+
WHERE {
|
|
7992
|
+
?fc a qcy:FileContent ;
|
|
7993
|
+
qcy:hasFileLocation ?fl .
|
|
7994
|
+
FILTER NOT EXISTS { ?x qcy:alternativeRepresentation ?fc }
|
|
7995
|
+
}
|
|
7996
|
+
GROUP BY ?fc
|
|
7997
|
+
HAVING (COUNT(?fl) > 1)
|
|
7998
|
+
}`;
|
|
7999
|
+
}
|
|
8000
|
+
async _runDuplicateCountQuery(t) {
|
|
8001
|
+
const o = (await this._api.sparql(t, this._projectId, this._graphType)).results.bindings[0];
|
|
8002
|
+
return o?.count ? parseInt(o.count.value, 10) : 0;
|
|
8003
|
+
}
|
|
8004
|
+
}
|
|
8005
|
+
class hr {
|
|
8006
|
+
constructor(t, e, { language: o, queryCache: r, rdfBase: s = ut, graphType: a }) {
|
|
8007
|
+
this._api = t, this._projectId = e, this.schema = new lr(t, e, o, r, a), this.entities = new we(t, e, s, r, a), this.documents = new ct(t, e, o, s, r, a), this.availableContentCategories = this.schema.availableContentCategories, this.availableEntityCategories = this.schema.availableEntityCategories, this.availableEntityRelationships = this.schema.availableEntityRelationships, this.schemaReady = this.schema.ready, this.entityInfoMap = this.entities.entityInfoMap, this.entityGraph = this.entities.entityGraph, this.documentInfoMap = this.documents.documentInfoMap, this.projectDocumentsData = this.documents.projectDocumentsData, this.searchResults = this._searchResults.asReadonly(), this.documents.fetchOverview().catch((n) => console.error("[CueProjectView] fetchOverview failed:", n));
|
|
8008
|
+
}
|
|
8009
|
+
_api;
|
|
8010
|
+
_projectId;
|
|
8011
|
+
/** Direct access to the schema data class (available categories / relationships). */
|
|
8012
|
+
schema;
|
|
8013
|
+
/** Direct access to the entity data class. */
|
|
8014
|
+
entities;
|
|
8015
|
+
/** Direct access to the document data class. */
|
|
8016
|
+
documents;
|
|
8017
|
+
// ── Proxied signals ────────────────────────────────────────────────────────
|
|
8018
|
+
/** Available content category definitions for this project. Auto-fetched on init. */
|
|
8019
|
+
availableContentCategories;
|
|
8020
|
+
/** Available entity category definitions for this project. Auto-fetched on init. */
|
|
8021
|
+
availableEntityCategories;
|
|
8022
|
+
/** Available entity relationship types. Auto-fetched on init. */
|
|
8023
|
+
availableEntityRelationships;
|
|
8024
|
+
/**
|
|
8025
|
+
* Resolves when the initial schema load has completed. Await before reading
|
|
8026
|
+
* schema signal values imperatively.
|
|
8027
|
+
*/
|
|
8028
|
+
schemaReady;
|
|
8029
|
+
/** Merged per-entity detail map. Populated lazily via `requestEntityData()` etc. */
|
|
8030
|
+
entityInfoMap;
|
|
8031
|
+
/** Project-level entity co-occurrence graph. Fetched once on init. */
|
|
8032
|
+
entityGraph;
|
|
8033
|
+
/** Per-document info map. Populated lazily via `requestDocumentData()`. */
|
|
8034
|
+
documentInfoMap;
|
|
8035
|
+
/** Project document overview (counts by suffix and category). Fetched on init. */
|
|
8036
|
+
projectDocumentsData;
|
|
8037
|
+
// ── Search state ───────────────────────────────────────────────────────────
|
|
8038
|
+
_searchResults = new k(void 0);
|
|
8039
|
+
/** The result of the most recent `search()` call. `undefined` before first search. */
|
|
8040
|
+
searchResults;
|
|
8041
|
+
_destroyed = !1;
|
|
8042
|
+
// ── Entity methods ─────────────────────────────────────────────────────────
|
|
8043
|
+
/**
|
|
8044
|
+
* Lazily batch-fetch core data (label + categories) for the given entity UUIDs.
|
|
8045
|
+
* Already-fetched UUIDs are skipped. Populates `entityInfoMap`.
|
|
8046
|
+
*/
|
|
8047
|
+
requestEntityData(t, e = !1) {
|
|
8048
|
+
this._destroyed || this.entities.requestEntityData(t, e);
|
|
8049
|
+
}
|
|
8050
|
+
/**
|
|
8051
|
+
* Lazily fetch OSM location data for the given entity UUIDs.
|
|
8052
|
+
* Already-fetched UUIDs are skipped. Populates `entityInfoMap` geometry fields.
|
|
8053
|
+
*/
|
|
8054
|
+
async requestEntityLocations(t) {
|
|
8055
|
+
if (!this._destroyed)
|
|
8056
|
+
return this.entities.requestEntityLocations(t);
|
|
8057
|
+
}
|
|
8058
|
+
/**
|
|
8059
|
+
* Fetch incoming and outgoing relationships for a single entity IRI.
|
|
8060
|
+
* Result is stored in `entityInfoMap[uuid].relationshipData`.
|
|
8061
|
+
*/
|
|
8062
|
+
async fetchEntityRelationships(t) {
|
|
8063
|
+
if (this._destroyed) throw new Error("CueProjectView is destroyed");
|
|
8064
|
+
return this.entities.fetchEntityRelationships(t);
|
|
8065
|
+
}
|
|
8066
|
+
/**
|
|
8067
|
+
* Fetch UUIDs of documents that reference the given entity IRI.
|
|
8068
|
+
* Result is stored in `entityInfoMap[uuid].documentRefs`.
|
|
8069
|
+
*/
|
|
8070
|
+
async fetchEntityDocuments(t) {
|
|
8071
|
+
if (this._destroyed) throw new Error("CueProjectView is destroyed");
|
|
8072
|
+
return this.entities.fetchEntityDocuments(t);
|
|
8073
|
+
}
|
|
8074
|
+
/** Constructs the full RDF IRI for an entity UUID. */
|
|
8075
|
+
entityIri(t) {
|
|
8076
|
+
return this.entities.entityIri(t);
|
|
8077
|
+
}
|
|
8078
|
+
// ── Document methods ───────────────────────────────────────────────────────
|
|
8079
|
+
/**
|
|
8080
|
+
* Lazily batch-fetch document info for the given UUIDs.
|
|
8081
|
+
* Already-fetched UUIDs are skipped. Populates `documentInfoMap`.
|
|
8082
|
+
*/
|
|
8083
|
+
requestDocumentData(t) {
|
|
8084
|
+
this._destroyed || this.documents.requestDocumentData(t);
|
|
8085
|
+
}
|
|
8086
|
+
// ── Search ─────────────────────────────────────────────────────────────────
|
|
8087
|
+
/**
|
|
8088
|
+
* Run a natural-language search against the project.
|
|
8089
|
+
* The result is stored in `searchResults` and replaces any previous result.
|
|
8090
|
+
*/
|
|
8091
|
+
async search(t, e) {
|
|
8092
|
+
if (this._destroyed) return;
|
|
8093
|
+
const o = await this._api.search({
|
|
8094
|
+
term: t,
|
|
8095
|
+
projectId: this._projectId,
|
|
8096
|
+
categories: e?.categories
|
|
8097
|
+
});
|
|
8098
|
+
this._destroyed || this._searchResults.set(o);
|
|
8099
|
+
}
|
|
8100
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
8101
|
+
/**
|
|
8102
|
+
* Switch the active language for schema labels and document text fields.
|
|
8103
|
+
* Schema responses are cached per language (instant if previously loaded).
|
|
8104
|
+
* The document info map is cleared and lazily re-populated on next access.
|
|
8105
|
+
*/
|
|
8106
|
+
setLanguage(t) {
|
|
8107
|
+
this._destroyed || (this.schema.setLanguage(t), this.documents.setLanguage(t));
|
|
8108
|
+
}
|
|
8109
|
+
/**
|
|
8110
|
+
* Reset all entity and document state and re-fetch the project overview.
|
|
8111
|
+
* Prefer creating a fresh `CueProjectView` when switching projects.
|
|
8112
|
+
* Use `reset()` only when the same project's data needs to be invalidated.
|
|
8113
|
+
*/
|
|
8114
|
+
reset() {
|
|
8115
|
+
this._destroyed || (this.entities.reset(), this.documents.reset(), this._searchResults.set(void 0), this.documents.fetchOverview().catch((t) => console.error("[CueProjectView] fetchOverview failed after reset:", t)));
|
|
8116
|
+
}
|
|
8117
|
+
/**
|
|
8118
|
+
* Tear down this view instance. Clears all reactive state and blocks further
|
|
8119
|
+
* updates. Call from the Angular adapter's `ngOnDestroy` or equivalent.
|
|
8120
|
+
*/
|
|
8121
|
+
destroy() {
|
|
8122
|
+
this._destroyed = !0, this._searchResults.set(void 0);
|
|
8123
|
+
}
|
|
8124
|
+
}
|
|
8125
|
+
function Yt(i, t) {
|
|
8126
|
+
return new Promise((e) => {
|
|
8127
|
+
const o = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map();
|
|
8128
|
+
for (const m of i)
|
|
8129
|
+
o.has(m.contentUUID) || o.set(m.contentUUID, []), o.get(m.contentUUID)?.push(m), r.set(m.locationUUID, m);
|
|
8130
|
+
const s = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Map();
|
|
8131
|
+
for (const m of t)
|
|
8132
|
+
s.has(m.contentUUID) || s.set(m.contentUUID, []), s.get(m.contentUUID)?.push(m), m.locationUUID && a.set(m.locationUUID, m);
|
|
8133
|
+
const n = [], p = [];
|
|
8134
|
+
for (const m of i)
|
|
8135
|
+
s.has(m.contentUUID) ? (s.get(m.contentUUID) || []).some((v) => v.locationUUID === m.locationUUID) || p.push(m) : n.push(m);
|
|
8136
|
+
const c = [], h = [];
|
|
8137
|
+
for (const m of t) {
|
|
8138
|
+
const x = o.get(m.contentUUID);
|
|
8139
|
+
x ? x.some((v) => v.locationUUID === m.locationUUID) || h.push(m) : c.push(m);
|
|
8140
|
+
}
|
|
8141
|
+
const d = i.length - n.length - p.length, g = i.length, w = g > 0 ? d / g : 1;
|
|
8142
|
+
let u = 0, f = 0;
|
|
8143
|
+
for (const m of i)
|
|
8144
|
+
f += m.size || 0, (s.get(m.contentUUID) || []).some((v) => v.locationUUID === m.locationUUID) && (u += m.size || 0);
|
|
8145
|
+
const E = f > 0 ? u / f : 1;
|
|
8146
|
+
e({
|
|
8147
|
+
localNotOnRemote: n,
|
|
8148
|
+
localNotOnRemotePathOnly: p,
|
|
8149
|
+
remoteNotOnLocal: c,
|
|
8150
|
+
remoteNotOnLocalPathOnly: h,
|
|
8151
|
+
syncCount: d,
|
|
8152
|
+
totalCount: g,
|
|
8153
|
+
syncSize: u,
|
|
8154
|
+
totalSize: f,
|
|
8155
|
+
synctPctSize: E,
|
|
8156
|
+
synctPctCount: w
|
|
8157
|
+
});
|
|
8158
|
+
});
|
|
8159
|
+
}
|
|
8160
|
+
const { namedNode: dr, literal: Rr } = j;
|
|
8161
|
+
dr("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
8162
|
+
const { namedNode: Ar } = j, { namedNode: gr, literal: Pr } = j;
|
|
8163
|
+
gr("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
8164
|
+
function ur(i) {
|
|
8038
8165
|
const t = i.split(".");
|
|
8039
8166
|
return t.length > 1 ? "." + t.pop()?.toLowerCase() : "";
|
|
8040
8167
|
}
|
|
8041
|
-
const { namedNode:
|
|
8042
|
-
|
|
8043
|
-
const { namedNode:
|
|
8044
|
-
|
|
8045
|
-
function
|
|
8046
|
-
const c =
|
|
8047
|
-
a === void 0 && (a =
|
|
8048
|
-
const g =
|
|
8168
|
+
const { namedNode: mr, literal: Or } = j;
|
|
8169
|
+
mr("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
8170
|
+
const { namedNode: wr, literal: Dr } = j;
|
|
8171
|
+
wr("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
8172
|
+
function Zt(i, t, e, o, r, s, a, n = !1, p = !1) {
|
|
8173
|
+
const c = ur(i), h = D(o), d = `${t}/${h}${c}`;
|
|
8174
|
+
a === void 0 && (a = lt[c]?.mime ?? "application/octet-stream");
|
|
8175
|
+
const g = eo(i, r);
|
|
8049
8176
|
return {
|
|
8050
8177
|
name: i,
|
|
8051
8178
|
blob_name: d,
|
|
@@ -8071,7 +8198,7 @@ async function U() {
|
|
|
8071
8198
|
"fs/promises"
|
|
8072
8199
|
);
|
|
8073
8200
|
}
|
|
8074
|
-
async function
|
|
8201
|
+
async function Jt(i) {
|
|
8075
8202
|
if (typeof window < "u")
|
|
8076
8203
|
throw new Error(
|
|
8077
8204
|
`Cannot read file from path "${i}" in a browser environment. Provide file.data (Uint8Array) instead.`
|
|
@@ -8080,10 +8207,10 @@ async function Yt(i) {
|
|
|
8080
8207
|
return t(i);
|
|
8081
8208
|
}
|
|
8082
8209
|
let q = null, G = null, H = null;
|
|
8083
|
-
function
|
|
8210
|
+
function Lr(i) {
|
|
8084
8211
|
H = i, G = null, q = null;
|
|
8085
8212
|
}
|
|
8086
|
-
async function
|
|
8213
|
+
async function fr() {
|
|
8087
8214
|
if (typeof window < "u") {
|
|
8088
8215
|
if (!H)
|
|
8089
8216
|
throw new Error(
|
|
@@ -8105,8 +8232,8 @@ async function mr() {
|
|
|
8105
8232
|
await a.default({ module_or_path: r }), q = a.scan;
|
|
8106
8233
|
}
|
|
8107
8234
|
}
|
|
8108
|
-
const
|
|
8109
|
-
async function
|
|
8235
|
+
const yr = "qlever", $ = 1e3, mt = "cue:pending:";
|
|
8236
|
+
async function wt(i) {
|
|
8110
8237
|
const { tmpdir: t } = await import(
|
|
8111
8238
|
/* webpackIgnore: true */
|
|
8112
8239
|
"os"
|
|
@@ -8116,37 +8243,37 @@ async function mt(i) {
|
|
|
8116
8243
|
);
|
|
8117
8244
|
return e(t(), `cue-sync-pending-${i}.json`);
|
|
8118
8245
|
}
|
|
8119
|
-
async function
|
|
8246
|
+
async function te(i) {
|
|
8120
8247
|
if (typeof window < "u") {
|
|
8121
|
-
const t = window.localStorage.getItem(`${
|
|
8248
|
+
const t = window.localStorage.getItem(`${mt}${i}`);
|
|
8122
8249
|
return t ? JSON.parse(t) : null;
|
|
8123
8250
|
}
|
|
8124
8251
|
try {
|
|
8125
|
-
const t = await (await U()).readFile(await
|
|
8252
|
+
const t = await (await U()).readFile(await wt(i), "utf-8");
|
|
8126
8253
|
return JSON.parse(t);
|
|
8127
8254
|
} catch {
|
|
8128
8255
|
return null;
|
|
8129
8256
|
}
|
|
8130
8257
|
}
|
|
8131
|
-
async function
|
|
8258
|
+
async function ee(i) {
|
|
8132
8259
|
const t = JSON.stringify(i);
|
|
8133
8260
|
if (typeof window < "u") {
|
|
8134
|
-
window.localStorage.setItem(`${
|
|
8261
|
+
window.localStorage.setItem(`${mt}${i.spaceId}`, t);
|
|
8135
8262
|
return;
|
|
8136
8263
|
}
|
|
8137
|
-
await (await U()).writeFile(await
|
|
8264
|
+
await (await U()).writeFile(await wt(i.spaceId), t, "utf-8");
|
|
8138
8265
|
}
|
|
8139
|
-
async function
|
|
8266
|
+
async function br(i) {
|
|
8140
8267
|
if (typeof window < "u") {
|
|
8141
|
-
window.localStorage.removeItem(`${
|
|
8268
|
+
window.localStorage.removeItem(`${mt}${i}`);
|
|
8142
8269
|
return;
|
|
8143
8270
|
}
|
|
8144
8271
|
try {
|
|
8145
|
-
await (await U()).unlink(await
|
|
8272
|
+
await (await U()).unlink(await wt(i));
|
|
8146
8273
|
} catch {
|
|
8147
8274
|
}
|
|
8148
8275
|
}
|
|
8149
|
-
class
|
|
8276
|
+
class vr {
|
|
8150
8277
|
constructor(t, e, o, r) {
|
|
8151
8278
|
this._auth = t, this._projects = e, this._blob = o, this._gatewayUrl = r;
|
|
8152
8279
|
}
|
|
@@ -8202,7 +8329,7 @@ class yr {
|
|
|
8202
8329
|
*/
|
|
8203
8330
|
async flushPendingMetadata(t, e, o) {
|
|
8204
8331
|
this._legacy = o ?? !1;
|
|
8205
|
-
const r = await
|
|
8332
|
+
const r = await te(t);
|
|
8206
8333
|
if (!(!r || r.items.length === 0)) {
|
|
8207
8334
|
console.info(`Trying to upload metadata (${r.items.length} item(s))...`), e && console.info(`Flushing ${r.items.length} pending file location(s) from previous sync ⏳`);
|
|
8208
8335
|
try {
|
|
@@ -8225,12 +8352,12 @@ class yr {
|
|
|
8225
8352
|
this._api?.getConsumption(o) ?? Promise.reject(new Error("CueSyncApi is not bound to a CueApi instance")),
|
|
8226
8353
|
this._fetchUnitCreditMap(s),
|
|
8227
8354
|
this._fetchTierNames()
|
|
8228
|
-
]), f = (await
|
|
8355
|
+
]), f = (await Yt(t, h)).localNotOnRemote ?? [], E = f.length > 0 ? await this.scanCost(f) : [];
|
|
8229
8356
|
let m = 0, x = 0;
|
|
8230
8357
|
for (const v of E) {
|
|
8231
8358
|
m += v.units;
|
|
8232
|
-
const
|
|
8233
|
-
s &&
|
|
8359
|
+
const b = g[c], C = b?.[v.ext] ?? 1;
|
|
8360
|
+
s && b && !(v.ext in b) && console.info(` Unknown format: .${v.ext} (using default rate of 1 credit/unit)`);
|
|
8234
8361
|
const P = v.units * C;
|
|
8235
8362
|
x += P, v.credits = Math.round(P);
|
|
8236
8363
|
}
|
|
@@ -8257,54 +8384,54 @@ class yr {
|
|
|
8257
8384
|
const [d, g] = await Promise.all([
|
|
8258
8385
|
this._listRemoteFiles(h, o, r, a),
|
|
8259
8386
|
this._api?.getConsumption(o) ?? Promise.reject(new Error("CueSyncApi is not bound to a CueApi instance"))
|
|
8260
|
-
]), { unitsAvailable: w } = g, u = await
|
|
8387
|
+
]), { unitsAvailable: w } = g, u = await Yt(t, d);
|
|
8261
8388
|
a && (console.info(`Total local files: ${t.length}`), console.info(`Total remote files: ${d.length}`), console.info(
|
|
8262
8389
|
`Total files to sync: ${(u.localNotOnRemote?.length ?? 0) + u.localNotOnRemotePathOnly.length}`
|
|
8263
8390
|
));
|
|
8264
8391
|
let f = u.syncCount, E = u.syncSize, m = 0, x = !1;
|
|
8265
8392
|
const I = u.localNotOnRemote ?? [];
|
|
8266
8393
|
if (I.length > 0) {
|
|
8267
|
-
const C = (await this.scanCost(I)).reduce((P,
|
|
8394
|
+
const C = (await this.scanCost(I)).reduce((P, ye) => P + ye.units, 0);
|
|
8268
8395
|
if (C > w)
|
|
8269
8396
|
throw new Error(
|
|
8270
8397
|
`Insufficient units: ${C} units required but only ${w} available.`
|
|
8271
8398
|
);
|
|
8272
8399
|
}
|
|
8273
8400
|
await this._initPendingBatch(o, a), a && I.length && console.info("Syncing missing files ⏳");
|
|
8274
|
-
for (const
|
|
8401
|
+
for (const b of I)
|
|
8275
8402
|
try {
|
|
8276
|
-
const C =
|
|
8277
|
-
|
|
8403
|
+
const C = Zt(
|
|
8404
|
+
b.relativePath,
|
|
8278
8405
|
o,
|
|
8279
8406
|
s,
|
|
8280
|
-
|
|
8407
|
+
b.md5,
|
|
8281
8408
|
r
|
|
8282
8409
|
);
|
|
8283
|
-
if (!C.blob_name) throw new Error(`blob_name missing for ${
|
|
8284
|
-
const P =
|
|
8410
|
+
if (!C.blob_name) throw new Error(`blob_name missing for ${b.relativePath}`);
|
|
8411
|
+
const P = b.data ?? new Uint8Array(await Jt(b.fullPath));
|
|
8285
8412
|
await this._blob.uploadRaw(
|
|
8286
8413
|
C.blob_name,
|
|
8287
8414
|
P,
|
|
8288
8415
|
C
|
|
8289
8416
|
), await this._queueFileLocation({
|
|
8290
|
-
relativePath:
|
|
8291
|
-
md5:
|
|
8292
|
-
size:
|
|
8417
|
+
relativePath: b.relativePath,
|
|
8418
|
+
md5: b.md5,
|
|
8419
|
+
size: b.size,
|
|
8293
8420
|
providerId: r,
|
|
8294
8421
|
fileContentExists: !1
|
|
8295
|
-
}), x = !0, f += 1, E +=
|
|
8422
|
+
}), x = !0, f += 1, E += b.size || 0, this._logProgress(f, u.totalCount, E, u.totalSize, n);
|
|
8296
8423
|
} catch (C) {
|
|
8297
|
-
m += 1, console.error(`[CueSyncApi] Failed to upload file: ${
|
|
8424
|
+
m += 1, console.error(`[CueSyncApi] Failed to upload file: ${b.fullPath}`), a && console.error("[CueSyncApi] Upload error details:", C);
|
|
8298
8425
|
}
|
|
8299
8426
|
a && u.localNotOnRemotePathOnly.length && console.info(`Syncing missing file locations (on provider "${r}") ⏳`);
|
|
8300
|
-
for (const
|
|
8427
|
+
for (const b of u.localNotOnRemotePathOnly)
|
|
8301
8428
|
await this._queueFileLocation({
|
|
8302
|
-
relativePath:
|
|
8303
|
-
md5:
|
|
8304
|
-
size:
|
|
8429
|
+
relativePath: b.relativePath,
|
|
8430
|
+
md5: b.md5,
|
|
8431
|
+
size: b.size,
|
|
8305
8432
|
providerId: r,
|
|
8306
8433
|
fileContentExists: !0
|
|
8307
|
-
}), x = !0, f += 1, E +=
|
|
8434
|
+
}), x = !0, f += 1, E += b.size || 0, this._logProgress(f, u.totalCount, E, u.totalSize, n);
|
|
8308
8435
|
await this._drainPending(a), this._stopFlushTimer();
|
|
8309
8436
|
const v = await (this._api?.getConsumption(o) ?? Promise.resolve({ creditsAvailable: 0 }));
|
|
8310
8437
|
return {
|
|
@@ -8320,7 +8447,7 @@ class yr {
|
|
|
8320
8447
|
async _getOrCreateGraph(t, e) {
|
|
8321
8448
|
const o = this._graphMap.get(t);
|
|
8322
8449
|
if (o) return o;
|
|
8323
|
-
const s = (await this._projects.getProject(t))?.projectSettings?.graph?.type ??
|
|
8450
|
+
const s = (await this._projects.getProject(t))?.projectSettings?.graph?.type ?? yr, a = s === "qlever" ? `${this._gatewayUrl}${pe}` : `${this._gatewayUrl}${ne}`, n = s === "qlever" ? `${this._gatewayUrl}${go}` : `${this._gatewayUrl}${co}`, p = new Je({
|
|
8324
8451
|
graphType: s,
|
|
8325
8452
|
queryEndpoint: a,
|
|
8326
8453
|
updateEndpoint: n,
|
|
@@ -8360,7 +8487,7 @@ class yr {
|
|
|
8360
8487
|
return p;
|
|
8361
8488
|
}
|
|
8362
8489
|
async _getGraphFiles(t, e) {
|
|
8363
|
-
const o = `PREFIX qcy: <${
|
|
8490
|
+
const o = `PREFIX qcy: <${y.qcy}>
|
|
8364
8491
|
SELECT ?fc ?loc ?created ?fp ?size
|
|
8365
8492
|
WHERE {
|
|
8366
8493
|
?fc a qcy:FileContent ;
|
|
@@ -8386,7 +8513,7 @@ WHERE {
|
|
|
8386
8513
|
}
|
|
8387
8514
|
async _initPendingBatch(t, e) {
|
|
8388
8515
|
this._flushTimer !== null && (clearInterval(this._flushTimer), this._flushTimer = null), this._pendingSpaceId = t, this._pendingItems = [];
|
|
8389
|
-
const o = await
|
|
8516
|
+
const o = await te(t);
|
|
8390
8517
|
if (o && o.items.length > 0) {
|
|
8391
8518
|
console.info(`Trying to upload metadata from interrupted sync (${o.items.length} item(s))...`), e && console.info(`Flushing ${o.items.length} pending file location(s) from previous sync ⏳`);
|
|
8392
8519
|
try {
|
|
@@ -8407,7 +8534,7 @@ WHERE {
|
|
|
8407
8534
|
typeof r == "object" && typeof r.unref == "function" && r.unref(), this._flushTimer = r;
|
|
8408
8535
|
}
|
|
8409
8536
|
async _queueFileLocation(t) {
|
|
8410
|
-
this._pendingItems.push(t), this._pendingSpaceId && await
|
|
8537
|
+
this._pendingItems.push(t), this._pendingSpaceId && await ee({ spaceId: this._pendingSpaceId, items: this._pendingItems });
|
|
8411
8538
|
}
|
|
8412
8539
|
/**
|
|
8413
8540
|
* Flush all queued file-location items to the commands API in a single batch.
|
|
@@ -8422,18 +8549,18 @@ WHERE {
|
|
|
8422
8549
|
}
|
|
8423
8550
|
async _flushBatch(t, e, o) {
|
|
8424
8551
|
const r = [...t];
|
|
8425
|
-
this._pendingSpaceId === e && (this._pendingItems = []), await
|
|
8552
|
+
this._pendingSpaceId === e && (this._pendingItems = []), await br(e);
|
|
8426
8553
|
try {
|
|
8427
8554
|
for (let s = 0; s < r.length; s += $)
|
|
8428
8555
|
await this._postFssBatch(r.slice(s, s + $), e);
|
|
8429
8556
|
o && console.info(`Wrote ${r.length} file location(s) to commands API ✅`);
|
|
8430
8557
|
} catch (s) {
|
|
8431
8558
|
const a = [...r, ...this._pendingItems];
|
|
8432
|
-
throw this._pendingItems = a, await
|
|
8559
|
+
throw this._pendingItems = a, await ee({ spaceId: e, items: a }), s;
|
|
8433
8560
|
}
|
|
8434
8561
|
}
|
|
8435
8562
|
async _postFssBatch(t, e) {
|
|
8436
|
-
const o = this._legacy ? `${this._gatewayUrl}${
|
|
8563
|
+
const o = this._legacy ? `${this._gatewayUrl}${Lt}?blob=true` : `${this._gatewayUrl}${Lt}`;
|
|
8437
8564
|
let r;
|
|
8438
8565
|
try {
|
|
8439
8566
|
r = await this._auth.authenticatedFetch(o, {
|
|
@@ -8463,14 +8590,14 @@ WHERE {
|
|
|
8463
8590
|
* shown to the user before or after calling {@link sync}.
|
|
8464
8591
|
*/
|
|
8465
8592
|
async scanCost(t) {
|
|
8466
|
-
if (G || (G =
|
|
8593
|
+
if (G || (G = fr()), await G, !q) throw new Error("WASM scan function not initialised");
|
|
8467
8594
|
const e = 200, o = /* @__PURE__ */ new Map();
|
|
8468
8595
|
for (let r = 0; r < t.length; r += e) {
|
|
8469
8596
|
const s = t.slice(r, r + e), a = await Promise.all(
|
|
8470
8597
|
s.map(async (p) => ({
|
|
8471
8598
|
originalPath: p.relativePath,
|
|
8472
8599
|
// Use pre-loaded data if available (browser), otherwise read from disk (Node.js).
|
|
8473
|
-
data: p.data ?? new Uint8Array(await
|
|
8600
|
+
data: p.data ?? new Uint8Array(await Jt(p.fullPath))
|
|
8474
8601
|
}))
|
|
8475
8602
|
), n = q(a);
|
|
8476
8603
|
for (const p of n) {
|
|
@@ -8530,7 +8657,7 @@ WHERE {
|
|
|
8530
8657
|
const { spaceId: o, providerId: r, userId: s, signal: a, onProgress: n } = e;
|
|
8531
8658
|
if (!t.data)
|
|
8532
8659
|
throw new Error("syncBrowserFile requires file.data (Uint8Array). Read the file with File.arrayBuffer() first.");
|
|
8533
|
-
const p =
|
|
8660
|
+
const p = Zt(t.relativePath, o, s, t.md5, r);
|
|
8534
8661
|
if (!p.blob_name) throw new Error(`blob_name missing for ${t.relativePath}`);
|
|
8535
8662
|
await this._blob.uploadRaw(
|
|
8536
8663
|
p.blob_name,
|
|
@@ -8574,7 +8701,7 @@ WHERE {
|
|
|
8574
8701
|
s({ percent: a, syncCount: t, totalCount: e, syncSize: o, totalSize: r });
|
|
8575
8702
|
}
|
|
8576
8703
|
}
|
|
8577
|
-
const
|
|
8704
|
+
const oe = {
|
|
8578
8705
|
production: {
|
|
8579
8706
|
gatewayUrl: "https://accessors-api-gateway-ueyeemwf2a-oa.a.run.app",
|
|
8580
8707
|
tokenUrl: "https://accessors-api-gateway-ueyeemwf2a-oa.a.run.app/token",
|
|
@@ -8594,7 +8721,7 @@ const te = {
|
|
|
8594
8721
|
firestoreEmulatorPort: 8080
|
|
8595
8722
|
}
|
|
8596
8723
|
};
|
|
8597
|
-
class
|
|
8724
|
+
class fe {
|
|
8598
8725
|
auth;
|
|
8599
8726
|
api;
|
|
8600
8727
|
projects;
|
|
@@ -8621,7 +8748,7 @@ class me {
|
|
|
8621
8748
|
* ```
|
|
8622
8749
|
*/
|
|
8623
8750
|
get gis() {
|
|
8624
|
-
return this._gis || (this._gis = new
|
|
8751
|
+
return this._gis || (this._gis = new ir(
|
|
8625
8752
|
() => this.api.getAuthHeaders(),
|
|
8626
8753
|
this._endpoints.gatewayUrl
|
|
8627
8754
|
)), this._gis;
|
|
@@ -8630,18 +8757,18 @@ class me {
|
|
|
8630
8757
|
!t.apiKey && !t.appId && !t.measurementId && console.warn(
|
|
8631
8758
|
"Using default SDK app settings. Contact QAECY for your own configuration for any production code."
|
|
8632
8759
|
);
|
|
8633
|
-
const o = t.apiKey ??
|
|
8634
|
-
this._endpoints = { ...
|
|
8760
|
+
const o = t.apiKey ?? Z.apiKey, r = t.appId ?? Z.appId, s = t.measurementId ?? Z.measurementId, a = t.environment ?? "production";
|
|
8761
|
+
this._endpoints = { ...oe[a], ...t.endpoints }, this._isEmulator = a === "emulator", this._app = be().find((g) => g.name === "[DEFAULT]") ?? ve({
|
|
8635
8762
|
apiKey: o,
|
|
8636
8763
|
appId: r,
|
|
8637
8764
|
measurementId: s,
|
|
8638
|
-
authDomain: `${
|
|
8639
|
-
projectId:
|
|
8640
|
-
messagingSenderId:
|
|
8641
|
-
}), this.auth = new
|
|
8642
|
-
const n = T(this._app,
|
|
8643
|
-
this._isEmulator && (
|
|
8644
|
-
const d = new
|
|
8765
|
+
authDomain: `${xt}.firebaseapp.com`,
|
|
8766
|
+
projectId: xt,
|
|
8767
|
+
messagingSenderId: oo
|
|
8768
|
+
}), this.auth = new Ut(this._app, this._isEmulator, this._endpoints), this.projects = new Ht(this.auth, this._app, this._isEmulator, this._endpoints), this._storageRaw = T(this._app, Tt), this._storageProcessed = T(this._app, St);
|
|
8769
|
+
const n = T(this._app, At), p = T(this._app, Rt), c = T(this._app, Ct), h = T(this._app, Pt);
|
|
8770
|
+
this._isEmulator && (Q(this._storageRaw, this._endpoints.storageEmulatorHost, this._endpoints.storageEmulatorPort), Q(this._storageProcessed, this._endpoints.storageEmulatorHost, this._endpoints.storageEmulatorPort)), this.api = this._buildApi(this.projects);
|
|
8771
|
+
const d = new kt({
|
|
8645
8772
|
storageRaw: this._storageRaw,
|
|
8646
8773
|
storageProcessed: this._storageProcessed,
|
|
8647
8774
|
storagePublic: n,
|
|
@@ -8649,12 +8776,12 @@ class me {
|
|
|
8649
8776
|
storageChatSessions: c,
|
|
8650
8777
|
storagePersistence: h
|
|
8651
8778
|
});
|
|
8652
|
-
this.storage = new
|
|
8779
|
+
this.storage = new Mt(d), this.profile = new Wt(
|
|
8653
8780
|
this.auth,
|
|
8654
8781
|
this._app,
|
|
8655
8782
|
this._isEmulator,
|
|
8656
8783
|
this._endpoints.gatewayUrl
|
|
8657
|
-
), this.privileges = new
|
|
8784
|
+
), this.privileges = new Qt(this.auth.isSuperAdmin), this._isEmulator && Q(h, this._endpoints.storageEmulatorHost, this._endpoints.storageEmulatorPort), this.cache = new Xt(h);
|
|
8658
8785
|
}
|
|
8659
8786
|
/**
|
|
8660
8787
|
* Create a `Cue` instance from an already-initialized Firebase app.
|
|
@@ -8673,16 +8800,16 @@ class me {
|
|
|
8673
8800
|
* });
|
|
8674
8801
|
*/
|
|
8675
8802
|
static fromApp(t, e = {}) {
|
|
8676
|
-
const o = e.environment ?? "production", r = { ...
|
|
8803
|
+
const o = e.environment ?? "production", r = { ...oe[o], ...e.endpoints }, s = new Ut(t, !1, r), a = new Ht(s, t, !1, r), n = T(t, Tt), p = T(t, St), c = T(t, At), h = T(t, Rt), d = T(t, Ct), g = T(t, Pt), w = new kt({
|
|
8677
8804
|
storageRaw: n,
|
|
8678
8805
|
storageProcessed: p,
|
|
8679
8806
|
storagePublic: c,
|
|
8680
8807
|
storageLogs: h,
|
|
8681
8808
|
storageChatSessions: d,
|
|
8682
8809
|
storagePersistence: g
|
|
8683
|
-
}), u = new
|
|
8810
|
+
}), u = new vr(s, a, w, r.gatewayUrl), f = new zt(s, r.gatewayUrl, a, u);
|
|
8684
8811
|
u._bindApi(f);
|
|
8685
|
-
const E = new
|
|
8812
|
+
const E = new Wt(s, t, !1, r.gatewayUrl), m = Object.create(fe.prototype), x = new Qt(s.isSuperAdmin), I = new Xt(g), v = new Mt(w);
|
|
8686
8813
|
return Object.assign(m, {
|
|
8687
8814
|
_app: t,
|
|
8688
8815
|
_endpoints: r,
|
|
@@ -8700,7 +8827,7 @@ class me {
|
|
|
8700
8827
|
}
|
|
8701
8828
|
/** Override in subclasses to provide a custom CueApi (e.g. with sync). */
|
|
8702
8829
|
_buildApi(t) {
|
|
8703
|
-
return new
|
|
8830
|
+
return new zt(this.auth, this._endpoints.gatewayUrl, t);
|
|
8704
8831
|
}
|
|
8705
8832
|
/** Convenience: get the current user's Firebase ID token */
|
|
8706
8833
|
getToken(t = !1) {
|
|
@@ -8725,7 +8852,7 @@ class me {
|
|
|
8725
8852
|
get: (r) => this.cache.getQueryCache(t, r).then((s) => s?.results),
|
|
8726
8853
|
set: (r, s) => this.cache.setQueryCache(t, r, { query: r, results: s })
|
|
8727
8854
|
};
|
|
8728
|
-
return new
|
|
8855
|
+
return new hr(this.api, t, { ...e, queryCache: o });
|
|
8729
8856
|
}
|
|
8730
8857
|
/**
|
|
8731
8858
|
* Creates a `CueProjectEntities` instance for the given project, with the
|
|
@@ -8749,7 +8876,7 @@ class me {
|
|
|
8749
8876
|
get: (r) => this.cache.getQueryCache(t, r).then((s) => s?.results),
|
|
8750
8877
|
set: (r, s) => this.cache.setQueryCache(t, r, { query: r, results: s })
|
|
8751
8878
|
};
|
|
8752
|
-
return new
|
|
8879
|
+
return new we(
|
|
8753
8880
|
this.api,
|
|
8754
8881
|
t,
|
|
8755
8882
|
e?.rdfBase,
|
|
@@ -8779,7 +8906,7 @@ class me {
|
|
|
8779
8906
|
const a = {
|
|
8780
8907
|
get: (p) => this.cache.getQueryCache(t, p).then((c) => c?.results),
|
|
8781
8908
|
set: (p, c) => this.cache.setQueryCache(t, p, { query: p, results: c })
|
|
8782
|
-
}, n = new
|
|
8909
|
+
}, n = new ct(
|
|
8783
8910
|
this.api,
|
|
8784
8911
|
t,
|
|
8785
8912
|
this.api.language,
|
|
@@ -8793,7 +8920,7 @@ class me {
|
|
|
8793
8920
|
get: (s) => this.cache.getQueryCache(t, s).then((a) => a?.results),
|
|
8794
8921
|
set: (s, a) => this.cache.setQueryCache(t, s, { query: s, results: a })
|
|
8795
8922
|
};
|
|
8796
|
-
return new
|
|
8923
|
+
return new ct(
|
|
8797
8924
|
this.api,
|
|
8798
8925
|
t,
|
|
8799
8926
|
e?.language ?? this.api.language,
|
|
@@ -8804,29 +8931,30 @@ class me {
|
|
|
8804
8931
|
}
|
|
8805
8932
|
}
|
|
8806
8933
|
export {
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
|
|
8813
|
-
|
|
8814
|
-
|
|
8815
|
-
|
|
8816
|
-
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
|
|
8822
|
-
|
|
8823
|
-
|
|
8824
|
-
|
|
8825
|
-
|
|
8826
|
-
|
|
8827
|
-
|
|
8828
|
-
|
|
8934
|
+
Ct as B,
|
|
8935
|
+
fe as C,
|
|
8936
|
+
Kt as R,
|
|
8937
|
+
zt as a,
|
|
8938
|
+
Ut as b,
|
|
8939
|
+
Xt as c,
|
|
8940
|
+
bo as d,
|
|
8941
|
+
ir as e,
|
|
8942
|
+
Qt as f,
|
|
8943
|
+
Wt as g,
|
|
8944
|
+
ct as h,
|
|
8945
|
+
we as i,
|
|
8946
|
+
lr as j,
|
|
8947
|
+
hr as k,
|
|
8948
|
+
Ht as l,
|
|
8949
|
+
k as m,
|
|
8950
|
+
Mt as n,
|
|
8951
|
+
vr as o,
|
|
8952
|
+
fo as p,
|
|
8953
|
+
Lr as q,
|
|
8954
|
+
dt as r,
|
|
8955
|
+
gt as s,
|
|
8829
8956
|
Rt as t,
|
|
8830
|
-
|
|
8831
|
-
|
|
8957
|
+
Pt as u,
|
|
8958
|
+
At as v,
|
|
8959
|
+
kt as w
|
|
8832
8960
|
};
|