@qaecy/cue-cli 0.0.46 → 0.0.48
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/assets/wasm/dir_scanner_wasm.js +461 -0
- package/main.js +789 -76
- package/package.json +1 -1
- package/readme.md +36 -0
package/main.js
CHANGED
|
@@ -372,7 +372,7 @@ var init_md5_builder_node = __esm({
|
|
|
372
372
|
});
|
|
373
373
|
|
|
374
374
|
// apps/desktop/cue-cli/src/main.ts
|
|
375
|
-
var
|
|
375
|
+
var import_commander2 = require("commander");
|
|
376
376
|
var import_fs8 = require("fs");
|
|
377
377
|
var import_path4 = require("path");
|
|
378
378
|
|
|
@@ -4721,6 +4721,53 @@ var prefixCC = {
|
|
|
4721
4721
|
rex: "http://purl.obolibrary.org/obo/REX_"
|
|
4722
4722
|
};
|
|
4723
4723
|
|
|
4724
|
+
// libs/js/prefixes/src/lib/compact-expand.ts
|
|
4725
|
+
var CompactExpand = class _CompactExpand {
|
|
4726
|
+
static _instance;
|
|
4727
|
+
// Opposite map is built once
|
|
4728
|
+
_nsMap;
|
|
4729
|
+
static getInstance() {
|
|
4730
|
+
if (this._instance) {
|
|
4731
|
+
return this._instance;
|
|
4732
|
+
}
|
|
4733
|
+
this._instance = new _CompactExpand();
|
|
4734
|
+
return this._instance;
|
|
4735
|
+
}
|
|
4736
|
+
compactIRI(iri) {
|
|
4737
|
+
let nsMap = this._nsMap;
|
|
4738
|
+
if (nsMap === void 0)
|
|
4739
|
+
nsMap = this._buildNSMap();
|
|
4740
|
+
let ns = iri;
|
|
4741
|
+
if (iri.includes("#"))
|
|
4742
|
+
ns = `${iri.split("#")[0]}#`;
|
|
4743
|
+
else {
|
|
4744
|
+
const parts = iri.split("/");
|
|
4745
|
+
parts.pop();
|
|
4746
|
+
ns = parts.join("/") + "/";
|
|
4747
|
+
}
|
|
4748
|
+
if (ns === void 0)
|
|
4749
|
+
return iri;
|
|
4750
|
+
const pfx = nsMap[ns];
|
|
4751
|
+
if (pfx === void 0)
|
|
4752
|
+
return iri;
|
|
4753
|
+
return iri.replace(ns, `${pfx}:`);
|
|
4754
|
+
}
|
|
4755
|
+
expandIRI(iri) {
|
|
4756
|
+
const prefix = iri.split(":")[0];
|
|
4757
|
+
const ns = prefixCC[prefix] ?? qaecyPrefixes[prefix];
|
|
4758
|
+
return iri.replace(`${prefix}:`, ns);
|
|
4759
|
+
}
|
|
4760
|
+
_buildNSMap() {
|
|
4761
|
+
const map = {};
|
|
4762
|
+
Object.keys(prefixCC).forEach((key) => map[prefixCC[key]] = key);
|
|
4763
|
+
Object.keys(qaecyPrefixes).forEach(
|
|
4764
|
+
(key) => map[qaecyPrefixes[key]] = key
|
|
4765
|
+
);
|
|
4766
|
+
this._nsMap = map;
|
|
4767
|
+
return map;
|
|
4768
|
+
}
|
|
4769
|
+
};
|
|
4770
|
+
|
|
4724
4771
|
// libs/js/sync-tools/src/lib/list-remote-files.ts
|
|
4725
4772
|
async function listRemoteFiles(spaceId, providerId, queryHandler2, verbose = false) {
|
|
4726
4773
|
const firebase = CueFirebase.getInstance();
|
|
@@ -5097,8 +5144,10 @@ var ENDPOINT_CREATE_PROJECT = "/commands/admin/project";
|
|
|
5097
5144
|
var ENDPOINT_SEARCH = "/assistant/search";
|
|
5098
5145
|
var ENDPOINT_FUSEKI_QUERY = "/triplestore/query";
|
|
5099
5146
|
var ENDPOINT_FUSEKI_UPDATE = "/triplestore/update";
|
|
5147
|
+
var ENDPOINT_FUSEKI_SHACL = "/triplestore/shacl";
|
|
5100
5148
|
var ENDPOINT_QLEVER_QUERY = "/qlever-server/qlever/query";
|
|
5101
5149
|
var ENDPOINT_QLEVER_UPDATE = "/qlever-server/qlever/update";
|
|
5150
|
+
var ENDPOINT_QLEVER_SHACL = "/qlever-server/qlever/shacl";
|
|
5102
5151
|
var ENDPOINT_FSS_BATCH = "/commands/file-system-structure/batch";
|
|
5103
5152
|
var MICROSOFT_PROVIDER_ID = "microsoft.com";
|
|
5104
5153
|
var SUPERADMIN_ROLE = "superadmin";
|
|
@@ -5290,6 +5339,89 @@ var CueAuth = class {
|
|
|
5290
5339
|
}
|
|
5291
5340
|
};
|
|
5292
5341
|
|
|
5342
|
+
// libs/js/cue-sdk/src/lib/storage.ts
|
|
5343
|
+
var CueStorage = class {
|
|
5344
|
+
constructor(_blob) {
|
|
5345
|
+
this._blob = _blob;
|
|
5346
|
+
}
|
|
5347
|
+
/**
|
|
5348
|
+
* Returns a Firebase authenticated download URL for a document stored in Cue.
|
|
5349
|
+
*
|
|
5350
|
+
* The storage path is `{projectId}/{uuid}{suffix}`, e.g. `my-project/abc-123.pdf`.
|
|
5351
|
+
*
|
|
5352
|
+
* @param projectId - The Cue project (space) ID.
|
|
5353
|
+
* @param uuid - The document UUID.
|
|
5354
|
+
* @param suffix - File suffix including the leading dot, e.g. `'.pdf'`, `'.ifc'`.
|
|
5355
|
+
* @param bucket - `'raw'` (default, original uploads) or `'processed'` (derived artefacts).
|
|
5356
|
+
*/
|
|
5357
|
+
async getDownloadUrl(projectId, uuid, suffix, bucket = "raw") {
|
|
5358
|
+
const path = `${projectId}/${uuid}${suffix}`;
|
|
5359
|
+
const url = await this._blob.getDownloadURL(bucket, path);
|
|
5360
|
+
if (!url)
|
|
5361
|
+
throw new Error(`File not found in storage: ${path} (bucket: ${bucket})`);
|
|
5362
|
+
return url;
|
|
5363
|
+
}
|
|
5364
|
+
/**
|
|
5365
|
+
* Returns a Firebase authenticated download URL for an alternative representation
|
|
5366
|
+
* using its full `qcy:remoteRelativePath` stored in the processed bucket.
|
|
5367
|
+
*
|
|
5368
|
+
* Use this instead of `getDownloadUrl` when the document info was obtained via
|
|
5369
|
+
* `fetchAlternativeRepresentations` and carries a `remoteRelativePath`.
|
|
5370
|
+
*
|
|
5371
|
+
* @param remoteRelativePath - The full path in the processed bucket,
|
|
5372
|
+
* e.g. `{projectId}/fragments/{uuid}.fragments`.
|
|
5373
|
+
*/
|
|
5374
|
+
async getAltRepDownloadUrl(remoteRelativePath) {
|
|
5375
|
+
const url = await this._blob.getDownloadURL("processed", remoteRelativePath);
|
|
5376
|
+
if (!url)
|
|
5377
|
+
throw new Error(`Alternative representation not found in storage: ${remoteRelativePath}`);
|
|
5378
|
+
return url;
|
|
5379
|
+
}
|
|
5380
|
+
};
|
|
5381
|
+
|
|
5382
|
+
// libs/js/cue-sdk/src/lib/tables.ts
|
|
5383
|
+
var ENDPOINT_DATA_VIEWS_TABLES = "/data-views/tables";
|
|
5384
|
+
var ENDPOINT_COMMANDS_TABLES = "/commands/tables";
|
|
5385
|
+
var CueTables = class {
|
|
5386
|
+
constructor(_auth, _gatewayUrl) {
|
|
5387
|
+
this._auth = _auth;
|
|
5388
|
+
this._gatewayUrl = _gatewayUrl;
|
|
5389
|
+
}
|
|
5390
|
+
async listTables(projectId) {
|
|
5391
|
+
const response = await this._auth.authenticatedFetch(
|
|
5392
|
+
`${this._gatewayUrl}${ENDPOINT_DATA_VIEWS_TABLES}`,
|
|
5393
|
+
{
|
|
5394
|
+
headers: {
|
|
5395
|
+
"Content-Type": "application/json",
|
|
5396
|
+
"x-project-id": projectId,
|
|
5397
|
+
"cue-project-id": projectId
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
);
|
|
5401
|
+
if (!response.ok) {
|
|
5402
|
+
throw new Error(`Failed to list tables: ${response.status} ${response.statusText}`);
|
|
5403
|
+
}
|
|
5404
|
+
return response.json();
|
|
5405
|
+
}
|
|
5406
|
+
async saveTables(tables, projectId) {
|
|
5407
|
+
const response = await this._auth.authenticatedFetch(
|
|
5408
|
+
`${this._gatewayUrl}${ENDPOINT_COMMANDS_TABLES}`,
|
|
5409
|
+
{
|
|
5410
|
+
method: "PUT",
|
|
5411
|
+
headers: {
|
|
5412
|
+
"Content-Type": "application/json",
|
|
5413
|
+
"x-project-id": projectId,
|
|
5414
|
+
"cue-project-id": projectId
|
|
5415
|
+
},
|
|
5416
|
+
body: JSON.stringify(tables)
|
|
5417
|
+
}
|
|
5418
|
+
);
|
|
5419
|
+
if (!response.ok) {
|
|
5420
|
+
throw new Error(`Failed to save tables: ${response.status} ${response.statusText}`);
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
5423
|
+
};
|
|
5424
|
+
|
|
5293
5425
|
// libs/js/cue-sdk/src/lib/api.ts
|
|
5294
5426
|
var CueApi = class {
|
|
5295
5427
|
constructor(_auth, _gatewayUrl, projects, sync) {
|
|
@@ -5297,6 +5429,14 @@ var CueApi = class {
|
|
|
5297
5429
|
this._gatewayUrl = _gatewayUrl;
|
|
5298
5430
|
this.projects = projects;
|
|
5299
5431
|
this.sync = sync;
|
|
5432
|
+
this.tables = new CueTables(_auth, _gatewayUrl);
|
|
5433
|
+
}
|
|
5434
|
+
tables;
|
|
5435
|
+
/** Active language used for language-sensitive SPARQL queries across all project classes. */
|
|
5436
|
+
language = "en";
|
|
5437
|
+
/** Updates the active language. All project classes (`CueProjectSchema`, `CueProjectDocuments`, `CueProjectEntities`) read this at query time. */
|
|
5438
|
+
setLanguage(lang) {
|
|
5439
|
+
this.language = lang;
|
|
5300
5440
|
}
|
|
5301
5441
|
/**
|
|
5302
5442
|
* Returns standard authentication headers for the current user.
|
|
@@ -5368,6 +5508,57 @@ var CueApi = class {
|
|
|
5368
5508
|
}
|
|
5369
5509
|
return response.json();
|
|
5370
5510
|
}
|
|
5511
|
+
/**
|
|
5512
|
+
* Validate a SHACL shape against the project's triplestore.
|
|
5513
|
+
*
|
|
5514
|
+
* @param shape - SHACL shapes graph in Turtle syntax.
|
|
5515
|
+
* @param projectId - Project to validate against.
|
|
5516
|
+
* @param options - `format`: `'json-ld'` (default, structured result) or `'turtle'` (raw string).
|
|
5517
|
+
* `verbose`: include server-side timing logs.
|
|
5518
|
+
*
|
|
5519
|
+
* Returns a {@link ShaclValidationReport} for JSON-LD, or a Turtle string.
|
|
5520
|
+
*/
|
|
5521
|
+
async shacl(shape, projectId, options) {
|
|
5522
|
+
const fmt = options?.format ?? "json-ld";
|
|
5523
|
+
const accept = fmt === "turtle" ? "text/turtle" : "application/ld+json";
|
|
5524
|
+
if (options?.graphType === "fuseki") {
|
|
5525
|
+
const response2 = await this._auth.authenticatedFetch(
|
|
5526
|
+
`${this._gatewayUrl}${ENDPOINT_FUSEKI_SHACL}`,
|
|
5527
|
+
{
|
|
5528
|
+
method: "POST",
|
|
5529
|
+
headers: {
|
|
5530
|
+
"Content-Type": "text/turtle",
|
|
5531
|
+
"Accept": accept,
|
|
5532
|
+
"x-project-id": projectId,
|
|
5533
|
+
"cue-project-id": projectId
|
|
5534
|
+
},
|
|
5535
|
+
body: shape
|
|
5536
|
+
}
|
|
5537
|
+
);
|
|
5538
|
+
if (!response2.ok) {
|
|
5539
|
+
const msg = await response2.text().catch(() => "");
|
|
5540
|
+
throw new Error(`SHACL validation failed: ${response2.status} ${response2.statusText}${msg ? " \u2014 " + msg.slice(0, 200) : ""}`);
|
|
5541
|
+
}
|
|
5542
|
+
return fmt === "turtle" ? response2.text() : response2.json();
|
|
5543
|
+
}
|
|
5544
|
+
const url = `${this._gatewayUrl}${ENDPOINT_QLEVER_SHACL}${options?.verbose ? "?verbose=true" : ""}`;
|
|
5545
|
+
const body = new URLSearchParams({ shape });
|
|
5546
|
+
const response = await this._auth.authenticatedFetch(url, {
|
|
5547
|
+
method: "POST",
|
|
5548
|
+
headers: {
|
|
5549
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
5550
|
+
"Accept": accept,
|
|
5551
|
+
"x-project-id": projectId,
|
|
5552
|
+
"cue-project-id": projectId
|
|
5553
|
+
},
|
|
5554
|
+
body
|
|
5555
|
+
});
|
|
5556
|
+
if (!response.ok) {
|
|
5557
|
+
const msg = await response.text().catch(() => "");
|
|
5558
|
+
throw new Error(`SHACL validation failed: ${response.status} ${response.statusText}${msg ? " \u2014 " + msg.slice(0, 200) : ""}`);
|
|
5559
|
+
}
|
|
5560
|
+
return fmt === "turtle" ? response.text() : response.json();
|
|
5561
|
+
}
|
|
5371
5562
|
async getConsumption(projectId) {
|
|
5372
5563
|
const response = await this._auth.authenticatedFetch(
|
|
5373
5564
|
`${this._gatewayUrl}${ENDPOINT_CONSUMPTION}`,
|
|
@@ -7552,19 +7743,20 @@ var CueProjectSchema = class {
|
|
|
7552
7743
|
this._projectId = _projectId;
|
|
7553
7744
|
this._queryCache = _queryCache;
|
|
7554
7745
|
this._graphType = _graphType;
|
|
7555
|
-
this.
|
|
7746
|
+
this._currentLang = language;
|
|
7747
|
+
this._api.setLanguage(language);
|
|
7556
7748
|
this._contentCategories = new CueSignal([]);
|
|
7557
7749
|
this._entityCategories = new CueSignal([]);
|
|
7558
7750
|
this._relationships = new CueSignal([]);
|
|
7559
7751
|
this.availableContentCategories = this._contentCategories.asReadonly();
|
|
7560
7752
|
this.availableEntityCategories = this._entityCategories.asReadonly();
|
|
7561
7753
|
this.availableEntityRelationships = this._relationships.asReadonly();
|
|
7562
|
-
this._load(language).catch(
|
|
7754
|
+
this.ready = this._load(language).catch(
|
|
7563
7755
|
(err) => console.error("[CueProjectSchema] Initial load failed:", err)
|
|
7564
7756
|
);
|
|
7565
7757
|
}
|
|
7566
7758
|
_cache = /* @__PURE__ */ new Map();
|
|
7567
|
-
|
|
7759
|
+
_currentLang;
|
|
7568
7760
|
_contentCategories;
|
|
7569
7761
|
_entityCategories;
|
|
7570
7762
|
_relationships;
|
|
@@ -7574,9 +7766,14 @@ var CueProjectSchema = class {
|
|
|
7574
7766
|
availableEntityCategories;
|
|
7575
7767
|
/** Currently active entity relationship types for the selected language. */
|
|
7576
7768
|
availableEntityRelationships;
|
|
7769
|
+
/**
|
|
7770
|
+
* Resolves when the initial schema load for the constructor language has
|
|
7771
|
+
* completed (or failed). Await this before reading signal values imperatively.
|
|
7772
|
+
*/
|
|
7773
|
+
ready;
|
|
7577
7774
|
/** Returns the currently active language. */
|
|
7578
7775
|
get language() {
|
|
7579
|
-
return this.
|
|
7776
|
+
return this._api.language;
|
|
7580
7777
|
}
|
|
7581
7778
|
/**
|
|
7582
7779
|
* Switch the active language. If the data for this language has already been
|
|
@@ -7584,9 +7781,10 @@ var CueProjectSchema = class {
|
|
|
7584
7781
|
* is triggered.
|
|
7585
7782
|
*/
|
|
7586
7783
|
setLanguage(lang) {
|
|
7587
|
-
if (this.
|
|
7784
|
+
if (this._currentLang === lang)
|
|
7588
7785
|
return;
|
|
7589
|
-
this.
|
|
7786
|
+
this._currentLang = lang;
|
|
7787
|
+
this._api.setLanguage(lang);
|
|
7590
7788
|
this._load(lang).catch(
|
|
7591
7789
|
(err) => console.error("[CueProjectSchema] Language switch failed:", err)
|
|
7592
7790
|
);
|
|
@@ -7596,7 +7794,7 @@ var CueProjectSchema = class {
|
|
|
7596
7794
|
* Useful when the triplestore data has changed.
|
|
7597
7795
|
*/
|
|
7598
7796
|
async refresh() {
|
|
7599
|
-
const lang = this.
|
|
7797
|
+
const lang = this._api.language;
|
|
7600
7798
|
this._cache.delete(lang);
|
|
7601
7799
|
await this._load(lang);
|
|
7602
7800
|
}
|
|
@@ -7622,7 +7820,7 @@ var CueProjectSchema = class {
|
|
|
7622
7820
|
},
|
|
7623
7821
|
(snapshot) => {
|
|
7624
7822
|
this._cache.set(lang, snapshot);
|
|
7625
|
-
if (this.
|
|
7823
|
+
if (this._currentLang === lang)
|
|
7626
7824
|
this._apply(snapshot);
|
|
7627
7825
|
},
|
|
7628
7826
|
this._queryCache
|
|
@@ -7711,7 +7909,9 @@ var CueProjectEntities = class {
|
|
|
7711
7909
|
baseURL;
|
|
7712
7910
|
// ── Internal writable slices ───────────────────────────────────────────────
|
|
7713
7911
|
_entityDetails = new CueSignal({});
|
|
7714
|
-
_entityDocuments = new CueSignal(
|
|
7912
|
+
_entityDocuments = new CueSignal(
|
|
7913
|
+
{}
|
|
7914
|
+
);
|
|
7715
7915
|
_entityRelationships = new CueSignal({});
|
|
7716
7916
|
_entityOSMMap = new CueSignal({});
|
|
7717
7917
|
_osmWKTMap = new CueSignal({});
|
|
@@ -7753,7 +7953,10 @@ var CueProjectEntities = class {
|
|
|
7753
7953
|
this._entityGraph.set(void 0);
|
|
7754
7954
|
this._fetchingOSMIds.clear();
|
|
7755
7955
|
this._fetchEntityGraph().catch(
|
|
7756
|
-
(err) => console.error(
|
|
7956
|
+
(err) => console.error(
|
|
7957
|
+
"[CueProjectEntities] Entity graph fetch failed after reset:",
|
|
7958
|
+
err
|
|
7959
|
+
)
|
|
7757
7960
|
);
|
|
7758
7961
|
}
|
|
7759
7962
|
// ── Public imperative API ──────────────────────────────────────────────────
|
|
@@ -7764,7 +7967,9 @@ var CueProjectEntities = class {
|
|
|
7764
7967
|
* Data is merged into `entityInfoMap` once the SPARQL response arrives.
|
|
7765
7968
|
*/
|
|
7766
7969
|
requestEntityData(uuids, includeMentionCount = false) {
|
|
7767
|
-
const newUUIDs = uuids.filter(
|
|
7970
|
+
const newUUIDs = uuids.filter(
|
|
7971
|
+
(id) => this._entityDetails.get()[id] === void 0
|
|
7972
|
+
);
|
|
7768
7973
|
if (newUUIDs.length === 0)
|
|
7769
7974
|
return;
|
|
7770
7975
|
const values = newUUIDs.map((id) => `r:${id}`).join(" ");
|
|
@@ -7782,7 +7987,9 @@ WHERE {
|
|
|
7782
7987
|
GROUP BY ?id ?mentionCount`;
|
|
7783
7988
|
this._api.sparql(q, this._projectId, this._graphType).then((data) => {
|
|
7784
7989
|
const result = data;
|
|
7785
|
-
const updates = {
|
|
7990
|
+
const updates = {
|
|
7991
|
+
...this._entityDetails.get()
|
|
7992
|
+
};
|
|
7786
7993
|
result.results.bindings.forEach((b) => {
|
|
7787
7994
|
if (!b["id"])
|
|
7788
7995
|
return;
|
|
@@ -7806,7 +8013,9 @@ GROUP BY ?id ?mentionCount`;
|
|
|
7806
8013
|
* query and merged into `entityInfoMap` reactively once it arrives.
|
|
7807
8014
|
*/
|
|
7808
8015
|
async requestEntityLocations(uuids) {
|
|
7809
|
-
const newUUIDs = uuids.filter(
|
|
8016
|
+
const newUUIDs = uuids.filter(
|
|
8017
|
+
(id) => this._entityOSMMap.get()[id] === void 0
|
|
8018
|
+
);
|
|
7810
8019
|
if (newUUIDs.length === 0)
|
|
7811
8020
|
return;
|
|
7812
8021
|
const osmInit = { ...this._entityOSMMap.get() };
|
|
@@ -7842,7 +8051,11 @@ WHERE {
|
|
|
7842
8051
|
}
|
|
7843
8052
|
BIND(REPLACE(STR(?iri), "^.*/([^/]*)$", "$1") AS ?id)
|
|
7844
8053
|
}`;
|
|
7845
|
-
const data = await this._api.sparql(
|
|
8054
|
+
const data = await this._api.sparql(
|
|
8055
|
+
q,
|
|
8056
|
+
this._projectId,
|
|
8057
|
+
this._graphType
|
|
8058
|
+
);
|
|
7846
8059
|
const update = { ...this._entityOSMMap.get() };
|
|
7847
8060
|
data.results.bindings.forEach((b) => {
|
|
7848
8061
|
if (!b["id"] || !b["osm"])
|
|
@@ -7881,7 +8094,10 @@ WHERE {
|
|
|
7881
8094
|
this._fetchIncomingRelationships(iri)
|
|
7882
8095
|
]);
|
|
7883
8096
|
const result = { outgoing, incoming };
|
|
7884
|
-
this._entityRelationships.set({
|
|
8097
|
+
this._entityRelationships.set({
|
|
8098
|
+
...this._entityRelationships.get(),
|
|
8099
|
+
[uuid]: result
|
|
8100
|
+
});
|
|
7885
8101
|
return result;
|
|
7886
8102
|
}
|
|
7887
8103
|
/**
|
|
@@ -7905,11 +8121,111 @@ WHERE {
|
|
|
7905
8121
|
qcy:about ?iri .
|
|
7906
8122
|
BIND(REPLACE(STR(?doc), "^.*/([^/]*)$", "$1") AS ?id)
|
|
7907
8123
|
}`;
|
|
7908
|
-
const data = await this._api.sparql(
|
|
8124
|
+
const data = await this._api.sparql(
|
|
8125
|
+
q,
|
|
8126
|
+
this._projectId,
|
|
8127
|
+
this._graphType
|
|
8128
|
+
);
|
|
7909
8129
|
const ids = data.results.bindings.filter((b) => b["id"] !== void 0).map((b) => b["id"].value);
|
|
7910
8130
|
this._entityDocuments.set({ ...this._entityDocuments.get(), [uuid]: ids });
|
|
7911
8131
|
return ids;
|
|
7912
8132
|
}
|
|
8133
|
+
/**
|
|
8134
|
+
* Fetches all `qcy:EntityCategory` IRIs and their preferred labels for this
|
|
8135
|
+
* project. Uses `api.language` (default `'en'`);
|
|
8136
|
+
* falls back to an untagged label when no match is found.
|
|
8137
|
+
*/
|
|
8138
|
+
async contentCategoriesInProject(orderByOccurences = true) {
|
|
8139
|
+
const language = this._api.language;
|
|
8140
|
+
const q = `PREFIX qcy: <${qaecyPrefixes["qcy"]}>
|
|
8141
|
+
PREFIX skos: <${prefixCC["skos"]}>
|
|
8142
|
+
SELECT ?iri (SAMPLE(?l) AS ?label) ?count
|
|
8143
|
+
WHERE {
|
|
8144
|
+
?iri a qcy:EntityCategory .
|
|
8145
|
+
OPTIONAL { ?iri skos:prefLabel ?lang_label FILTER(LANG(?lang_label) = "${language}") }
|
|
8146
|
+
OPTIONAL { ?iri skos:prefLabel ?no_lang_label }
|
|
8147
|
+
BIND(COALESCE(?lang_label, ?no_lang_label) AS ?l)
|
|
8148
|
+
${orderByOccurences ? "{ SELECT (COUNT(?x) AS ?count) ?iri where { ?x a qcy:CanonicalEntity ; qcy:hasEntityCategory ?iri } GROUP BY ?iri }" : ""}
|
|
8149
|
+
}
|
|
8150
|
+
GROUP BY ?iri ?count
|
|
8151
|
+
ORDER BY ${orderByOccurences ? "DESC(?count)" : "ASC(?label)"}`;
|
|
8152
|
+
const data = await this._api.sparql(
|
|
8153
|
+
q,
|
|
8154
|
+
this._projectId,
|
|
8155
|
+
this._graphType
|
|
8156
|
+
);
|
|
8157
|
+
return data.results.bindings.filter((b) => b["iri"] !== void 0).map((b) => {
|
|
8158
|
+
const count = b["count"] ? parseInt(b["count"].value, 10) : 0;
|
|
8159
|
+
const label = b["label"]?.value ?? b["iri"].value.split("#").at(-1);
|
|
8160
|
+
const labelWithCount = count > 0 ? `${label} (${count})` : label ?? "";
|
|
8161
|
+
return {
|
|
8162
|
+
iri: b["iri"].value,
|
|
8163
|
+
label: labelWithCount
|
|
8164
|
+
};
|
|
8165
|
+
});
|
|
8166
|
+
}
|
|
8167
|
+
async buildSummaryGraph(format) {
|
|
8168
|
+
const q = `PREFIX qcy: <${qaecyPrefixes["qcy"]}>
|
|
8169
|
+
SELECT
|
|
8170
|
+
?sourceCat
|
|
8171
|
+
?predicate
|
|
8172
|
+
?targetCat
|
|
8173
|
+
(COUNT(*) AS ?weight)
|
|
8174
|
+
WHERE {
|
|
8175
|
+
?s a qcy:CanonicalEntity ;
|
|
8176
|
+
qcy:hasEntityCategory ?sourceCat .
|
|
8177
|
+
?o a qcy:CanonicalEntity ;
|
|
8178
|
+
qcy:hasEntityCategory ?targetCat .
|
|
8179
|
+
?s ?predicate ?o .
|
|
8180
|
+
FILTER(isIRI(?s) && isIRI(?o))
|
|
8181
|
+
FILTER(?predicate != qcy:relatedEntity)
|
|
8182
|
+
}
|
|
8183
|
+
GROUP BY ?sourceCat ?predicate ?targetCat
|
|
8184
|
+
ORDER BY DESC(?weight)`;
|
|
8185
|
+
const data = await this._api.sparql(
|
|
8186
|
+
q,
|
|
8187
|
+
this._projectId,
|
|
8188
|
+
this._graphType
|
|
8189
|
+
);
|
|
8190
|
+
const bindings = data.results.bindings.filter(
|
|
8191
|
+
(b) => b["sourceCat"] && b["predicate"] && b["targetCat"]
|
|
8192
|
+
);
|
|
8193
|
+
if (format === "graph") {
|
|
8194
|
+
const irisSet = /* @__PURE__ */ new Set();
|
|
8195
|
+
const relations = [];
|
|
8196
|
+
for (const b of bindings) {
|
|
8197
|
+
const sourceID = b["sourceCat"].value;
|
|
8198
|
+
const predicate = b["predicate"].value;
|
|
8199
|
+
const targetID = b["targetCat"].value;
|
|
8200
|
+
const weight = parseInt(b["weight"].value, 10);
|
|
8201
|
+
irisSet.add(sourceID);
|
|
8202
|
+
irisSet.add(targetID);
|
|
8203
|
+
relations.push({ sourceID, predicate, targetID, weight });
|
|
8204
|
+
}
|
|
8205
|
+
return {
|
|
8206
|
+
entities: Array.from(irisSet).map((iri) => ({ iri })),
|
|
8207
|
+
relations
|
|
8208
|
+
};
|
|
8209
|
+
}
|
|
8210
|
+
if (format === "md") {
|
|
8211
|
+
const ce = CompactExpand.getInstance();
|
|
8212
|
+
const rows = bindings.map((b) => ({
|
|
8213
|
+
src: ce.compactIRI(b["sourceCat"].value),
|
|
8214
|
+
pred: ce.compactIRI(b["predicate"].value),
|
|
8215
|
+
tgt: ce.compactIRI(b["targetCat"].value),
|
|
8216
|
+
weight: parseInt(b["weight"].value, 10)
|
|
8217
|
+
}));
|
|
8218
|
+
if (rows.length === 0)
|
|
8219
|
+
return "(no results)";
|
|
8220
|
+
const maxSrc = Math.max(...rows.map((r) => r.src.length));
|
|
8221
|
+
const maxPred = Math.max(...rows.map((r) => r.pred.length));
|
|
8222
|
+
const maxTgt = Math.max(...rows.map((r) => r.tgt.length));
|
|
8223
|
+
return rows.map(
|
|
8224
|
+
(r) => `${r.src.padEnd(maxSrc)} -> ${r.pred.padEnd(maxPred)} -> ${r.tgt.padEnd(maxTgt)} (${r.weight})`
|
|
8225
|
+
).join("\n");
|
|
8226
|
+
}
|
|
8227
|
+
return data;
|
|
8228
|
+
}
|
|
7913
8229
|
// ── Private helpers ────────────────────────────────────────────────────────
|
|
7914
8230
|
_computeEntityInfoMap() {
|
|
7915
8231
|
const details = this._entityDetails.get();
|
|
@@ -7983,7 +8299,11 @@ WHERE {
|
|
|
7983
8299
|
FILTER(?rel != qcy:relatedEntity)
|
|
7984
8300
|
}
|
|
7985
8301
|
GROUP BY ?rel ?related`;
|
|
7986
|
-
const data = await this._api.sparql(
|
|
8302
|
+
const data = await this._api.sparql(
|
|
8303
|
+
q,
|
|
8304
|
+
this._projectId,
|
|
8305
|
+
this._graphType
|
|
8306
|
+
);
|
|
7987
8307
|
const result = [];
|
|
7988
8308
|
const detailsUpdate = { ...this._entityDetails.get() };
|
|
7989
8309
|
data.results.bindings.forEach((b) => {
|
|
@@ -8017,7 +8337,11 @@ WHERE {
|
|
|
8017
8337
|
FILTER(?rel != qcy:relatedEntity)
|
|
8018
8338
|
}
|
|
8019
8339
|
GROUP BY ?rel ?relating`;
|
|
8020
|
-
const data = await this._api.sparql(
|
|
8340
|
+
const data = await this._api.sparql(
|
|
8341
|
+
q,
|
|
8342
|
+
this._projectId,
|
|
8343
|
+
this._graphType
|
|
8344
|
+
);
|
|
8021
8345
|
const result = [];
|
|
8022
8346
|
const detailsUpdate = { ...this._entityDetails.get() };
|
|
8023
8347
|
data.results.bindings.forEach((b) => {
|
|
@@ -8052,7 +8376,11 @@ GROUP BY ?e1Cat ?e2Cat`;
|
|
|
8052
8376
|
await staleWhileRevalidate(
|
|
8053
8377
|
q,
|
|
8054
8378
|
async () => {
|
|
8055
|
-
const data = await this._api.sparql(
|
|
8379
|
+
const data = await this._api.sparql(
|
|
8380
|
+
q,
|
|
8381
|
+
this._projectId,
|
|
8382
|
+
this._graphType
|
|
8383
|
+
);
|
|
8056
8384
|
const entities = [];
|
|
8057
8385
|
const relations = [];
|
|
8058
8386
|
data.results.bindings.forEach((b) => {
|
|
@@ -8109,7 +8437,11 @@ SELECT * WHERE {
|
|
|
8109
8437
|
?s geo:hasGeometry/geo:asWKT ?wkt
|
|
8110
8438
|
}
|
|
8111
8439
|
}`;
|
|
8112
|
-
const data = await this._api.sparql(
|
|
8440
|
+
const data = await this._api.sparql(
|
|
8441
|
+
q,
|
|
8442
|
+
this._projectId,
|
|
8443
|
+
this._graphType
|
|
8444
|
+
);
|
|
8113
8445
|
const update = { ...this._osmWKTMap.get() };
|
|
8114
8446
|
data.results.bindings.forEach((b) => {
|
|
8115
8447
|
if (!b["s"] || !b["wkt"])
|
|
@@ -8129,13 +8461,14 @@ var CueProjectDocuments = class {
|
|
|
8129
8461
|
this._queryCache = _queryCache;
|
|
8130
8462
|
this._graphType = _graphType;
|
|
8131
8463
|
this.baseURL = `${rdfBase}${_projectId}/`;
|
|
8132
|
-
this.
|
|
8464
|
+
this._currentLang = language ?? this._api.language;
|
|
8133
8465
|
this.documentInfoMap = this._documentInfoMap.asReadonly();
|
|
8134
8466
|
this.projectDocumentsData = this._projectDocumentsData.asReadonly();
|
|
8135
8467
|
}
|
|
8136
8468
|
/** Full RDF base URL for this project, e.g. `https://cue.qaecy.com/r/{pid}/` */
|
|
8137
8469
|
baseURL;
|
|
8138
|
-
|
|
8470
|
+
/** Tracks the language for which `_documentInfoMap` is currently populated. */
|
|
8471
|
+
_currentLang;
|
|
8139
8472
|
_documentInfoMap = new CueSignal({});
|
|
8140
8473
|
_projectDocumentsData = new CueSignal({
|
|
8141
8474
|
duplicateCount: 0,
|
|
@@ -8165,9 +8498,10 @@ var CueProjectDocuments = class {
|
|
|
8165
8498
|
* `requestDocumentData()` call.
|
|
8166
8499
|
*/
|
|
8167
8500
|
setLanguage(lang) {
|
|
8168
|
-
if (this.
|
|
8501
|
+
if (this._currentLang === lang)
|
|
8169
8502
|
return;
|
|
8170
|
-
this.
|
|
8503
|
+
this._currentLang = lang;
|
|
8504
|
+
this._api.setLanguage(lang);
|
|
8171
8505
|
this._documentInfoMap.set({});
|
|
8172
8506
|
}
|
|
8173
8507
|
// ── Public API ─────────────────────────────────────────────────────────────
|
|
@@ -8208,8 +8542,128 @@ var CueProjectDocuments = class {
|
|
|
8208
8542
|
const newUUIDs = uuids.filter((id) => this._documentInfoMap.get()[id] === void 0);
|
|
8209
8543
|
if (newUUIDs.length === 0)
|
|
8210
8544
|
return;
|
|
8211
|
-
|
|
8212
|
-
|
|
8545
|
+
this._fetchDocumentInfoBatch(newUUIDs).catch(
|
|
8546
|
+
(err) => console.error("[CueProjectDocuments] requestDocumentData failed:", err)
|
|
8547
|
+
);
|
|
8548
|
+
}
|
|
8549
|
+
/**
|
|
8550
|
+
* Promise-based alternative to {@link requestDocumentData} for non-reactive contexts.
|
|
8551
|
+
*
|
|
8552
|
+
* Resolves with the `DocumentInfo` entries for every requested UUID once the
|
|
8553
|
+
* SPARQL response arrives. UUIDs already present in the cache are returned
|
|
8554
|
+
* immediately without a network request. The result is also written into
|
|
8555
|
+
* `documentInfoMap` so reactive consumers stay in sync.
|
|
8556
|
+
*
|
|
8557
|
+
* UUIDs not found in the triplestore are omitted from the returned map.
|
|
8558
|
+
*
|
|
8559
|
+
* @example
|
|
8560
|
+
* ```ts
|
|
8561
|
+
* const docs = await cueProjectDocs.fetchDocumentData(['uuid1', 'uuid2']);
|
|
8562
|
+
* console.log(docs['uuid1'].subject);
|
|
8563
|
+
* ```
|
|
8564
|
+
*/
|
|
8565
|
+
async fetchDocumentData(uuids) {
|
|
8566
|
+
const current = this._documentInfoMap.get();
|
|
8567
|
+
const newUUIDs = uuids.filter((id) => current[id] === void 0);
|
|
8568
|
+
if (newUUIDs.length > 0) {
|
|
8569
|
+
await this._fetchDocumentInfoBatch(newUUIDs);
|
|
8570
|
+
}
|
|
8571
|
+
const updated = this._documentInfoMap.get();
|
|
8572
|
+
return Object.fromEntries(
|
|
8573
|
+
uuids.filter((id) => updated[id] !== void 0).map((id) => [id, updated[id]])
|
|
8574
|
+
);
|
|
8575
|
+
}
|
|
8576
|
+
/**
|
|
8577
|
+
* Fetches a lightweight document metadata shape (id/path/suffix/size) for
|
|
8578
|
+
* the given UUIDs and merges the results into `documentInfoMap`.
|
|
8579
|
+
*
|
|
8580
|
+
* This is useful for list/table contexts that do not need language-tagged
|
|
8581
|
+
* fields (`subject`, `summary`) or category/tag enrichment.
|
|
8582
|
+
*
|
|
8583
|
+
* UUIDs already present in `documentInfoMap` are skipped.
|
|
8584
|
+
*/
|
|
8585
|
+
async fetchDocumentDataSimple(uuids) {
|
|
8586
|
+
const current = this._documentInfoMap.get();
|
|
8587
|
+
const newUUIDs = uuids.filter((id) => current[id] === void 0);
|
|
8588
|
+
if (newUUIDs.length > 0) {
|
|
8589
|
+
await this._fetchSimpleDocumentInfoBatch(newUUIDs);
|
|
8590
|
+
}
|
|
8591
|
+
const updated = this._documentInfoMap.get();
|
|
8592
|
+
return Object.fromEntries(
|
|
8593
|
+
uuids.filter((id) => updated[id] !== void 0).map((id) => [id, updated[id]])
|
|
8594
|
+
);
|
|
8595
|
+
}
|
|
8596
|
+
/**
|
|
8597
|
+
* Returns the alternative representations of the given document UUID.
|
|
8598
|
+
*
|
|
8599
|
+
* Alternative representations are derived artefacts stored under
|
|
8600
|
+
* `qcy:alternativeRepresentation` in the triplestore — for example a
|
|
8601
|
+
* `.fragments` BIM tile derived from an `.ifc` source file.
|
|
8602
|
+
*
|
|
8603
|
+
* The returned `DocumentInfo` entries are also merged into
|
|
8604
|
+
* `documentInfoMap` so reactive consumers stay in sync.
|
|
8605
|
+
*
|
|
8606
|
+
* @example
|
|
8607
|
+
* ```ts
|
|
8608
|
+
* const alts = await docs.fetchAlternativeRepresentations('abc-123');
|
|
8609
|
+
* // alts[0].suffix => '.fragments'
|
|
8610
|
+
* ```
|
|
8611
|
+
*/
|
|
8612
|
+
async fetchAlternativeRepresentations(uuid) {
|
|
8613
|
+
const q = `PREFIX qcy: <${qaecyPrefixes["qcy"]}>
|
|
8614
|
+
PREFIX r: <${this.baseURL}>
|
|
8615
|
+
SELECT ?altId ?contentIRI ?suffix ?rrp
|
|
8616
|
+
WHERE {
|
|
8617
|
+
r:${uuid} qcy:alternativeRepresentation ?contentIRI .
|
|
8618
|
+
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?altId)
|
|
8619
|
+
?contentIRI qcy:hasFileLocation ?loc .
|
|
8620
|
+
?loc qcy:suffix ?suffix .
|
|
8621
|
+
OPTIONAL { ?loc qcy:remoteRelativePath ?rrp }
|
|
8622
|
+
}`;
|
|
8623
|
+
const data = await this._api.sparql(q, this._projectId, this._graphType);
|
|
8624
|
+
const updates = { ...this._documentInfoMap.get() };
|
|
8625
|
+
const alts = [];
|
|
8626
|
+
data.results.bindings.forEach((b) => {
|
|
8627
|
+
if (!b["altId"] || !b["contentIRI"])
|
|
8628
|
+
return;
|
|
8629
|
+
const id = b["altId"].value;
|
|
8630
|
+
const info = {
|
|
8631
|
+
id,
|
|
8632
|
+
contentIRI: b["contentIRI"].value,
|
|
8633
|
+
path: "",
|
|
8634
|
+
suffix: b["suffix"]?.value ?? "",
|
|
8635
|
+
size: 0,
|
|
8636
|
+
tags: [],
|
|
8637
|
+
categories: [],
|
|
8638
|
+
remoteRelativePath: b["rrp"]?.value
|
|
8639
|
+
};
|
|
8640
|
+
updates[id] = info;
|
|
8641
|
+
alts.push(info);
|
|
8642
|
+
});
|
|
8643
|
+
this._documentInfoMap.set(updates);
|
|
8644
|
+
return alts;
|
|
8645
|
+
}
|
|
8646
|
+
/**
|
|
8647
|
+
* Returns a single arbitrary file path from the project's triplestore.
|
|
8648
|
+
* Useful for pre-filling path-based query inputs with a realistic example.
|
|
8649
|
+
*/
|
|
8650
|
+
async randomFilePath() {
|
|
8651
|
+
const q = `PREFIX qcy: <${qaecyPrefixes["qcy"]}>
|
|
8652
|
+
SELECT ?path
|
|
8653
|
+
WHERE {
|
|
8654
|
+
?fl a qcy:FileLocation ;
|
|
8655
|
+
qcy:filePath ?path .
|
|
8656
|
+
}
|
|
8657
|
+
LIMIT 1`;
|
|
8658
|
+
const data = await this._api.sparql(q, this._projectId, this._graphType);
|
|
8659
|
+
return data.results.bindings[0]?.["path"]?.value ?? null;
|
|
8660
|
+
}
|
|
8661
|
+
// ── Private helpers ────────────────────────────────────────────────────────
|
|
8662
|
+
/** Executes the document-info SPARQL query for the given UUIDs, merges results
|
|
8663
|
+
* into `documentInfoMap`, and returns the newly fetched entries. */
|
|
8664
|
+
async _fetchDocumentInfoBatch(uuids) {
|
|
8665
|
+
const values = uuids.map((id) => `r:${id}`).join(" ");
|
|
8666
|
+
const lang = this._api.language;
|
|
8213
8667
|
const q = `PREFIX qcy: <${qaecyPrefixes["qcy"]}>
|
|
8214
8668
|
PREFIX r: <${this.baseURL}>
|
|
8215
8669
|
SELECT ?id ?contentIRI ?suffix ?size ?subject ?summary
|
|
@@ -8237,32 +8691,73 @@ WHERE {
|
|
|
8237
8691
|
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?id)
|
|
8238
8692
|
}
|
|
8239
8693
|
GROUP BY ?id ?contentIRI ?suffix ?size ?subject ?summary`;
|
|
8240
|
-
this._api.sparql(q, this._projectId)
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
})
|
|
8262
|
-
|
|
8263
|
-
|
|
8694
|
+
const result = await this._api.sparql(q, this._projectId);
|
|
8695
|
+
const updates = { ...this._documentInfoMap.get() };
|
|
8696
|
+
const fetched = {};
|
|
8697
|
+
result.results.bindings.forEach((b) => {
|
|
8698
|
+
if (!b["id"] || !b["contentIRI"])
|
|
8699
|
+
return;
|
|
8700
|
+
const id = b["id"].value;
|
|
8701
|
+
const info = {
|
|
8702
|
+
id,
|
|
8703
|
+
contentIRI: b["contentIRI"].value,
|
|
8704
|
+
path: b["path"]?.value ?? "",
|
|
8705
|
+
suffix: b["suffix"]?.value ?? "",
|
|
8706
|
+
size: b["size"] ? parseInt(b["size"].value, 10) : 0,
|
|
8707
|
+
tags: b["tags"]?.value?.split(";").filter(Boolean) ?? [],
|
|
8708
|
+
categories: b["categories"]?.value?.split(";").filter(Boolean) ?? [],
|
|
8709
|
+
subject: b["subject"]?.value,
|
|
8710
|
+
summary: b["summary"]?.value,
|
|
8711
|
+
providerId: b["pid"]?.value
|
|
8712
|
+
};
|
|
8713
|
+
updates[id] = info;
|
|
8714
|
+
fetched[id] = info;
|
|
8715
|
+
});
|
|
8716
|
+
this._documentInfoMap.set(updates);
|
|
8717
|
+
return fetched;
|
|
8718
|
+
}
|
|
8719
|
+
/** Executes a reduced document-info query (id/path/suffix/size only), merges
|
|
8720
|
+
* into `documentInfoMap`, and returns newly fetched entries. */
|
|
8721
|
+
async _fetchSimpleDocumentInfoBatch(uuids) {
|
|
8722
|
+
const values = uuids.map((id) => `r:${id}`).join(" ");
|
|
8723
|
+
const q = `PREFIX qcy: <${qaecyPrefixes["qcy"]}>
|
|
8724
|
+
PREFIX r: <${this.baseURL}>
|
|
8725
|
+
SELECT ?id ?contentIRI ?suffix ?size (SAMPLE(?fp) AS ?path)
|
|
8726
|
+
WHERE {
|
|
8727
|
+
VALUES ?contentIRI { ${values} }
|
|
8728
|
+
?contentIRI qcy:sizeBytes ?size ;
|
|
8729
|
+
qcy:hasFileLocation ?loc .
|
|
8730
|
+
?loc qcy:filePath ?fp ;
|
|
8731
|
+
qcy:suffix ?suffix .
|
|
8732
|
+
BIND(REPLACE(STR(?contentIRI), "^.*/([^/]*)$", "$1") AS ?id)
|
|
8733
|
+
}
|
|
8734
|
+
GROUP BY ?id ?contentIRI ?suffix ?size`;
|
|
8735
|
+
const result = await this._api.sparql(q, this._projectId, this._graphType);
|
|
8736
|
+
const updates = { ...this._documentInfoMap.get() };
|
|
8737
|
+
const fetched = {};
|
|
8738
|
+
result.results.bindings.forEach((b) => {
|
|
8739
|
+
if (!b["id"])
|
|
8740
|
+
return;
|
|
8741
|
+
const id = b["id"].value;
|
|
8742
|
+
const existing = updates[id];
|
|
8743
|
+
const info = {
|
|
8744
|
+
id,
|
|
8745
|
+
contentIRI: b["contentIRI"]?.value ?? existing?.contentIRI ?? id,
|
|
8746
|
+
path: b["path"]?.value ?? existing?.path ?? id,
|
|
8747
|
+
suffix: b["suffix"]?.value ?? existing?.suffix ?? "",
|
|
8748
|
+
size: b["size"] ? parseInt(b["size"].value, 10) : existing?.size ?? 0,
|
|
8749
|
+
tags: existing?.tags ?? [],
|
|
8750
|
+
categories: existing?.categories ?? [],
|
|
8751
|
+
subject: existing?.subject,
|
|
8752
|
+
summary: existing?.summary,
|
|
8753
|
+
providerId: existing?.providerId
|
|
8754
|
+
};
|
|
8755
|
+
updates[id] = info;
|
|
8756
|
+
fetched[id] = info;
|
|
8757
|
+
});
|
|
8758
|
+
this._documentInfoMap.set(updates);
|
|
8759
|
+
return fetched;
|
|
8264
8760
|
}
|
|
8265
|
-
// ── Private helpers ────────────────────────────────────────────────────────
|
|
8266
8761
|
async _fetchDocumentsBySuffix() {
|
|
8267
8762
|
return this._runDocumentsBySuffixQuery(this._buildDocumentsBySuffixQuery());
|
|
8268
8763
|
}
|
|
@@ -8364,6 +8859,7 @@ var CueProjectView = class {
|
|
|
8364
8859
|
this.availableContentCategories = this.schema.availableContentCategories;
|
|
8365
8860
|
this.availableEntityCategories = this.schema.availableEntityCategories;
|
|
8366
8861
|
this.availableEntityRelationships = this.schema.availableEntityRelationships;
|
|
8862
|
+
this.schemaReady = this.schema.ready;
|
|
8367
8863
|
this.entityInfoMap = this.entities.entityInfoMap;
|
|
8368
8864
|
this.entityGraph = this.entities.entityGraph;
|
|
8369
8865
|
this.documentInfoMap = this.documents.documentInfoMap;
|
|
@@ -8384,6 +8880,11 @@ var CueProjectView = class {
|
|
|
8384
8880
|
availableEntityCategories;
|
|
8385
8881
|
/** Available entity relationship types. Auto-fetched on init. */
|
|
8386
8882
|
availableEntityRelationships;
|
|
8883
|
+
/**
|
|
8884
|
+
* Resolves when the initial schema load has completed. Await before reading
|
|
8885
|
+
* schema signal values imperatively.
|
|
8886
|
+
*/
|
|
8887
|
+
schemaReady;
|
|
8387
8888
|
/** Merged per-entity detail map. Populated lazily via `requestEntityData()` etc. */
|
|
8388
8889
|
entityInfoMap;
|
|
8389
8890
|
/** Project-level entity co-occurrence graph. Fetched once on init. */
|
|
@@ -10191,10 +10692,14 @@ var Cue = class _Cue {
|
|
|
10191
10692
|
profile;
|
|
10192
10693
|
privileges;
|
|
10193
10694
|
cache;
|
|
10695
|
+
storage;
|
|
10194
10696
|
_app;
|
|
10195
10697
|
_endpoints;
|
|
10196
10698
|
_isEmulator;
|
|
10699
|
+
_storageRaw;
|
|
10700
|
+
_storageProcessed;
|
|
10197
10701
|
_gis = null;
|
|
10702
|
+
_projectDocuments = /* @__PURE__ */ new Map();
|
|
10198
10703
|
/**
|
|
10199
10704
|
* Reactive GIS service. Lazily constructed on first access.
|
|
10200
10705
|
*
|
|
@@ -10238,7 +10743,26 @@ var Cue = class _Cue {
|
|
|
10238
10743
|
});
|
|
10239
10744
|
this.auth = new CueAuth(this._app, this._isEmulator, this._endpoints);
|
|
10240
10745
|
this.projects = new CueProjects(this.auth, this._app, this._isEmulator, this._endpoints);
|
|
10746
|
+
this._storageRaw = (0, import_storage5.getStorage)(this._app, BUCKET_RAW2);
|
|
10747
|
+
this._storageProcessed = (0, import_storage5.getStorage)(this._app, BUCKET_PROCESSED2);
|
|
10748
|
+
const storagePublic = (0, import_storage5.getStorage)(this._app, BUCKET_PUBLIC2);
|
|
10749
|
+
const storageLogs = (0, import_storage5.getStorage)(this._app, BUCKET_LOGS2);
|
|
10750
|
+
const storageChatSessions = (0, import_storage5.getStorage)(this._app, BUCKET_CHAT_SESSIONS2);
|
|
10751
|
+
const storagePersistence = (0, import_storage5.getStorage)(this._app, BUCKET_PERSISTENCE2);
|
|
10752
|
+
if (this._isEmulator) {
|
|
10753
|
+
(0, import_storage5.connectStorageEmulator)(this._storageRaw, this._endpoints.storageEmulatorHost, this._endpoints.storageEmulatorPort);
|
|
10754
|
+
(0, import_storage5.connectStorageEmulator)(this._storageProcessed, this._endpoints.storageEmulatorHost, this._endpoints.storageEmulatorPort);
|
|
10755
|
+
}
|
|
10241
10756
|
this.api = this._buildApi(this.projects);
|
|
10757
|
+
const blob = new CueBlobStorage({
|
|
10758
|
+
storageRaw: this._storageRaw,
|
|
10759
|
+
storageProcessed: this._storageProcessed,
|
|
10760
|
+
storagePublic,
|
|
10761
|
+
storageLogs,
|
|
10762
|
+
storageChatSessions,
|
|
10763
|
+
storagePersistence
|
|
10764
|
+
});
|
|
10765
|
+
this.storage = new CueStorage(blob);
|
|
10242
10766
|
this.profile = new CueProfile(
|
|
10243
10767
|
this.auth,
|
|
10244
10768
|
this._app,
|
|
@@ -10246,7 +10770,6 @@ var Cue = class _Cue {
|
|
|
10246
10770
|
this._endpoints.gatewayUrl
|
|
10247
10771
|
);
|
|
10248
10772
|
this.privileges = new CuePrivileges(this.auth.isSuperAdmin);
|
|
10249
|
-
const storagePersistence = (0, import_storage5.getStorage)(this._app, BUCKET_PERSISTENCE2);
|
|
10250
10773
|
if (this._isEmulator) {
|
|
10251
10774
|
(0, import_storage5.connectStorageEmulator)(storagePersistence, this._endpoints.storageEmulatorHost, this._endpoints.storageEmulatorPort);
|
|
10252
10775
|
}
|
|
@@ -10294,16 +10817,20 @@ var Cue = class _Cue {
|
|
|
10294
10817
|
const instance = Object.create(_Cue.prototype);
|
|
10295
10818
|
const privileges = new CuePrivileges(auth.isSuperAdmin);
|
|
10296
10819
|
const cache = new CueCache(storagePersistence);
|
|
10820
|
+
const storage = new CueStorage(blob);
|
|
10297
10821
|
Object.assign(instance, {
|
|
10298
10822
|
_app: app,
|
|
10299
10823
|
_endpoints: endpoints,
|
|
10300
10824
|
_isEmulator: env === "emulator",
|
|
10825
|
+
_storageRaw: storageRaw,
|
|
10826
|
+
_storageProcessed: storageProcessed,
|
|
10301
10827
|
auth,
|
|
10302
10828
|
api,
|
|
10303
10829
|
projects,
|
|
10304
10830
|
profile,
|
|
10305
10831
|
privileges,
|
|
10306
|
-
cache
|
|
10832
|
+
cache,
|
|
10833
|
+
storage
|
|
10307
10834
|
});
|
|
10308
10835
|
return instance;
|
|
10309
10836
|
}
|
|
@@ -10336,27 +10863,105 @@ var Cue = class _Cue {
|
|
|
10336
10863
|
};
|
|
10337
10864
|
return new CueProjectView(this.api, projectId, { ...opts, queryCache });
|
|
10338
10865
|
}
|
|
10866
|
+
/**
|
|
10867
|
+
* Creates a `CueProjectEntities` instance for the given project, with the
|
|
10868
|
+
* SDK query cache wired automatically.
|
|
10869
|
+
*
|
|
10870
|
+
* Prefer this over `new CueProjectEntities(cue.api, projectId)` — it avoids
|
|
10871
|
+
* the manual cache setup and keeps the instance bound to the correct API.
|
|
10872
|
+
*
|
|
10873
|
+
* @example
|
|
10874
|
+
* ```ts
|
|
10875
|
+
* const entities = cue.createProjectEntities('my-project');
|
|
10876
|
+
* entities.requestEntityData(['uuid1']);
|
|
10877
|
+
* const info = entities.entityInfoMap.get()['uuid1'];
|
|
10878
|
+
*
|
|
10879
|
+
* // Promise-based (no signal polling needed):
|
|
10880
|
+
* const graph = await entities.buildSummaryGraph('graph');
|
|
10881
|
+
* ```
|
|
10882
|
+
*/
|
|
10883
|
+
createProjectEntities(projectId, opts) {
|
|
10884
|
+
const queryCache = opts?.queryCache ?? {
|
|
10885
|
+
get: (key) => this.cache.getQueryCache(projectId, key).then((entry) => entry?.results),
|
|
10886
|
+
set: (key, data) => this.cache.setQueryCache(projectId, key, { query: key, results: data })
|
|
10887
|
+
};
|
|
10888
|
+
return new CueProjectEntities(
|
|
10889
|
+
this.api,
|
|
10890
|
+
projectId,
|
|
10891
|
+
opts?.rdfBase,
|
|
10892
|
+
queryCache,
|
|
10893
|
+
opts?.graphType
|
|
10894
|
+
);
|
|
10895
|
+
}
|
|
10896
|
+
/**
|
|
10897
|
+
* Creates a `CueProjectDocuments` instance for the given project, with the
|
|
10898
|
+
* SDK query cache wired automatically.
|
|
10899
|
+
*
|
|
10900
|
+
* Prefer this over `new CueProjectDocuments(cue.api, projectId)` — it avoids
|
|
10901
|
+
* the manual cache setup and keeps the instance bound to the correct API.
|
|
10902
|
+
*
|
|
10903
|
+
* @example
|
|
10904
|
+
* ```ts
|
|
10905
|
+
* const docs = cue.createProjectDocuments('my-project');
|
|
10906
|
+
* await docs.fetchOverview();
|
|
10907
|
+
* const data = await docs.fetchDocumentData(['uuid1', 'uuid2']);
|
|
10908
|
+
* ```
|
|
10909
|
+
*/
|
|
10910
|
+
createProjectDocuments(projectId, opts) {
|
|
10911
|
+
const hasCustomOptions = opts?.language !== void 0 || opts?.rdfBase !== void 0 || opts?.graphType !== void 0 || opts?.queryCache !== void 0;
|
|
10912
|
+
if (!hasCustomOptions) {
|
|
10913
|
+
const existing = this._projectDocuments.get(projectId);
|
|
10914
|
+
if (existing) {
|
|
10915
|
+
existing.setLanguage(this.api.language);
|
|
10916
|
+
return existing;
|
|
10917
|
+
}
|
|
10918
|
+
const queryCache2 = {
|
|
10919
|
+
get: (key) => this.cache.getQueryCache(projectId, key).then((entry) => entry?.results),
|
|
10920
|
+
set: (key, data) => this.cache.setQueryCache(projectId, key, { query: key, results: data })
|
|
10921
|
+
};
|
|
10922
|
+
const docs = new CueProjectDocuments(
|
|
10923
|
+
this.api,
|
|
10924
|
+
projectId,
|
|
10925
|
+
this.api.language,
|
|
10926
|
+
void 0,
|
|
10927
|
+
queryCache2,
|
|
10928
|
+
void 0
|
|
10929
|
+
);
|
|
10930
|
+
this._projectDocuments.set(projectId, docs);
|
|
10931
|
+
return docs;
|
|
10932
|
+
}
|
|
10933
|
+
const queryCache = opts?.queryCache ?? {
|
|
10934
|
+
get: (key) => this.cache.getQueryCache(projectId, key).then((entry) => entry?.results),
|
|
10935
|
+
set: (key, data) => this.cache.setQueryCache(projectId, key, { query: key, results: data })
|
|
10936
|
+
};
|
|
10937
|
+
return new CueProjectDocuments(
|
|
10938
|
+
this.api,
|
|
10939
|
+
projectId,
|
|
10940
|
+
opts?.language ?? this.api.language,
|
|
10941
|
+
opts?.rdfBase,
|
|
10942
|
+
queryCache,
|
|
10943
|
+
opts?.graphType
|
|
10944
|
+
);
|
|
10945
|
+
}
|
|
10339
10946
|
};
|
|
10340
10947
|
|
|
10341
10948
|
// libs/js/cue-sdk/src/lib/cue-node.ts
|
|
10342
|
-
var
|
|
10949
|
+
var import_storage8 = require("firebase/storage");
|
|
10343
10950
|
var CueNode = class extends Cue {
|
|
10344
10951
|
constructor(config) {
|
|
10345
10952
|
super(config);
|
|
10346
10953
|
}
|
|
10347
10954
|
_buildApi(projects) {
|
|
10348
|
-
const storageChatSessions = (0,
|
|
10349
|
-
const storageLogs = (0,
|
|
10350
|
-
const storageRaw =
|
|
10351
|
-
const storagePersistence = (0,
|
|
10352
|
-
const storageProcessed =
|
|
10353
|
-
const storagePublic = (0,
|
|
10955
|
+
const storageChatSessions = (0, import_storage8.getStorage)(this._app, BUCKET_CHAT_SESSIONS2);
|
|
10956
|
+
const storageLogs = (0, import_storage8.getStorage)(this._app, BUCKET_LOGS2);
|
|
10957
|
+
const storageRaw = this._storageRaw;
|
|
10958
|
+
const storagePersistence = (0, import_storage8.getStorage)(this._app, BUCKET_PERSISTENCE2);
|
|
10959
|
+
const storageProcessed = this._storageProcessed;
|
|
10960
|
+
const storagePublic = (0, import_storage8.getStorage)(this._app, BUCKET_PUBLIC2);
|
|
10354
10961
|
if (this._isEmulator) {
|
|
10355
10962
|
const storageHost = this._endpoints.storageEmulatorHost;
|
|
10356
10963
|
const storagePort = this._endpoints.storageEmulatorPort;
|
|
10357
|
-
(0,
|
|
10358
|
-
(0, import_storage6.connectStorageEmulator)(storageProcessed, storageHost, storagePort);
|
|
10359
|
-
(0, import_storage6.connectStorageEmulator)(storagePublic, storageHost, storagePort);
|
|
10964
|
+
(0, import_storage8.connectStorageEmulator)(storagePublic, storageHost, storagePort);
|
|
10360
10965
|
}
|
|
10361
10966
|
const blob = new CueBlobStorage({
|
|
10362
10967
|
storageChatSessions,
|
|
@@ -10519,21 +11124,21 @@ async function compareHandler(options) {
|
|
|
10519
11124
|
}
|
|
10520
11125
|
|
|
10521
11126
|
// apps/desktop/cue-cli/src/helpers/get-files-containing-substring.ts
|
|
10522
|
-
var
|
|
11127
|
+
var import_storage9 = require("firebase/storage");
|
|
10523
11128
|
var import_path2 = require("path");
|
|
10524
11129
|
var import_promises = require("fs/promises");
|
|
10525
11130
|
async function getFilesContainingSubstring(bucket, subDir = "", subString = "") {
|
|
10526
11131
|
const firebase = CueFirebase.getInstance();
|
|
10527
11132
|
const storage = bucket === "raw" ? firebase.storageRaw : firebase.storageProcessed;
|
|
10528
11133
|
console.log("Fetching files from storage bucket:", bucket, "in subdir:", subDir, "containing substring:", subString);
|
|
10529
|
-
const listResult = await (0,
|
|
11134
|
+
const listResult = await (0, import_storage9.listAll)((0, import_storage9.ref)(storage, subDir));
|
|
10530
11135
|
const outputDir = (0, import_path2.join)(process.cwd(), "downloaded_blobs", bucket, subDir);
|
|
10531
11136
|
await (0, import_promises.mkdir)(outputDir, { recursive: true });
|
|
10532
11137
|
for (const fileRef of listResult.items) {
|
|
10533
11138
|
console.log(fileRef.name);
|
|
10534
11139
|
if (subDir && !fileRef.name.includes(subString))
|
|
10535
11140
|
continue;
|
|
10536
|
-
const bytes = await (0,
|
|
11141
|
+
const bytes = await (0, import_storage9.getBytes)(fileRef);
|
|
10537
11142
|
const outputPath = (0, import_path2.join)(outputDir, fileRef.name);
|
|
10538
11143
|
await (0, import_promises.writeFile)(outputPath, Buffer.from(bytes));
|
|
10539
11144
|
console.log(`Downloaded ${fileRef.name} to ${outputPath} \u2705`);
|
|
@@ -10927,16 +11532,16 @@ async function dumpHandler(options) {
|
|
|
10927
11532
|
}
|
|
10928
11533
|
|
|
10929
11534
|
// apps/desktop/cue-cli/src/helpers/repair-remote-ttl.ts
|
|
10930
|
-
var
|
|
11535
|
+
var import_storage10 = require("firebase/storage");
|
|
10931
11536
|
async function repairRemoteTTL(space, subString, regex, substituteString) {
|
|
10932
11537
|
const firebase = CueFirebase.getInstance();
|
|
10933
11538
|
const storage = firebase.storageProcessed;
|
|
10934
11539
|
console.log("Fetching files from storage bucket 'triples' containing substring:", subString);
|
|
10935
|
-
const listResult = await (0,
|
|
11540
|
+
const listResult = await (0, import_storage10.listAll)((0, import_storage10.ref)(storage, `${space}/triples`));
|
|
10936
11541
|
for (const fileRef of listResult.items) {
|
|
10937
11542
|
if (subString && !fileRef.name.match(subString))
|
|
10938
11543
|
continue;
|
|
10939
|
-
const stream = await (0,
|
|
11544
|
+
const stream = await (0, import_storage10.getStream)(fileRef);
|
|
10940
11545
|
const reader = stream.getReader();
|
|
10941
11546
|
const chunks = [];
|
|
10942
11547
|
let done = false;
|
|
@@ -10960,13 +11565,13 @@ async function repairRemoteTTL(space, subString, regex, substituteString) {
|
|
|
10960
11565
|
const buffer = Buffer.from(fileContent, "utf8");
|
|
10961
11566
|
let existingMetadata = {};
|
|
10962
11567
|
try {
|
|
10963
|
-
existingMetadata = await (0,
|
|
11568
|
+
existingMetadata = await (0, import_storage10.getMetadata)(fileRef);
|
|
10964
11569
|
} catch (err) {
|
|
10965
11570
|
console.warn(`Could not fetch metadata for ${fileRef.name}, proceeding with default.`);
|
|
10966
11571
|
}
|
|
10967
11572
|
const customMetadata = { ...existingMetadata.customMetadata || {}, stored: "False" };
|
|
10968
11573
|
const metadata = { customMetadata };
|
|
10969
|
-
await (0,
|
|
11574
|
+
await (0, import_storage10.uploadBytesResumable)((0, import_storage10.ref)(storage, `${space}/triples/${fileRef.name}`), buffer, metadata);
|
|
10970
11575
|
console.log(`Fixed ${fileRef.name} \u2705`);
|
|
10971
11576
|
} else {
|
|
10972
11577
|
console.log(`No changes for ${fileRef.name}`);
|
|
@@ -11201,10 +11806,17 @@ async function syncHandler(options) {
|
|
|
11201
11806
|
process.exit(0);
|
|
11202
11807
|
} catch (err) {
|
|
11203
11808
|
const msg = err instanceof Error ? err.message : String(err);
|
|
11809
|
+
const cause = err instanceof Error ? err.cause : void 0;
|
|
11810
|
+
const causeCode = cause instanceof Error ? cause.code : void 0;
|
|
11811
|
+
const causeMsg = cause instanceof Error ? cause.message : void 0;
|
|
11812
|
+
const isTimeout = causeCode === "UND_ERR_HEADERS_TIMEOUT" || causeCode === "UND_ERR_BODY_TIMEOUT" || causeCode === "UND_ERR_CONNECT_TIMEOUT" || causeMsg?.includes("Timeout") || msg.includes("fetch failed");
|
|
11204
11813
|
if (msg.includes("GRAPH_UNAVAILABLE")) {
|
|
11205
11814
|
console.error("The knowledge graph for this project has no database configured. Contact your administrator or check the project setup.");
|
|
11206
|
-
} else if (msg.includes("GRAPH_TIMEOUT")) {
|
|
11207
|
-
console.error("Could not reach the
|
|
11815
|
+
} else if (msg.includes("GRAPH_TIMEOUT") || isTimeout) {
|
|
11816
|
+
console.error("Could not reach the QAECY API \u2014 the request timed out or the server could not be reached.");
|
|
11817
|
+
console.error("Check your internet connection and try again. If the problem persists, the service may be temporarily unavailable.");
|
|
11818
|
+
if (verbose && causeCode)
|
|
11819
|
+
console.error(` Cause: ${causeMsg ?? causeCode}`);
|
|
11208
11820
|
} else if (msg.includes("METADATA_SYNC_FAILED")) {
|
|
11209
11821
|
console.error("Metadata sync failed. Try again.");
|
|
11210
11822
|
} else if (msg.includes("LEDGER_WRITE_FAILED") || msg.includes("File structure batch POST failed")) {
|
|
@@ -11212,7 +11824,13 @@ async function syncHandler(options) {
|
|
|
11212
11824
|
"Failed communication with the knowledge graph. The files are up to date but metadata is not. Run the tool again to sync metadata. This is a swift job."
|
|
11213
11825
|
);
|
|
11214
11826
|
} else {
|
|
11215
|
-
console.error("
|
|
11827
|
+
console.error("An unexpected error occurred during sync.");
|
|
11828
|
+
if (verbose) {
|
|
11829
|
+
console.error("Details:", err);
|
|
11830
|
+
} else {
|
|
11831
|
+
console.error(` ${msg}`);
|
|
11832
|
+
console.error("Re-run with --verbose for more details.");
|
|
11833
|
+
}
|
|
11216
11834
|
}
|
|
11217
11835
|
process.exit(1);
|
|
11218
11836
|
}
|
|
@@ -11675,6 +12293,100 @@ Project created \u2705`);
|
|
|
11675
12293
|
}
|
|
11676
12294
|
}
|
|
11677
12295
|
|
|
12296
|
+
// apps/desktop/cue-cli/src/cue-cli-app-builder-tools.ts
|
|
12297
|
+
var import_commander = require("commander");
|
|
12298
|
+
async function buildCueClient(options) {
|
|
12299
|
+
const key = options.key ?? process.env["CUE_API_KEY"];
|
|
12300
|
+
if (!key) {
|
|
12301
|
+
console.error("API key is required. Provide it via --key or CUE_API_KEY env variable.");
|
|
12302
|
+
process.exit(1);
|
|
12303
|
+
}
|
|
12304
|
+
const cue = new CueNode({
|
|
12305
|
+
apiKey: FIREBASE_CONFIG().apiKey,
|
|
12306
|
+
appId: FIREBASE_CONFIG().appId,
|
|
12307
|
+
measurementId: FIREBASE_CONFIG().measurementId,
|
|
12308
|
+
environment: options.emulators ? "emulator" : "production",
|
|
12309
|
+
...options.emulators ? { endpoints: getEmulatorEndpoints() } : {}
|
|
12310
|
+
});
|
|
12311
|
+
await cue.auth.signInWithApiKey(key);
|
|
12312
|
+
return cue;
|
|
12313
|
+
}
|
|
12314
|
+
async function listProjectsHandler(options) {
|
|
12315
|
+
try {
|
|
12316
|
+
const cue = await buildCueClient(options);
|
|
12317
|
+
if (options.verbose)
|
|
12318
|
+
console.error("Fetching projects...");
|
|
12319
|
+
const projects = await cue.api.projects.listProjects();
|
|
12320
|
+
const output = projects.map((p) => ({
|
|
12321
|
+
id: p.id,
|
|
12322
|
+
name: p.name,
|
|
12323
|
+
organizationID: p.organizationID,
|
|
12324
|
+
isPublic: p.isPublic,
|
|
12325
|
+
graphType: p.projectSettings?.graph?.type ?? "qlever",
|
|
12326
|
+
lastSync: p.lastSync
|
|
12327
|
+
}));
|
|
12328
|
+
console.log(JSON.stringify(output, null, 2));
|
|
12329
|
+
process.exit(0);
|
|
12330
|
+
} catch (err) {
|
|
12331
|
+
console.error("Error:", err instanceof Error ? err.message : String(err));
|
|
12332
|
+
process.exit(1);
|
|
12333
|
+
}
|
|
12334
|
+
}
|
|
12335
|
+
async function entitySummaryGraphHandler(options) {
|
|
12336
|
+
try {
|
|
12337
|
+
const cue = await buildCueClient(options);
|
|
12338
|
+
if (options.verbose)
|
|
12339
|
+
console.error(`Fetching entity summary graph for project ${options.space}...`);
|
|
12340
|
+
const entities = new CueProjectEntities(cue.api, options.space);
|
|
12341
|
+
if (options.format === "graph") {
|
|
12342
|
+
const graph = await entities.buildSummaryGraph("graph");
|
|
12343
|
+
console.log(JSON.stringify(graph, null, 2));
|
|
12344
|
+
} else if (options.format === "md") {
|
|
12345
|
+
const md = await entities.buildSummaryGraph("md");
|
|
12346
|
+
console.log(md);
|
|
12347
|
+
} else {
|
|
12348
|
+
const raw = await entities.buildSummaryGraph();
|
|
12349
|
+
console.log(JSON.stringify(raw, null, 2));
|
|
12350
|
+
}
|
|
12351
|
+
process.exit(0);
|
|
12352
|
+
} catch (err) {
|
|
12353
|
+
console.error("Error:", err instanceof Error ? err.message : String(err));
|
|
12354
|
+
process.exit(1);
|
|
12355
|
+
}
|
|
12356
|
+
}
|
|
12357
|
+
async function sparqlHandler(options) {
|
|
12358
|
+
try {
|
|
12359
|
+
let sparqlQuery = options.query;
|
|
12360
|
+
if (!sparqlQuery) {
|
|
12361
|
+
if (process.stdin.isTTY) {
|
|
12362
|
+
console.error("Provide a SPARQL query via --query or pipe it via stdin.");
|
|
12363
|
+
process.exit(1);
|
|
12364
|
+
}
|
|
12365
|
+
const chunks = [];
|
|
12366
|
+
for await (const chunk of process.stdin)
|
|
12367
|
+
chunks.push(chunk);
|
|
12368
|
+
sparqlQuery = Buffer.concat(chunks).toString("utf8").trim();
|
|
12369
|
+
}
|
|
12370
|
+
if (!sparqlQuery) {
|
|
12371
|
+
console.error("SPARQL query is empty.");
|
|
12372
|
+
process.exit(1);
|
|
12373
|
+
}
|
|
12374
|
+
const cue = await buildCueClient(options);
|
|
12375
|
+
if (options.verbose)
|
|
12376
|
+
console.error(`Executing SPARQL query against project ${options.space}...`);
|
|
12377
|
+
const result = await cue.api.sparql(sparqlQuery, options.space);
|
|
12378
|
+
console.log(JSON.stringify(result, null, 2));
|
|
12379
|
+
process.exit(0);
|
|
12380
|
+
} catch (err) {
|
|
12381
|
+
console.error("Error:", err instanceof Error ? err.message : String(err));
|
|
12382
|
+
process.exit(1);
|
|
12383
|
+
}
|
|
12384
|
+
}
|
|
12385
|
+
var appBuilderToolsCommand = new import_commander.Command("app-builder-tools").description("Tools for agent-assisted Cue app development. Outputs JSON for machine consumption.");
|
|
12386
|
+
appBuilderToolsCommand.command("list-projects").description("List all projects accessible to the authenticated user").option("-k, --key <api-key>", "Specify the API key (or set CUE_API_KEY env variable)").option("-e, --emulators", "Use emulators", false).option("-v, --verbose", "Enable verbose output", false).action(listProjectsHandler);
|
|
12387
|
+
appBuilderToolsCommand.command("entity-summary-graph").description("Fetch the entity category relationship summary graph for a project").requiredOption("-s, --space <id>", "Project ID (required)").option("-k, --key <api-key>", "Specify the API key (or set CUE_API_KEY env variable)").option("-e, --emulators", "Use emulators", false).option("-f, --format <format>", "Output format: md (aligned text), graph (JSON nodes+edges), json (raw SPARQL)", "md").option("-v, --verbose", "Enable verbose output", false).action(entitySummaryGraphHandler);
|
|
12388
|
+
appBuilderToolsCommand.command("sparql").description("Execute a SPARQL SELECT query against a project triplestore. Query via --query or stdin.").requiredOption("-s, --space <id>", "Project ID (required)").option("-q, --query <sparql>", "SPARQL query string (or pipe query via stdin)").option("-k, --key <api-key>", "Specify the API key (or set CUE_API_KEY env variable)").option("-e, --emulators", "Use emulators", false).option("-v, --verbose", "Enable verbose output", false).action(sparqlHandler);
|
|
12389
|
+
|
|
11678
12390
|
// apps/desktop/cue-cli/src/main.ts
|
|
11679
12391
|
var packageJson;
|
|
11680
12392
|
try {
|
|
@@ -11687,7 +12399,7 @@ try {
|
|
|
11687
12399
|
console.warn("Could not find package.json, using fallback version");
|
|
11688
12400
|
}
|
|
11689
12401
|
}
|
|
11690
|
-
var program = new
|
|
12402
|
+
var program = new import_commander2.Command();
|
|
11691
12403
|
program.name("cue-cli").description("Cue Command Line Interface").version(packageJson.version);
|
|
11692
12404
|
program.command("sync").description("Sync files to Cue").option("-s, --space <id>", "Specify the space ID (omit to pick interactively)").requiredOption("-p, --path <id>", "Specify the folder path (required)").option("-k, --key <api-key>", "Specify the API key (or set CUE_API_KEY env variable)").option("--provider <provider ID>", "Specify the provider ID (eg. sharepoint, drive, dropbox) or leave empty for default provider", "").option("-v, --verbose", "Enable verbose output", false).option("-e, --emulators", "Uses emulators for sync", false).option("-z, --zip", 'Include zipped content (will be unzipped to path "<zip_path>_unzipped". Max uncompressed size: 500 MB, max recursion depth: 3)', false).option("--legacy", "Write RDF as BLOBs to the processed bucket instead of patching the graph directly", false).option("--metadata-only", "Push filesystem-structure metadata for all local files without checking credits or remote state", false).action(syncHandler);
|
|
11693
12405
|
program.command("dump").description("Dump Cue Knowledge Graph data to file\n Examples:\n $ cue-cli dump -s <space_id> -l -v\n $ cue-cli dump -s <space_id> -j -v").requiredOption("-s, --space <id>", "Specify the space ID (required)").option("-k, --key <api-key>", "Specify the API key (or set CUE_API_KEY env variable)").option("-v, --verbose", "Enable verbose output", false).option("-e, --emulators", "Uses emulators for sync", false).option("-q, --query", "Uses a construct query to get the dump rather than using the /data endpoint", false).option("-j, --jelly", "Downloads a Jelly file rather than the standard Gzipped NQuads format", false).option("-l, --load", "Loads the dumped file into a local triplestore (requires emulators)", false).action(dumpHandler);
|
|
@@ -11697,4 +12409,5 @@ program.command("repair-ttl").description("Repair TTL files in the specified spa
|
|
|
11697
12409
|
program.command("util-rdf-compare").description("Compare two Turtle (.ttl) files and report semantic differences").requiredOption("--file1 <path>", "Path to the first TTL file").requiredOption("--file2 <path>", "Path to the second TTL file").option("-v, --verbose", "Enable verbose output", false).action(utilRdfCompareHandler);
|
|
11698
12410
|
program.command("util-remove-rdf-star").description("Remove RDF-star (quoted) triples from an NQuads file. Supports .nq and .nq.gz input/output.").requiredOption("-i, --input <path>", "Input file path (.nq or .nq.gz)").requiredOption("-o, --output <path>", "Output file path (.nq or .nq.gz)").option("-v, --verbose", "Enable verbose output", false).action(utilRemoveRdfStarHandler);
|
|
11699
12411
|
program.command("create-project").description("Interactively create a new project under an organisation").option("-k, --key <api-key>", "Specify the API key (or set CUE_API_KEY env variable)").option("-e, --emulators", "Uses emulators", false).option("-v, --verbose", "Enable verbose output", false).action(createProjectHandler);
|
|
12412
|
+
program.addCommand(appBuilderToolsCommand);
|
|
11700
12413
|
program.parse(process.argv);
|