@qaecy/cue-cli 0.0.31 → 0.0.33
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/.gitkeep +0 -0
- package/assets/wasm/dir_scanner_wasm.mjs +28 -0
- package/assets/wasm/dir_scanner_wasm_bg.wasm +0 -0
- package/main.js +398 -271
- package/package.json +1 -2
package/assets/.gitkeep
ADDED
|
File without changes
|
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
/* @ts-self-types="./dir_scanner_wasm.d.ts" */
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Attempts to extract the unit count from any supported file and returns a plain JS
|
|
5
|
+
* object `{ units: number, error: string | null }`.
|
|
6
|
+
*
|
|
7
|
+
* `original_path` is used only for extension detection.
|
|
8
|
+
*
|
|
9
|
+
* ```js
|
|
10
|
+
* const buf = await file.arrayBuffer();
|
|
11
|
+
* const result = debug_file(file.name, new Uint8Array(buf));
|
|
12
|
+
* console.log(result); // { units: 12, error: null }
|
|
13
|
+
* ```
|
|
14
|
+
* @param {string} original_path
|
|
15
|
+
* @param {Uint8Array} data
|
|
16
|
+
* @returns {any}
|
|
17
|
+
*/
|
|
18
|
+
export function debug_file(original_path, data) {
|
|
19
|
+
const ptr0 = passStringToWasm0(original_path, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
20
|
+
const len0 = WASM_VECTOR_LEN;
|
|
21
|
+
const ret = wasm.debug_file(ptr0, len0, data);
|
|
22
|
+
return ret;
|
|
23
|
+
}
|
|
24
|
+
|
|
3
25
|
/**
|
|
4
26
|
* Scans a list of in-memory files and returns per-extension metrics sorted by
|
|
5
27
|
* file count descending.
|
|
@@ -101,6 +123,9 @@ function __wbg_get_imports() {
|
|
|
101
123
|
const ret = arg0.length;
|
|
102
124
|
return ret;
|
|
103
125
|
},
|
|
126
|
+
__wbg_log_7e1aa9064a1dbdbd: function(arg0) {
|
|
127
|
+
console.log(arg0);
|
|
128
|
+
},
|
|
104
129
|
__wbg_new_0c7403db6e782f19: function(arg0) {
|
|
105
130
|
const ret = new Uint8Array(arg0);
|
|
106
131
|
return ret;
|
|
@@ -126,6 +151,9 @@ function __wbg_get_imports() {
|
|
|
126
151
|
__wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
|
|
127
152
|
arg0[arg1] = arg2;
|
|
128
153
|
},
|
|
154
|
+
__wbg_warn_3cc416af27dbdc02: function(arg0) {
|
|
155
|
+
console.warn(arg0);
|
|
156
|
+
},
|
|
129
157
|
__wbindgen_cast_0000000000000001: function(arg0) {
|
|
130
158
|
// Cast intrinsic for `F64 -> Externref`.
|
|
131
159
|
const ret = arg0;
|
|
Binary file
|
package/main.js
CHANGED
|
@@ -3827,19 +3827,6 @@ function generateFileUUID(filepath, providerId = "") {
|
|
|
3827
3827
|
return contextBasedGuid(`${providerId}${filepath}`);
|
|
3828
3828
|
}
|
|
3829
3829
|
|
|
3830
|
-
// libs/js/id-builders/src/lib/id-extractor.ts
|
|
3831
|
-
var extractIdsFromRawPath = (filePath) => {
|
|
3832
|
-
if (filePath.startsWith("/")) {
|
|
3833
|
-
filePath = filePath.slice(1);
|
|
3834
|
-
}
|
|
3835
|
-
const pathParts = filePath.split("/");
|
|
3836
|
-
const projectId = pathParts[0];
|
|
3837
|
-
const fileName = pathParts.pop() ?? "";
|
|
3838
|
-
const suffix = `.${fileName.split(".").pop()?.toLowerCase()}`;
|
|
3839
|
-
const documentUUID = fileName.replace(/\.[^.]+$/, "");
|
|
3840
|
-
return { projectId, documentUUID, suffix };
|
|
3841
|
-
};
|
|
3842
|
-
|
|
3843
3830
|
// libs/js/id-builders/src/lib/md5-builder.ts
|
|
3844
3831
|
var import_spark_md5 = __toESM(require("spark-md5"));
|
|
3845
3832
|
async function fromReadStream(readStream) {
|
|
@@ -4154,6 +4141,7 @@ var CueAuth = class {
|
|
|
4154
4141
|
// libs/js/cue-sdk/src/lib/api.ts
|
|
4155
4142
|
var ENDPOINT_SEARCH = "/assistant/search";
|
|
4156
4143
|
var ENDPOINT_SPARQL = "/triplestore/query";
|
|
4144
|
+
var ENDPOINT_CONSUMPTION = "/data-views/admin/consumption/units";
|
|
4157
4145
|
var CueApi = class {
|
|
4158
4146
|
constructor(_auth, _gatewayUrl, projects, sync) {
|
|
4159
4147
|
this._auth = _auth;
|
|
@@ -4213,6 +4201,16 @@ var CueApi = class {
|
|
|
4213
4201
|
}
|
|
4214
4202
|
return response.json();
|
|
4215
4203
|
}
|
|
4204
|
+
async getConsumption(projectId) {
|
|
4205
|
+
const headers = await this._authHeaders();
|
|
4206
|
+
const response = await fetch(`${this._gatewayUrl}${ENDPOINT_CONSUMPTION}`, {
|
|
4207
|
+
headers: { ...headers, "x-project-id": projectId }
|
|
4208
|
+
});
|
|
4209
|
+
if (!response.ok) {
|
|
4210
|
+
throw new Error(`Failed to fetch consumption: ${response.status} ${response.statusText}`);
|
|
4211
|
+
}
|
|
4212
|
+
return response.json();
|
|
4213
|
+
}
|
|
4216
4214
|
};
|
|
4217
4215
|
|
|
4218
4216
|
// libs/js/cue-sdk/src/lib/project.ts
|
|
@@ -4317,7 +4315,6 @@ var CueProjects = class {
|
|
|
4317
4315
|
// libs/js/cue-sdk/src/lib/profile.ts
|
|
4318
4316
|
var import_auth4 = require("firebase/auth");
|
|
4319
4317
|
var import_firestore3 = require("firebase/firestore");
|
|
4320
|
-
var import_nanoid = require("nanoid");
|
|
4321
4318
|
var COLLECTION_API_KEYS2 = "apiKeys";
|
|
4322
4319
|
var CueProfile = class {
|
|
4323
4320
|
constructor(_auth, app, useEmulator, emulatorHost, emulatorPort) {
|
|
@@ -4405,7 +4402,9 @@ var CueProfile = class {
|
|
|
4405
4402
|
const uid = this._auth.currentUser?.uid;
|
|
4406
4403
|
if (!uid)
|
|
4407
4404
|
throw new Error("User not authenticated");
|
|
4408
|
-
const
|
|
4405
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4406
|
+
const randomKey = Array.from(globalThis.crypto.getRandomValues(new Uint8Array(150)), (b) => alphabet[b & 63]).join("");
|
|
4407
|
+
const data = { key: `cue-${randomKey}`, uid, expiration };
|
|
4409
4408
|
const col = (0, import_firestore3.collection)(this._db, COLLECTION_API_KEYS2);
|
|
4410
4409
|
this._apiKeyDocRef = await (0, import_firestore3.addDoc)(col, data);
|
|
4411
4410
|
return data;
|
|
@@ -4598,9 +4597,18 @@ var Fuseki = class _Fuseki {
|
|
|
4598
4597
|
};
|
|
4599
4598
|
|
|
4600
4599
|
// libs/js/databases/src/lib/graph/qlever.ts
|
|
4600
|
+
var import_zlib = require("zlib");
|
|
4601
|
+
var import_n3 = require("n3");
|
|
4602
|
+
var QLeverLockedError = class extends Error {
|
|
4603
|
+
constructor(body) {
|
|
4604
|
+
super(`QLever is locked (rebuild in progress): ${body}`);
|
|
4605
|
+
this.name = "QLeverLockedError";
|
|
4606
|
+
}
|
|
4607
|
+
};
|
|
4601
4608
|
var QLever = class _QLever {
|
|
4602
4609
|
queryEndpoint;
|
|
4603
4610
|
updateEndpoint;
|
|
4611
|
+
dataEndpoint;
|
|
4604
4612
|
baseHeaders;
|
|
4605
4613
|
static RELEVANT_HEADER_KEYS = [
|
|
4606
4614
|
"authorization",
|
|
@@ -4609,14 +4617,44 @@ var QLever = class _QLever {
|
|
|
4609
4617
|
"x-user-roles"
|
|
4610
4618
|
// add more if needed
|
|
4611
4619
|
];
|
|
4620
|
+
/** Max retries on 423 Locked (rebuild in progress). */
|
|
4621
|
+
static LOCKED_MAX_RETRIES = parseInt(process.env["QLEVER_LOCKED_MAX_RETRIES"] ?? "10", 10);
|
|
4622
|
+
/** Base delay (ms) for exponential backoff on 423. */
|
|
4623
|
+
static LOCKED_BASE_DELAY_MS = parseInt(process.env["QLEVER_LOCKED_BASE_DELAY_MS"] ?? "2000", 10);
|
|
4624
|
+
/**
|
|
4625
|
+
* Retry an async write operation on 423 Locked with exponential backoff + jitter.
|
|
4626
|
+
* 423 means qlever accessor has an ongoing rebuild; we should wait and retry.
|
|
4627
|
+
*/
|
|
4628
|
+
static async _retryOnLocked(fn) {
|
|
4629
|
+
const maxRetries = _QLever.LOCKED_MAX_RETRIES;
|
|
4630
|
+
const baseDelayMs = _QLever.LOCKED_BASE_DELAY_MS;
|
|
4631
|
+
let lastError;
|
|
4632
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
4633
|
+
try {
|
|
4634
|
+
return await fn();
|
|
4635
|
+
} catch (err) {
|
|
4636
|
+
lastError = err;
|
|
4637
|
+
if (err instanceof QLeverLockedError && attempt < maxRetries) {
|
|
4638
|
+
const jitter = 0.5 + Math.random();
|
|
4639
|
+
const delay = baseDelayMs * Math.pow(2, attempt) * jitter;
|
|
4640
|
+
await new Promise((resolve2) => setTimeout(resolve2, delay));
|
|
4641
|
+
continue;
|
|
4642
|
+
}
|
|
4643
|
+
throw err;
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4646
|
+
throw lastError;
|
|
4647
|
+
}
|
|
4612
4648
|
constructor(graphOptions) {
|
|
4613
4649
|
this.queryEndpoint = graphOptions.queryEndpoint;
|
|
4614
4650
|
this.updateEndpoint = graphOptions.updateEndpoint;
|
|
4651
|
+
this.dataEndpoint = this.updateEndpoint.replace(/\/update$/, "/data");
|
|
4615
4652
|
this.baseHeaders = Object.fromEntries(
|
|
4616
4653
|
Object.entries(graphOptions.originalHeaders || {}).filter(
|
|
4617
4654
|
([key]) => _QLever.RELEVANT_HEADER_KEYS.includes(key)
|
|
4618
4655
|
)
|
|
4619
4656
|
);
|
|
4657
|
+
this.baseHeaders["x-user-roles"] = "admin";
|
|
4620
4658
|
}
|
|
4621
4659
|
async ping() {
|
|
4622
4660
|
const query3 = "ASK { }";
|
|
@@ -4626,7 +4664,6 @@ var QLever = class _QLever {
|
|
|
4626
4664
|
async query(query3, accept = "application/sparql-results+json") {
|
|
4627
4665
|
let res;
|
|
4628
4666
|
try {
|
|
4629
|
-
console.log(this.queryEndpoint);
|
|
4630
4667
|
res = await fetch(this.queryEndpoint, {
|
|
4631
4668
|
headers: {
|
|
4632
4669
|
...this.baseHeaders,
|
|
@@ -4660,19 +4697,65 @@ var QLever = class _QLever {
|
|
|
4660
4697
|
return await res.text();
|
|
4661
4698
|
}
|
|
4662
4699
|
async update(update) {
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4668
|
-
|
|
4669
|
-
|
|
4700
|
+
return _QLever._retryOnLocked(async () => {
|
|
4701
|
+
const res = await fetch(this.updateEndpoint, {
|
|
4702
|
+
headers: {
|
|
4703
|
+
...this.baseHeaders,
|
|
4704
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
4705
|
+
},
|
|
4706
|
+
method: "POST",
|
|
4707
|
+
body: new URLSearchParams({ update })
|
|
4708
|
+
});
|
|
4709
|
+
if (!res.ok) {
|
|
4710
|
+
const body = await res.text();
|
|
4711
|
+
if (res.status === 423)
|
|
4712
|
+
throw new QLeverLockedError(body);
|
|
4713
|
+
throw new Error(`SPARQL update failed (HTTP ${res.status}): ${body}`);
|
|
4714
|
+
}
|
|
4715
|
+
return await res.json();
|
|
4716
|
+
});
|
|
4717
|
+
}
|
|
4718
|
+
/**
|
|
4719
|
+
* Insert quads via the /data endpoint, grouped by named graph.
|
|
4720
|
+
* This is preferred over SPARQL INSERT DATA for QLever because
|
|
4721
|
+
* the /data endpoint correctly registers named graphs in the index.
|
|
4722
|
+
*/
|
|
4723
|
+
async insertData(quads) {
|
|
4724
|
+
await this._postToDataEndpoint(quads, this.dataEndpoint);
|
|
4725
|
+
}
|
|
4726
|
+
/**
|
|
4727
|
+
* Delete quads via the /data/delete endpoint, grouped by named graph.
|
|
4728
|
+
*/
|
|
4729
|
+
async deleteData(quads) {
|
|
4730
|
+
await this._postToDataEndpoint(quads, `${this.dataEndpoint}/delete`);
|
|
4731
|
+
}
|
|
4732
|
+
async _postToDataEndpoint(quads, baseUrl) {
|
|
4733
|
+
const nquads = await this._quadsToNQuads(quads);
|
|
4734
|
+
const body = new Uint8Array((0, import_zlib.gzipSync)(Buffer.from(nquads, "utf-8")));
|
|
4735
|
+
await _QLever._retryOnLocked(async () => {
|
|
4736
|
+
const res = await fetch(baseUrl, {
|
|
4737
|
+
method: "POST",
|
|
4738
|
+
headers: {
|
|
4739
|
+
...this.baseHeaders,
|
|
4740
|
+
"Content-Type": "application/n-quads",
|
|
4741
|
+
"Content-Encoding": "gzip"
|
|
4742
|
+
},
|
|
4743
|
+
body
|
|
4744
|
+
});
|
|
4745
|
+
if (!res.ok) {
|
|
4746
|
+
const text = await res.text();
|
|
4747
|
+
if (res.status === 423)
|
|
4748
|
+
throw new QLeverLockedError(text);
|
|
4749
|
+
throw new Error(`QLever data POST failed (HTTP ${res.status}): ${text}`);
|
|
4750
|
+
}
|
|
4751
|
+
});
|
|
4752
|
+
}
|
|
4753
|
+
_quadsToNQuads(quads) {
|
|
4754
|
+
return new Promise((resolve2, reject) => {
|
|
4755
|
+
const writer = new import_n3.Writer({ format: "application/n-quads" });
|
|
4756
|
+
writer.addQuads(quads);
|
|
4757
|
+
writer.end((err, result) => err ? reject(err) : resolve2(result));
|
|
4670
4758
|
});
|
|
4671
|
-
if (!res.ok) {
|
|
4672
|
-
const body = await res.text();
|
|
4673
|
-
throw new Error(`SPARQL update failed (HTTP ${res.status}): ${body}`);
|
|
4674
|
-
}
|
|
4675
|
-
return await res.json();
|
|
4676
4759
|
}
|
|
4677
4760
|
};
|
|
4678
4761
|
|
|
@@ -4717,6 +4800,32 @@ var CueGraphDatabase = class {
|
|
|
4717
4800
|
update(updateString) {
|
|
4718
4801
|
return this._db.update(updateString);
|
|
4719
4802
|
}
|
|
4803
|
+
/** Returns true if this backend supports the /data bulk-insert endpoint (QLever only). */
|
|
4804
|
+
supportsDataEndpoint() {
|
|
4805
|
+
return this.options.graphType === "qlever";
|
|
4806
|
+
}
|
|
4807
|
+
/**
|
|
4808
|
+
* Insert quads using the backend's preferred bulk-insert mechanism.
|
|
4809
|
+
* For QLever: uses the /data endpoint (correctly registers named graphs).
|
|
4810
|
+
* For Fuseki: falls back to SPARQL INSERT DATA.
|
|
4811
|
+
*/
|
|
4812
|
+
insertData(quads) {
|
|
4813
|
+
if (this.options.graphType === "qlever") {
|
|
4814
|
+
return this._db.insertData(quads);
|
|
4815
|
+
}
|
|
4816
|
+
return Promise.reject(new Error("insertData not supported for Fuseki \u2014 use update() with SPARQL INSERT DATA"));
|
|
4817
|
+
}
|
|
4818
|
+
/**
|
|
4819
|
+
* Delete quads using the backend's preferred bulk-delete mechanism.
|
|
4820
|
+
* For QLever: uses the /data/delete endpoint.
|
|
4821
|
+
* For Fuseki: falls back to SPARQL DELETE DATA.
|
|
4822
|
+
*/
|
|
4823
|
+
deleteData(quads) {
|
|
4824
|
+
if (this.options.graphType === "qlever") {
|
|
4825
|
+
return this._db.deleteData(quads);
|
|
4826
|
+
}
|
|
4827
|
+
return Promise.reject(new Error("deleteData not supported for Fuseki \u2014 use update() with SPARQL DELETE DATA"));
|
|
4828
|
+
}
|
|
4720
4829
|
};
|
|
4721
4830
|
|
|
4722
4831
|
// libs/js/databases/src/lib/blob/blob.ts
|
|
@@ -4777,6 +4886,7 @@ var CueBlobStorage = class {
|
|
|
4777
4886
|
var import_promises3 = require("fs/promises");
|
|
4778
4887
|
var import_path3 = require("path");
|
|
4779
4888
|
var import_url = require("url");
|
|
4889
|
+
var import_os = require("os");
|
|
4780
4890
|
|
|
4781
4891
|
// libs/js/models/src/lib/file-extensions.ts
|
|
4782
4892
|
var fileExtensionsInfo = {
|
|
@@ -5677,106 +5787,20 @@ var import_uuid4 = require("uuid");
|
|
|
5677
5787
|
var import_uuid5 = require("uuid");
|
|
5678
5788
|
|
|
5679
5789
|
// libs/js/rdf-document-writers/src/lib/alternative-representation.ts
|
|
5680
|
-
var
|
|
5790
|
+
var import_n33 = require("n3");
|
|
5681
5791
|
|
|
5682
5792
|
// libs/js/rdf-document-writers/src/lib/file-location.ts
|
|
5683
|
-
var
|
|
5684
|
-
var { namedNode, literal } =
|
|
5793
|
+
var import_n32 = require("n3");
|
|
5794
|
+
var { namedNode, literal } = import_n32.DataFactory;
|
|
5685
5795
|
var a = namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
5686
5796
|
var prefixes = {
|
|
5687
5797
|
qcy: qaecyPrefixes["qcy"],
|
|
5688
5798
|
"qcy-e": qaecyPrefixes["qcy-e"],
|
|
5689
5799
|
xsd: prefixCC["xsd"]
|
|
5690
5800
|
};
|
|
5691
|
-
function fileLocationRaw(metadata, size, fileContentClasses = ["qcy:FileContent"], writer = new import_n3.Writer({ prefixes }), remoteProviderType = "GCP" /* GCP */) {
|
|
5692
|
-
if (metadata.md5_hash === void 0)
|
|
5693
|
-
throw new Error("md5_hash must be specified");
|
|
5694
|
-
if (metadata.blob_name === void 0)
|
|
5695
|
-
throw new Error("blob_name must be specified");
|
|
5696
|
-
if (metadata.suffix === void 0)
|
|
5697
|
-
throw new Error("suffix must be specified");
|
|
5698
|
-
if (metadata.name === void 0)
|
|
5699
|
-
throw new Error("name must be specified");
|
|
5700
|
-
const ids = extractIdsFromRawPath(metadata.blob_name);
|
|
5701
|
-
const fileInfo = getFileInfo(metadata.suffix);
|
|
5702
|
-
const mimeCategory = fileTypeToMimeCategory[fileInfo.type];
|
|
5703
|
-
const originalName = metadata.name.split("/").pop() ?? metadata.name;
|
|
5704
|
-
const fileContent = namedNode(ids.documentUUID);
|
|
5705
|
-
const fileLocationUUID = generateFileUUID(
|
|
5706
|
-
metadata.name,
|
|
5707
|
-
metadata.provider_id ?? ""
|
|
5708
|
-
);
|
|
5709
|
-
const fileLocation = namedNode(fileLocationUUID);
|
|
5710
|
-
fileContentClasses.forEach((cl) => {
|
|
5711
|
-
writer.addQuad(fileContent, a, namedNode(cl));
|
|
5712
|
-
});
|
|
5713
|
-
writer.addQuad(
|
|
5714
|
-
fileContent,
|
|
5715
|
-
namedNode("qcy:hasMimeCategory"),
|
|
5716
|
-
namedNode(`qcy-e:${mimeCategory}`)
|
|
5717
|
-
);
|
|
5718
|
-
writer.addQuad(
|
|
5719
|
-
fileContent,
|
|
5720
|
-
namedNode("qcy:md5Hash"),
|
|
5721
|
-
literal(metadata.md5_hash)
|
|
5722
|
-
);
|
|
5723
|
-
writer.addQuad(fileContent, namedNode("qcy:mime"), literal(fileInfo.mime));
|
|
5724
|
-
writer.addQuad(
|
|
5725
|
-
fileContent,
|
|
5726
|
-
namedNode("qcy:openFormat"),
|
|
5727
|
-
literal(fileInfo?.open)
|
|
5728
|
-
);
|
|
5729
|
-
writer.addQuad(fileContent, namedNode("qcy:sizeBytes"), literal(size));
|
|
5730
|
-
writer.addQuad(fileContent, namedNode("qcy:hasFileLocation"), fileLocation);
|
|
5731
|
-
writer.addQuad(fileLocation, a, namedNode("qcy:FileLocation"));
|
|
5732
|
-
writer.addQuad(
|
|
5733
|
-
fileLocation,
|
|
5734
|
-
namedNode("qcy:filePath"),
|
|
5735
|
-
literal(metadata.name)
|
|
5736
|
-
);
|
|
5737
|
-
writer.addQuad(
|
|
5738
|
-
fileLocation,
|
|
5739
|
-
namedNode("qcy:remoteProviderType"),
|
|
5740
|
-
namedNode(`qcy-e:${remoteProviderType}`)
|
|
5741
|
-
);
|
|
5742
|
-
writer.addQuad(
|
|
5743
|
-
fileLocation,
|
|
5744
|
-
namedNode("qcy:remoteProviderId"),
|
|
5745
|
-
literal(metadata.provider_id ?? "")
|
|
5746
|
-
);
|
|
5747
|
-
writer.addQuad(
|
|
5748
|
-
fileLocation,
|
|
5749
|
-
namedNode("qcy:remoteRelativePath"),
|
|
5750
|
-
literal(metadata.blob_name)
|
|
5751
|
-
);
|
|
5752
|
-
writer.addQuad(
|
|
5753
|
-
fileLocation,
|
|
5754
|
-
namedNode("qcy:suffix"),
|
|
5755
|
-
literal(metadata.suffix)
|
|
5756
|
-
);
|
|
5757
|
-
writer.addQuad(
|
|
5758
|
-
fileLocation,
|
|
5759
|
-
namedNode("qcy:dateCreated"),
|
|
5760
|
-
literal((/* @__PURE__ */ new Date()).toISOString(), namedNode("xsd:dateTime"))
|
|
5761
|
-
);
|
|
5762
|
-
writer.addQuad(fileLocation, namedNode("qcy:value"), literal(originalName));
|
|
5763
|
-
return writer;
|
|
5764
|
-
}
|
|
5765
|
-
function getFileInfo(suffix) {
|
|
5766
|
-
let fileInfo = fileExtensionsInfo[suffix];
|
|
5767
|
-
if (fileInfo === void 0) {
|
|
5768
|
-
fileInfo = {
|
|
5769
|
-
type: "unknown" /* UNKNOWN */,
|
|
5770
|
-
open: false,
|
|
5771
|
-
suffix,
|
|
5772
|
-
mime: "application/octet-stream"
|
|
5773
|
-
};
|
|
5774
|
-
}
|
|
5775
|
-
return fileInfo;
|
|
5776
|
-
}
|
|
5777
5801
|
|
|
5778
5802
|
// libs/js/rdf-document-writers/src/lib/alternative-representation.ts
|
|
5779
|
-
var { namedNode: namedNode2 } =
|
|
5803
|
+
var { namedNode: namedNode2 } = import_n33.DataFactory;
|
|
5780
5804
|
var prefixes2 = {
|
|
5781
5805
|
qcy: qaecyPrefixes["qcy"],
|
|
5782
5806
|
"qcy-e": qaecyPrefixes["qcy-e"],
|
|
@@ -5784,12 +5808,12 @@ var prefixes2 = {
|
|
|
5784
5808
|
};
|
|
5785
5809
|
|
|
5786
5810
|
// libs/js/rdf-document-writers/src/lib/custom-template-parser.ts
|
|
5787
|
-
var
|
|
5788
|
-
var { namedNode: namedNode3, literal: literal2 } =
|
|
5811
|
+
var import_n34 = require("n3");
|
|
5812
|
+
var { namedNode: namedNode3, literal: literal2 } = import_n34.DataFactory;
|
|
5789
5813
|
var a2 = namedNode3("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
5790
5814
|
|
|
5791
5815
|
// libs/js/rdf-document-writers/src/lib/document-file.ts
|
|
5792
|
-
var
|
|
5816
|
+
var import_n35 = require("n3");
|
|
5793
5817
|
|
|
5794
5818
|
// libs/js/rdf-document-writers/src/lib/file-suffix.ts
|
|
5795
5819
|
function getFileSuffix(filename) {
|
|
@@ -5801,28 +5825,13 @@ function getFileSuffix(filename) {
|
|
|
5801
5825
|
}
|
|
5802
5826
|
|
|
5803
5827
|
// libs/js/rdf-document-writers/src/lib/document-file.ts
|
|
5804
|
-
var { namedNode: namedNode4, literal: literal3 } =
|
|
5828
|
+
var { namedNode: namedNode4, literal: literal3 } = import_n35.DataFactory;
|
|
5805
5829
|
var a3 = namedNode4("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
5806
5830
|
|
|
5807
5831
|
// libs/js/rdf-document-writers/src/lib/process-logs.ts
|
|
5808
|
-
var
|
|
5809
|
-
|
|
5810
|
-
// libs/js/rdf-document-writers/src/lib/serialize-rdf.ts
|
|
5811
|
-
async function serializeRDF(namespace, writer, format = "ttl") {
|
|
5812
|
-
return new Promise((resolve2, reject) => {
|
|
5813
|
-
writer.end((err, res) => {
|
|
5814
|
-
if (err)
|
|
5815
|
-
reject(err);
|
|
5816
|
-
const addBase = format === "ttl" && namespace !== "";
|
|
5817
|
-
resolve2(addBase ? `@base <${namespace}>.
|
|
5818
|
-
${res}` : res);
|
|
5819
|
-
});
|
|
5820
|
-
});
|
|
5821
|
-
}
|
|
5822
|
-
|
|
5823
|
-
// libs/js/rdf-document-writers/src/lib/process-logs.ts
|
|
5832
|
+
var import_n36 = require("n3");
|
|
5824
5833
|
var import_uuid6 = require("uuid");
|
|
5825
|
-
var { namedNode: namedNode5, literal: literal4 } =
|
|
5834
|
+
var { namedNode: namedNode5, literal: literal4 } = import_n36.DataFactory;
|
|
5826
5835
|
var a4 = namedNode5("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
|
|
5827
5836
|
var prefixes3 = {
|
|
5828
5837
|
qcy: qaecyPrefixes["qcy"],
|
|
@@ -5860,24 +5869,9 @@ function uploadedFileMetadata(originalName, projectId, userId, md5, providerId,
|
|
|
5860
5869
|
})
|
|
5861
5870
|
};
|
|
5862
5871
|
}
|
|
5863
|
-
function turtleFileMetadata(sourceFile, processorId, locationUUID, stored = false) {
|
|
5864
|
-
const ids = extractIdsFromRawPath(sourceFile);
|
|
5865
|
-
const blob_name = locationUUID !== void 0 ? `${ids.projectId}/triples/${ids.documentUUID}_${locationUUID}_${processorId}.ttl` : `${ids.projectId}/triples/${ids.documentUUID}_${processorId}.ttl`;
|
|
5866
|
-
const identifier = locationUUID !== void 0 ? `${ids.documentUUID}_${locationUUID}` : ids.documentUUID;
|
|
5867
|
-
return {
|
|
5868
|
-
blob_name,
|
|
5869
|
-
processor: processorId,
|
|
5870
|
-
space_id: ids.projectId,
|
|
5871
|
-
stored: stored ? "True" : "False",
|
|
5872
|
-
suffix: ".ttl",
|
|
5873
|
-
identifier,
|
|
5874
|
-
source: sourceFile
|
|
5875
|
-
};
|
|
5876
|
-
}
|
|
5877
5872
|
|
|
5878
5873
|
// libs/js/cue-sdk/src/lib/sync.ts
|
|
5879
5874
|
var _scanFn = null;
|
|
5880
|
-
var _fileMapFn = null;
|
|
5881
5875
|
var _wasmInitPromise = null;
|
|
5882
5876
|
async function _initWasm() {
|
|
5883
5877
|
const wasmDir = (0, import_path3.join)(__dirname, "assets", "wasm");
|
|
@@ -5889,25 +5883,91 @@ async function _initWasm() {
|
|
|
5889
5883
|
);
|
|
5890
5884
|
await mod.default({ module_or_path: wasmBinary });
|
|
5891
5885
|
_scanFn = mod.scan;
|
|
5892
|
-
_fileMapFn = mod.scan_file_map;
|
|
5893
5886
|
}
|
|
5894
5887
|
var DEFAULT_GRAPH_TYPE = "fuseki";
|
|
5895
|
-
var DEFAULT_SERVICE_ID = "cue-cli";
|
|
5896
|
-
var DEFAULT_RDF_BASE = "https://cue.qaecy.com/r/";
|
|
5897
5888
|
var ENDPOINT_FUSEKI_QUERY = "/triplestore/query";
|
|
5898
5889
|
var ENDPOINT_QLEVER_QUERY = "/sparql/query";
|
|
5899
5890
|
var ENDPOINT_FUSEKI_UPDATE = "/triplestore/update";
|
|
5900
5891
|
var ENDPOINT_QLEVER_UPDATE = "/sparql/update";
|
|
5892
|
+
var ENDPOINT_FSS_BATCH = "/commands/file-system-structure/batch";
|
|
5893
|
+
var FSS_BATCH_CHUNK_SIZE = 1e3;
|
|
5894
|
+
var PENDING_LS_PREFIX = "cue:pending:";
|
|
5895
|
+
function _pendingFilePath(spaceId) {
|
|
5896
|
+
return (0, import_path3.join)((0, import_os.tmpdir)(), `cue-sync-pending-${spaceId}.json`);
|
|
5897
|
+
}
|
|
5898
|
+
async function _loadPending(spaceId) {
|
|
5899
|
+
if (typeof window !== "undefined") {
|
|
5900
|
+
const raw = window.localStorage.getItem(`${PENDING_LS_PREFIX}${spaceId}`);
|
|
5901
|
+
return raw ? JSON.parse(raw) : null;
|
|
5902
|
+
}
|
|
5903
|
+
try {
|
|
5904
|
+
const raw = await (0, import_promises3.readFile)(_pendingFilePath(spaceId), "utf-8");
|
|
5905
|
+
return JSON.parse(raw);
|
|
5906
|
+
} catch {
|
|
5907
|
+
return null;
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
async function _savePending(batch) {
|
|
5911
|
+
const data = JSON.stringify(batch);
|
|
5912
|
+
if (typeof window !== "undefined") {
|
|
5913
|
+
window.localStorage.setItem(`${PENDING_LS_PREFIX}${batch.spaceId}`, data);
|
|
5914
|
+
return;
|
|
5915
|
+
}
|
|
5916
|
+
await (0, import_promises3.writeFile)(_pendingFilePath(batch.spaceId), data, "utf-8");
|
|
5917
|
+
}
|
|
5918
|
+
async function _clearPending(spaceId) {
|
|
5919
|
+
if (typeof window !== "undefined") {
|
|
5920
|
+
window.localStorage.removeItem(`${PENDING_LS_PREFIX}${spaceId}`);
|
|
5921
|
+
return;
|
|
5922
|
+
}
|
|
5923
|
+
try {
|
|
5924
|
+
await (0, import_promises3.unlink)(_pendingFilePath(spaceId));
|
|
5925
|
+
} catch {
|
|
5926
|
+
}
|
|
5927
|
+
}
|
|
5901
5928
|
var CueSyncApi = class {
|
|
5902
|
-
constructor(_auth, _projects, _blob, _gatewayUrl
|
|
5929
|
+
constructor(_auth, _projects, _blob, _gatewayUrl) {
|
|
5903
5930
|
this._auth = _auth;
|
|
5904
5931
|
this._projects = _projects;
|
|
5905
5932
|
this._blob = _blob;
|
|
5906
5933
|
this._gatewayUrl = _gatewayUrl;
|
|
5907
|
-
this._serviceId = _serviceId;
|
|
5908
|
-
this._rdfBase = _rdfBase;
|
|
5909
5934
|
}
|
|
5910
5935
|
_graphMap = /* @__PURE__ */ new Map();
|
|
5936
|
+
_api;
|
|
5937
|
+
_pendingItems = [];
|
|
5938
|
+
_pendingSpaceId = null;
|
|
5939
|
+
_flushTimer = null;
|
|
5940
|
+
/** @internal Injected by CueApi after construction to avoid circular dependency. */
|
|
5941
|
+
_bindApi(api) {
|
|
5942
|
+
this._api = api;
|
|
5943
|
+
}
|
|
5944
|
+
/**
|
|
5945
|
+
* Returns a preview of what would be synced: cost breakdown for new files only,
|
|
5946
|
+
* units required, and units still available. Use this before calling {@link sync}
|
|
5947
|
+
* to show the user an accurate cost estimate.
|
|
5948
|
+
*/
|
|
5949
|
+
async previewSync(localFiles, options) {
|
|
5950
|
+
const { spaceId, providerId, verbose } = options;
|
|
5951
|
+
const token = await this._auth.getToken();
|
|
5952
|
+
if (!token)
|
|
5953
|
+
throw new Error("Not authenticated. Call cue.auth.signIn() first.");
|
|
5954
|
+
const graph = await this._getOrCreateGraph(spaceId, token);
|
|
5955
|
+
const [remoteFiles, consumption] = await Promise.all([
|
|
5956
|
+
this._listRemoteFiles(graph, spaceId, providerId, verbose),
|
|
5957
|
+
this._api?.getConsumption(spaceId) ?? Promise.reject(new Error("CueSyncApi is not bound to a CueApi instance"))
|
|
5958
|
+
]);
|
|
5959
|
+
const report = await compareLocalRemote(localFiles, remoteFiles);
|
|
5960
|
+
const toUpload = report.localNotOnRemote ?? [];
|
|
5961
|
+
const costRecords = toUpload.length > 0 ? await this.scanCost(toUpload) : [];
|
|
5962
|
+
const unitsToConsume = costRecords.reduce((sum, r) => sum + r.units, 0);
|
|
5963
|
+
return {
|
|
5964
|
+
costRecords,
|
|
5965
|
+
unitsToConsume,
|
|
5966
|
+
unitsAvailable: consumption.unitsAvailable,
|
|
5967
|
+
filesToUpload: toUpload.length,
|
|
5968
|
+
totalLocalFiles: localFiles.length
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5911
5971
|
async sync(localFiles, options) {
|
|
5912
5972
|
const { spaceId, providerId, userId, verbose } = options;
|
|
5913
5973
|
const token = await this._auth.getToken();
|
|
@@ -5916,7 +5976,11 @@ var CueSyncApi = class {
|
|
|
5916
5976
|
const graph = await this._getOrCreateGraph(spaceId, token);
|
|
5917
5977
|
if (verbose)
|
|
5918
5978
|
console.info("Listing remote files \u23F3");
|
|
5919
|
-
const remoteFiles = await
|
|
5979
|
+
const [remoteFiles, consumption] = await Promise.all([
|
|
5980
|
+
this._listRemoteFiles(graph, spaceId, providerId, verbose),
|
|
5981
|
+
this._api?.getConsumption(spaceId) ?? Promise.reject(new Error("CueSyncApi is not bound to a CueApi instance"))
|
|
5982
|
+
]);
|
|
5983
|
+
const { unitsAvailable } = consumption;
|
|
5920
5984
|
const report = await compareLocalRemote(localFiles, remoteFiles);
|
|
5921
5985
|
if (verbose) {
|
|
5922
5986
|
console.info(`Total local files: ${localFiles.length}`);
|
|
@@ -5929,27 +5993,20 @@ var CueSyncApi = class {
|
|
|
5929
5993
|
let syncSize = report.syncSize;
|
|
5930
5994
|
let failedUploads = 0;
|
|
5931
5995
|
let rdfWritten = false;
|
|
5932
|
-
let unitsConsumed = 0;
|
|
5933
|
-
let fileUnits = {};
|
|
5934
|
-
try {
|
|
5935
|
-
if (!_wasmInitPromise)
|
|
5936
|
-
_wasmInitPromise = _initWasm();
|
|
5937
|
-
await _wasmInitPromise;
|
|
5938
|
-
const entries = await Promise.all(
|
|
5939
|
-
localFiles.map(async (f) => ({
|
|
5940
|
-
originalPath: f.relativePath,
|
|
5941
|
-
data: new Uint8Array(await (0, import_promises3.readFile)(f.fullPath))
|
|
5942
|
-
}))
|
|
5943
|
-
);
|
|
5944
|
-
fileUnits = _fileMapFn(entries);
|
|
5945
|
-
} catch (err) {
|
|
5946
|
-
console.warn("[CueSyncApi] Unit map failed, proceeding without unit tracking:", err);
|
|
5947
|
-
}
|
|
5948
5996
|
const toUpload = report.localNotOnRemote ?? [];
|
|
5997
|
+
if (toUpload.length > 0) {
|
|
5998
|
+
const costRecords = await this.scanCost(toUpload);
|
|
5999
|
+
const unitsToConsume = costRecords.reduce((sum, r) => sum + r.units, 0);
|
|
6000
|
+
if (unitsToConsume > unitsAvailable) {
|
|
6001
|
+
throw new Error(
|
|
6002
|
+
`Insufficient units: ${unitsToConsume} units required but only ${unitsAvailable} available.`
|
|
6003
|
+
);
|
|
6004
|
+
}
|
|
6005
|
+
}
|
|
6006
|
+
await this._initPendingBatch(spaceId, token, verbose);
|
|
5949
6007
|
if (verbose && toUpload.length)
|
|
5950
6008
|
console.info("Syncing missing files \u23F3");
|
|
5951
6009
|
for (const file of toUpload) {
|
|
5952
|
-
let uploadSucceeded = false;
|
|
5953
6010
|
try {
|
|
5954
6011
|
const rawMeta = uploadedFileMetadata(
|
|
5955
6012
|
file.relativePath,
|
|
@@ -5966,12 +6023,16 @@ var CueSyncApi = class {
|
|
|
5966
6023
|
new Uint8Array(fileBuffer),
|
|
5967
6024
|
rawMeta
|
|
5968
6025
|
);
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
6026
|
+
await this._queueFileLocation({
|
|
6027
|
+
relativePath: file.relativePath,
|
|
6028
|
+
md5: file.md5,
|
|
6029
|
+
size: file.size,
|
|
6030
|
+
providerId,
|
|
6031
|
+
fileContentExists: false
|
|
6032
|
+
});
|
|
6033
|
+
rdfWritten = true;
|
|
5972
6034
|
syncCount += 1;
|
|
5973
6035
|
syncSize += file.size || 0;
|
|
5974
|
-
uploadSucceeded = true;
|
|
5975
6036
|
this._logProgress(syncCount, report.totalCount, syncSize, report.totalSize, verbose);
|
|
5976
6037
|
} catch (err) {
|
|
5977
6038
|
failedUploads += 1;
|
|
@@ -5979,54 +6040,31 @@ var CueSyncApi = class {
|
|
|
5979
6040
|
if (verbose)
|
|
5980
6041
|
console.error("[CueSyncApi] Upload error details:", err);
|
|
5981
6042
|
}
|
|
5982
|
-
if (uploadSucceeded) {
|
|
5983
|
-
const fileUnitsCount = fileUnits[file.relativePath] ?? 0;
|
|
5984
|
-
if (fileUnitsCount > 0) {
|
|
5985
|
-
unitsConsumed += fileUnitsCount;
|
|
5986
|
-
try {
|
|
5987
|
-
await this._projects.incrementUnitsConsumed(spaceId, fileUnitsCount, userId);
|
|
5988
|
-
} catch (err) {
|
|
5989
|
-
console.error(`[CueSyncApi] Failed to write clientSync entry for ${file.relativePath}:`, err);
|
|
5990
|
-
}
|
|
5991
|
-
}
|
|
5992
|
-
}
|
|
5993
6043
|
}
|
|
5994
6044
|
if (verbose && report.localNotOnRemotePathOnly.length)
|
|
5995
6045
|
console.info(`Syncing missing file locations (on provider "${providerId}") \u23F3`);
|
|
5996
6046
|
for (const file of report.localNotOnRemotePathOnly) {
|
|
5997
|
-
|
|
5998
|
-
file.relativePath,
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
);
|
|
6004
|
-
|
|
6005
|
-
throw new Error(`blob_name missing for ${file.relativePath}`);
|
|
6006
|
-
const uploaded = await this._uploadRdfMetadata(file, rawMeta, verbose);
|
|
6007
|
-
if (uploaded)
|
|
6008
|
-
rdfWritten = true;
|
|
6047
|
+
await this._queueFileLocation({
|
|
6048
|
+
relativePath: file.relativePath,
|
|
6049
|
+
md5: file.md5,
|
|
6050
|
+
size: file.size,
|
|
6051
|
+
providerId,
|
|
6052
|
+
fileContentExists: true
|
|
6053
|
+
});
|
|
6054
|
+
rdfWritten = true;
|
|
6009
6055
|
syncCount += 1;
|
|
6010
6056
|
syncSize += file.size || 0;
|
|
6011
|
-
const fileUnitsCount = fileUnits[file.relativePath] ?? 0;
|
|
6012
|
-
if (fileUnitsCount > 0) {
|
|
6013
|
-
unitsConsumed += fileUnitsCount;
|
|
6014
|
-
try {
|
|
6015
|
-
await this._projects.incrementUnitsConsumed(spaceId, fileUnitsCount, userId);
|
|
6016
|
-
} catch (err) {
|
|
6017
|
-
console.error(`[CueSyncApi] Failed to write clientSync entry for ${file.relativePath}:`, err);
|
|
6018
|
-
}
|
|
6019
|
-
}
|
|
6020
6057
|
this._logProgress(syncCount, report.totalCount, syncSize, report.totalSize, verbose);
|
|
6021
6058
|
}
|
|
6059
|
+
await this._drainPending(verbose);
|
|
6060
|
+
this._stopFlushTimer();
|
|
6022
6061
|
return {
|
|
6023
6062
|
syncCount,
|
|
6024
6063
|
syncSize,
|
|
6025
6064
|
failedUploads,
|
|
6026
6065
|
totalCount: report.totalCount,
|
|
6027
6066
|
totalSize: report.totalSize,
|
|
6028
|
-
rdfWritten
|
|
6029
|
-
unitsConsumed
|
|
6067
|
+
rdfWritten
|
|
6030
6068
|
};
|
|
6031
6069
|
}
|
|
6032
6070
|
async _getOrCreateGraph(spaceId, token) {
|
|
@@ -6105,30 +6143,77 @@ WHERE {
|
|
|
6105
6143
|
}
|
|
6106
6144
|
return map;
|
|
6107
6145
|
}
|
|
6108
|
-
async
|
|
6109
|
-
|
|
6110
|
-
|
|
6111
|
-
const
|
|
6112
|
-
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
const triples = await serializeRDF(namespace, writer);
|
|
6121
|
-
const uploaded = await this._blob.uploadProcessed(
|
|
6122
|
-
ttlMeta.blob_name,
|
|
6123
|
-
new Uint8Array(Buffer.from(triples, "utf-8")),
|
|
6124
|
-
ttlMeta
|
|
6125
|
-
);
|
|
6126
|
-
if (!uploaded && verbose) {
|
|
6127
|
-
console.info(
|
|
6128
|
-
`Graph data for ${file.relativePath} already exists \u2014 skipping \u26A0\uFE0F`
|
|
6146
|
+
async _initPendingBatch(spaceId, token, verbose) {
|
|
6147
|
+
this._pendingSpaceId = spaceId;
|
|
6148
|
+
this._pendingItems = [];
|
|
6149
|
+
const existing = await _loadPending(spaceId);
|
|
6150
|
+
if (existing && existing.items.length > 0) {
|
|
6151
|
+
if (verbose)
|
|
6152
|
+
console.info(`Flushing ${existing.items.length} pending file location(s) from previous sync \u23F3`);
|
|
6153
|
+
await this._flushBatch(existing.items, spaceId, token, verbose);
|
|
6154
|
+
}
|
|
6155
|
+
const timer = setInterval(() => {
|
|
6156
|
+
this._drainPending(verbose).catch(
|
|
6157
|
+
(err) => console.error("[CueSyncApi] Periodic flush failed:", err)
|
|
6129
6158
|
);
|
|
6159
|
+
}, 6e4);
|
|
6160
|
+
if (typeof timer === "object" && typeof timer.unref === "function") {
|
|
6161
|
+
timer.unref();
|
|
6162
|
+
}
|
|
6163
|
+
this._flushTimer = timer;
|
|
6164
|
+
}
|
|
6165
|
+
async _queueFileLocation(item) {
|
|
6166
|
+
this._pendingItems.push(item);
|
|
6167
|
+
if (this._pendingSpaceId) {
|
|
6168
|
+
await _savePending({ spaceId: this._pendingSpaceId, items: this._pendingItems });
|
|
6169
|
+
}
|
|
6170
|
+
}
|
|
6171
|
+
async _drainPending(verbose) {
|
|
6172
|
+
if (!this._pendingSpaceId || this._pendingItems.length === 0)
|
|
6173
|
+
return;
|
|
6174
|
+
const token = await this._auth.getToken();
|
|
6175
|
+
if (!token)
|
|
6176
|
+
return;
|
|
6177
|
+
await this._flushBatch(this._pendingItems, this._pendingSpaceId, token, verbose);
|
|
6178
|
+
}
|
|
6179
|
+
async _flushBatch(items, spaceId, token, verbose) {
|
|
6180
|
+
const snapshot = [...items];
|
|
6181
|
+
if (this._pendingSpaceId === spaceId)
|
|
6182
|
+
this._pendingItems = [];
|
|
6183
|
+
await _clearPending(spaceId);
|
|
6184
|
+
try {
|
|
6185
|
+
for (let i = 0; i < snapshot.length; i += FSS_BATCH_CHUNK_SIZE) {
|
|
6186
|
+
await this._postFssBatch(snapshot.slice(i, i + FSS_BATCH_CHUNK_SIZE), spaceId, token);
|
|
6187
|
+
}
|
|
6188
|
+
if (verbose)
|
|
6189
|
+
console.info(`Wrote ${snapshot.length} file location(s) to commands API \u2705`);
|
|
6190
|
+
} catch (err) {
|
|
6191
|
+
const restored = [...snapshot, ...this._pendingItems];
|
|
6192
|
+
this._pendingItems = restored;
|
|
6193
|
+
await _savePending({ spaceId, items: restored });
|
|
6194
|
+
throw err;
|
|
6195
|
+
}
|
|
6196
|
+
}
|
|
6197
|
+
async _postFssBatch(items, spaceId, token) {
|
|
6198
|
+
const response = await fetch(`${this._gatewayUrl}${ENDPOINT_FSS_BATCH}`, {
|
|
6199
|
+
method: "POST",
|
|
6200
|
+
headers: {
|
|
6201
|
+
Authorization: `Bearer ${token}`,
|
|
6202
|
+
"Content-Type": "application/json",
|
|
6203
|
+
"x-project-id": spaceId
|
|
6204
|
+
},
|
|
6205
|
+
body: JSON.stringify({ items })
|
|
6206
|
+
});
|
|
6207
|
+
if (!response.ok) {
|
|
6208
|
+
const body = await response.text().catch(() => "");
|
|
6209
|
+
throw new Error(`File structure batch POST failed: ${response.status} ${response.statusText}${body ? ` \u2014 ${body}` : ""}`);
|
|
6210
|
+
}
|
|
6211
|
+
}
|
|
6212
|
+
_stopFlushTimer() {
|
|
6213
|
+
if (this._flushTimer !== null) {
|
|
6214
|
+
clearInterval(this._flushTimer);
|
|
6215
|
+
this._flushTimer = null;
|
|
6130
6216
|
}
|
|
6131
|
-
return uploaded;
|
|
6132
6217
|
}
|
|
6133
6218
|
/**
|
|
6134
6219
|
* Scans `localFiles` and returns a per-extension cost breakdown.
|
|
@@ -6141,13 +6226,31 @@ WHERE {
|
|
|
6141
6226
|
if (!_wasmInitPromise)
|
|
6142
6227
|
_wasmInitPromise = _initWasm();
|
|
6143
6228
|
await _wasmInitPromise;
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6229
|
+
if (!_scanFn)
|
|
6230
|
+
throw new Error("WASM scan function not initialised");
|
|
6231
|
+
const BATCH_SIZE = 200;
|
|
6232
|
+
const merged = /* @__PURE__ */ new Map();
|
|
6233
|
+
for (let i = 0; i < localFiles.length; i += BATCH_SIZE) {
|
|
6234
|
+
const batch = localFiles.slice(i, i + BATCH_SIZE);
|
|
6235
|
+
const entries = await Promise.all(
|
|
6236
|
+
batch.map(async (f) => ({
|
|
6237
|
+
originalPath: f.relativePath,
|
|
6238
|
+
data: new Uint8Array(await (0, import_promises3.readFile)(f.fullPath))
|
|
6239
|
+
}))
|
|
6240
|
+
);
|
|
6241
|
+
const records = _scanFn(entries);
|
|
6242
|
+
for (const r of records) {
|
|
6243
|
+
const existing = merged.get(r.ext);
|
|
6244
|
+
if (existing) {
|
|
6245
|
+
existing.count += r.count;
|
|
6246
|
+
existing.units += r.units;
|
|
6247
|
+
existing.sizeMb += r.sizeMb;
|
|
6248
|
+
} else {
|
|
6249
|
+
merged.set(r.ext, { ...r });
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6253
|
+
return Array.from(merged.values());
|
|
6151
6254
|
}
|
|
6152
6255
|
_logProgress(syncCount, totalCount, syncSize, totalSize, verbose) {
|
|
6153
6256
|
if (!verbose || totalCount === 0)
|
|
@@ -6179,7 +6282,9 @@ var CueNode = class extends Cue {
|
|
|
6179
6282
|
}
|
|
6180
6283
|
const blob = new CueBlobStorage({ storageRaw, storageProcessed });
|
|
6181
6284
|
const syncApi = new CueSyncApi(this.auth, projects, blob, this._endpoints.gatewayUrl);
|
|
6182
|
-
|
|
6285
|
+
const api = new CueApi(this.auth, this._endpoints.gatewayUrl, projects, syncApi);
|
|
6286
|
+
syncApi._bindApi(api);
|
|
6287
|
+
return api;
|
|
6183
6288
|
}
|
|
6184
6289
|
};
|
|
6185
6290
|
|
|
@@ -6362,7 +6467,7 @@ async function dumpProcessedHandler(options) {
|
|
|
6362
6467
|
var import_fs2 = require("fs");
|
|
6363
6468
|
var import_stream = require("stream");
|
|
6364
6469
|
var import_fs3 = require("fs");
|
|
6365
|
-
var
|
|
6470
|
+
var import_zlib2 = require("zlib");
|
|
6366
6471
|
var import_promises5 = require("stream/promises");
|
|
6367
6472
|
var import_promises6 = require("fs/promises");
|
|
6368
6473
|
var import_auth9 = require("firebase/auth");
|
|
@@ -6542,7 +6647,7 @@ async function retryWithBackoff(fn, maxRetries, delayMs, label) {
|
|
|
6542
6647
|
async function _doGzip(filePath) {
|
|
6543
6648
|
const gzFilePath = `${filePath}.gz`;
|
|
6544
6649
|
await new Promise((resolve2, reject) => {
|
|
6545
|
-
const gzip = (0,
|
|
6650
|
+
const gzip = (0, import_zlib2.createGzip)();
|
|
6546
6651
|
const source = (0, import_fs3.createReadStream)(filePath);
|
|
6547
6652
|
const dest = (0, import_fs2.createWriteStream)(gzFilePath);
|
|
6548
6653
|
(0, import_promises5.pipeline)(source, gzip, dest).then(resolve2).catch(reject);
|
|
@@ -6898,24 +7003,46 @@ async function syncHandler(options) {
|
|
|
6898
7003
|
}
|
|
6899
7004
|
if (verbose)
|
|
6900
7005
|
console.info("Built sync base \u2705\n");
|
|
6901
|
-
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
|
|
6905
|
-
console.info(
|
|
7006
|
+
if (verbose)
|
|
7007
|
+
console.info("Authenticating \u23F3");
|
|
7008
|
+
const user = await cue.auth.signInWithApiKey(key, space);
|
|
7009
|
+
if (verbose)
|
|
7010
|
+
console.info("Authenticated \u2705\n");
|
|
7011
|
+
if (verbose)
|
|
7012
|
+
console.info("Checking sync preview \u23F3");
|
|
7013
|
+
const preview = await cue.api.sync.previewSync(localFiles, {
|
|
7014
|
+
spaceId: space,
|
|
7015
|
+
providerId: provider,
|
|
7016
|
+
userId: user.uid,
|
|
7017
|
+
verbose
|
|
7018
|
+
});
|
|
7019
|
+
console.info("Cost estimate (new files only):");
|
|
7020
|
+
if (preview.costRecords.length === 0) {
|
|
7021
|
+
console.info(" Nothing new to sync.");
|
|
7022
|
+
} else {
|
|
7023
|
+
for (const r of preview.costRecords) {
|
|
7024
|
+
console.info(` .${r.ext}: ${r.count} file(s) \u2192 ${r.units} unit(s)`);
|
|
7025
|
+
}
|
|
6906
7026
|
}
|
|
6907
|
-
console.info(`
|
|
7027
|
+
console.info(` New files: ${preview.filesToUpload}/${preview.totalLocalFiles}`);
|
|
7028
|
+
console.info(` Units required: ${preview.unitsToConsume}`);
|
|
7029
|
+
console.info(` Units available: ${preview.unitsAvailable}
|
|
6908
7030
|
`);
|
|
7031
|
+
if (preview.filesToUpload === 0) {
|
|
7032
|
+
console.info("Everything is already synced.");
|
|
7033
|
+
process.exit(0);
|
|
7034
|
+
}
|
|
7035
|
+
if (preview.unitsToConsume > preview.unitsAvailable) {
|
|
7036
|
+
console.error(
|
|
7037
|
+
`Insufficient units: ${preview.unitsToConsume} required but only ${preview.unitsAvailable} available.`
|
|
7038
|
+
);
|
|
7039
|
+
process.exit(1);
|
|
7040
|
+
}
|
|
6909
7041
|
const confirmed = await askConfirm("Continue with sync? (y/n) ");
|
|
6910
7042
|
if (!confirmed) {
|
|
6911
7043
|
console.info("Sync cancelled.");
|
|
6912
7044
|
process.exit(0);
|
|
6913
7045
|
}
|
|
6914
|
-
if (verbose)
|
|
6915
|
-
console.info("Authenticating \u23F3");
|
|
6916
|
-
const user = await cue.auth.signInWithApiKey(key, space);
|
|
6917
|
-
if (verbose)
|
|
6918
|
-
console.info("Authenticated \u2705\n");
|
|
6919
7046
|
const result = await cue.api.sync.sync(localFiles, {
|
|
6920
7047
|
spaceId: space,
|
|
6921
7048
|
providerId: provider,
|
|
@@ -6933,7 +7060,7 @@ async function syncHandler(options) {
|
|
|
6933
7060
|
console.info(`Threw RDF_WRITING_IDLE topic \u2705`);
|
|
6934
7061
|
} catch (error) {
|
|
6935
7062
|
if (verbose)
|
|
6936
|
-
console.error(`Error throwing RDF_WRITING_IDLE topic: ${error.message}`);
|
|
7063
|
+
console.error(`Error throwing RDF_WRITING_IDLE topic: ${error instanceof Error ? error.message : String(error)}`);
|
|
6937
7064
|
if (verbose)
|
|
6938
7065
|
console.warn("Continuing despite PubSub error in emulator mode...");
|
|
6939
7066
|
}
|
|
@@ -6961,22 +7088,22 @@ async function syncHandler(options) {
|
|
|
6961
7088
|
|
|
6962
7089
|
// apps/desktop/cue-cli/src/cue-cli-util-remove-rdf-star.ts
|
|
6963
7090
|
var import_fs7 = require("fs");
|
|
6964
|
-
var
|
|
7091
|
+
var import_zlib3 = require("zlib");
|
|
6965
7092
|
|
|
6966
7093
|
// libs/js/rdf-tools/src/lib/nq-to-nt.ts
|
|
6967
|
-
var
|
|
6968
|
-
var { quad, defaultGraph } =
|
|
7094
|
+
var import_n37 = require("n3");
|
|
7095
|
+
var { quad, defaultGraph } = import_n37.DataFactory;
|
|
6969
7096
|
|
|
6970
7097
|
// libs/js/rdf-tools/src/lib/remove-rdf-star.ts
|
|
6971
|
-
var
|
|
7098
|
+
var import_n38 = require("n3");
|
|
6972
7099
|
var import_stream2 = require("stream");
|
|
6973
7100
|
function isRDFStarTerm(term) {
|
|
6974
7101
|
return term.termType === "Quad";
|
|
6975
7102
|
}
|
|
6976
7103
|
function removeRDFStar(inputStream, starCount) {
|
|
6977
|
-
const parser = new
|
|
7104
|
+
const parser = new import_n38.Parser({ format: "N-Quads*" });
|
|
6978
7105
|
const outputStream = new import_stream2.PassThrough();
|
|
6979
|
-
const writer = new
|
|
7106
|
+
const writer = new import_n38.StreamWriter({ format: "N-Quads" });
|
|
6980
7107
|
writer.pipe(outputStream);
|
|
6981
7108
|
let count = 0;
|
|
6982
7109
|
parser.parse(inputStream, (error, quad2, prefixes4) => {
|
|
@@ -7009,7 +7136,7 @@ async function utilRemoveRdfStarHandler(options) {
|
|
|
7009
7136
|
if (verbose)
|
|
7010
7137
|
console.info(`Output: ${output}`);
|
|
7011
7138
|
const fileStream = (0, import_fs7.createReadStream)(input);
|
|
7012
|
-
const inputStream = isGzipped ? fileStream.pipe((0,
|
|
7139
|
+
const inputStream = isGzipped ? fileStream.pipe((0, import_zlib3.createGunzip)()) : fileStream;
|
|
7013
7140
|
let removed = 0;
|
|
7014
7141
|
const cleanStream = removeRDFStar(inputStream, (count) => {
|
|
7015
7142
|
removed = count;
|
|
@@ -7019,7 +7146,7 @@ async function utilRemoveRdfStarHandler(options) {
|
|
|
7019
7146
|
});
|
|
7020
7147
|
const writeStream = (0, import_fs7.createWriteStream)(output);
|
|
7021
7148
|
if (isGzipped) {
|
|
7022
|
-
const gzip = (0,
|
|
7149
|
+
const gzip = (0, import_zlib3.createGzip)();
|
|
7023
7150
|
gzip.pipe(writeStream);
|
|
7024
7151
|
for await (const chunk of cleanStream) {
|
|
7025
7152
|
gzip.write(chunk);
|
|
@@ -7047,11 +7174,11 @@ async function utilRemoveRdfStarHandler(options) {
|
|
|
7047
7174
|
var import_fs8 = require("fs");
|
|
7048
7175
|
|
|
7049
7176
|
// libs/js/rdf-compare/src/lib/js-rdf-compare.ts
|
|
7050
|
-
var
|
|
7177
|
+
var import_n39 = require("n3");
|
|
7051
7178
|
var import_jsonld = require("jsonld");
|
|
7052
7179
|
function parseTurtle(content) {
|
|
7053
7180
|
return new Promise((resolve2, reject) => {
|
|
7054
|
-
const parser = new
|
|
7181
|
+
const parser = new import_n39.Parser({ format: "Turtle" });
|
|
7055
7182
|
const quads = [];
|
|
7056
7183
|
parser.parse(content, (error, quad2) => {
|
|
7057
7184
|
if (error)
|
|
@@ -7065,7 +7192,7 @@ function parseTurtle(content) {
|
|
|
7065
7192
|
}
|
|
7066
7193
|
function quadsToNQuads(quads) {
|
|
7067
7194
|
return new Promise((resolve2, reject) => {
|
|
7068
|
-
const writer = new
|
|
7195
|
+
const writer = new import_n39.Writer({ format: "N-Quads" });
|
|
7069
7196
|
writer.addQuads(quads);
|
|
7070
7197
|
writer.end((error, result) => {
|
|
7071
7198
|
if (error)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qaecy/cue-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.33",
|
|
4
4
|
"description": "Cue CLI for QAECY platform",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
"jsonld": "8.3.3",
|
|
22
22
|
"jszip": "3.10.1",
|
|
23
23
|
"n3": "1.26.0",
|
|
24
|
-
"nanoid": "5.1.6",
|
|
25
24
|
"oxigraph": "0.5.3",
|
|
26
25
|
"protobufjs": "7.5.4",
|
|
27
26
|
"spark-md5": "3.0.2",
|