@qaecy/cue-cli 0.0.13 → 0.0.15
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/main.js +92 -25
- package/package.json +1 -1
- package/readme.md +14 -1
package/main.js
CHANGED
|
@@ -211,6 +211,7 @@ var BUCKET_CHAT_SESSIONS = "spaces_chats_eu_west6";
|
|
|
211
211
|
var BUCKET_RAW = "spaces_raw_eu_west6";
|
|
212
212
|
var BUCKET_PROCESSED = "spaces_processed_eu_west6";
|
|
213
213
|
var BUCKET_LOGS = "spaces_logs_eu_west6";
|
|
214
|
+
var BUCKET_PUBLIC = "cue_public_eu_west6";
|
|
214
215
|
var COLLECTION_CHAT_SESSIONS = "chatSessions";
|
|
215
216
|
var COLLECTION_ORGANIZATIONS = "organizations";
|
|
216
217
|
var COLLECTION_PROJECTS = "projects";
|
|
@@ -272,6 +273,9 @@ var CueFirebase = class _CueFirebase {
|
|
|
272
273
|
get storageChatSessions() {
|
|
273
274
|
return this._storageChatSessions;
|
|
274
275
|
}
|
|
276
|
+
get storagePublic() {
|
|
277
|
+
return this._storagePublic;
|
|
278
|
+
}
|
|
275
279
|
get collectionChatSessions() {
|
|
276
280
|
return this._collectionChatSessions;
|
|
277
281
|
}
|
|
@@ -342,6 +346,7 @@ var CueFirebase = class _CueFirebase {
|
|
|
342
346
|
this._storageRaw = (0, import_storage.getStorage)(app, BUCKET_RAW);
|
|
343
347
|
this._storageChatSessions = (0, import_storage.getStorage)(app, BUCKET_CHAT_SESSIONS);
|
|
344
348
|
this._storageLogs = (0, import_storage.getStorage)(app, BUCKET_LOGS);
|
|
349
|
+
this._storagePublic = (0, import_storage.getStorage)(app, BUCKET_PUBLIC);
|
|
345
350
|
this._collectionChatSessions = (0, import_firestore.collection)(
|
|
346
351
|
(0, import_firestore.getFirestore)(app),
|
|
347
352
|
COLLECTION_CHAT_SESSIONS
|
|
@@ -377,6 +382,8 @@ var CueFirebase = class _CueFirebase {
|
|
|
377
382
|
throw new Error("Storage chat sessions is not initialized");
|
|
378
383
|
if (this._storageLogs === void 0)
|
|
379
384
|
throw new Error("Storage logs is not initialized");
|
|
385
|
+
if (this._storagePublic === void 0)
|
|
386
|
+
throw new Error("Storage public is not initialized");
|
|
380
387
|
if (this._app === void 0)
|
|
381
388
|
throw new Error("App is not initialized");
|
|
382
389
|
const functions = (0, import_functions.getFunctions)(this._app, GCP_REGION);
|
|
@@ -387,6 +394,7 @@ var CueFirebase = class _CueFirebase {
|
|
|
387
394
|
(0, import_storage.connectStorageEmulator)(this._storageRaw, "localhost", 9199);
|
|
388
395
|
(0, import_storage.connectStorageEmulator)(this._storageChatSessions, "localhost", 9199);
|
|
389
396
|
(0, import_storage.connectStorageEmulator)(this._storageLogs, "localhost", 9199);
|
|
397
|
+
(0, import_storage.connectStorageEmulator)(this._storagePublic, "localhost", 9199);
|
|
390
398
|
if (!this._muted)
|
|
391
399
|
console.info("Firebase emulators attached");
|
|
392
400
|
}
|
|
@@ -402,6 +410,7 @@ var import_storage2 = require("firebase/storage");
|
|
|
402
410
|
var qaecyPrefixes = {
|
|
403
411
|
qcy: "https://dev.qaecy.com/ont#",
|
|
404
412
|
"qcy-e": "https://dev.qaecy.com/enum#",
|
|
413
|
+
"qcy-f": "https://dev.qaecy.com/functions#",
|
|
405
414
|
obc: "https://w3id.org/obc#",
|
|
406
415
|
// OpenBIM Components
|
|
407
416
|
dicc: "https://w3id.org/digitalconstruction/0.5/Contexts#",
|
|
@@ -5736,20 +5745,64 @@ async function uploadFile(file, spaceId, userId, providerId) {
|
|
|
5736
5745
|
const storage = firebase.storageRaw;
|
|
5737
5746
|
const fileRef = (0, import_storage5.ref)(storage, rawFileMetadata.blob_name);
|
|
5738
5747
|
const fileBuffer = await (0, import_promises6.readFile)(file.fullPath);
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5748
|
+
const maxRetries = 3;
|
|
5749
|
+
let attempt = 0;
|
|
5750
|
+
let lastError = null;
|
|
5751
|
+
while (attempt < maxRetries) {
|
|
5752
|
+
try {
|
|
5753
|
+
await new Promise((resolve, reject) => {
|
|
5754
|
+
const uploadTask = (0, import_storage5.uploadBytesResumable)(fileRef, fileBuffer, {
|
|
5755
|
+
customMetadata: rawFileMetadata
|
|
5756
|
+
});
|
|
5757
|
+
uploadTask.on(
|
|
5758
|
+
"state_changed",
|
|
5759
|
+
null,
|
|
5760
|
+
(error) => {
|
|
5761
|
+
const blobName = rawFileMetadata.blob_name;
|
|
5762
|
+
console.error("[uploadFile] Error uploading file:", {
|
|
5763
|
+
filePath: file.fullPath,
|
|
5764
|
+
relativePath: file.relativePath,
|
|
5765
|
+
md5: file.md5,
|
|
5766
|
+
blobName,
|
|
5767
|
+
blobNameLength: blobName?.length,
|
|
5768
|
+
blobNameIsUnusual: blobName && (blobName.length > 256 || /[^\w\-./]/.test(blobName)),
|
|
5769
|
+
errorCode: error?.code,
|
|
5770
|
+
errorMessage: error?.message,
|
|
5771
|
+
errorPayload: error,
|
|
5772
|
+
fileBufferSize: fileBuffer?.length,
|
|
5773
|
+
rawFileMetadataKeys: Object.keys(rawFileMetadata),
|
|
5774
|
+
rawFileMetadataLength: Object.keys(rawFileMetadata).length,
|
|
5775
|
+
attempt
|
|
5776
|
+
});
|
|
5777
|
+
reject(error);
|
|
5778
|
+
},
|
|
5779
|
+
() => resolve()
|
|
5780
|
+
);
|
|
5781
|
+
if (!uploadTask) {
|
|
5782
|
+
console.error("[uploadFile] Upload task could not be created:", {
|
|
5783
|
+
filePath: file.fullPath,
|
|
5784
|
+
relativePath: file.relativePath,
|
|
5785
|
+
md5: file.md5,
|
|
5786
|
+
blobName: rawFileMetadata.blob_name,
|
|
5787
|
+
attempt
|
|
5788
|
+
});
|
|
5789
|
+
reject(new Error("Upload task could not be created"));
|
|
5790
|
+
}
|
|
5791
|
+
});
|
|
5792
|
+
lastError = null;
|
|
5793
|
+
break;
|
|
5794
|
+
} catch (err) {
|
|
5795
|
+
lastError = err;
|
|
5796
|
+
attempt++;
|
|
5797
|
+
if (attempt < maxRetries) {
|
|
5798
|
+
console.warn(`[uploadFile] Retry attempt ${attempt} for file: ${file.fullPath}`);
|
|
5799
|
+
await new Promise((res) => setTimeout(res, 1e3 * attempt));
|
|
5800
|
+
}
|
|
5751
5801
|
}
|
|
5752
|
-
}
|
|
5802
|
+
}
|
|
5803
|
+
if (lastError) {
|
|
5804
|
+
throw lastError;
|
|
5805
|
+
}
|
|
5753
5806
|
return rawFileMetadata;
|
|
5754
5807
|
}
|
|
5755
5808
|
|
|
@@ -5869,20 +5922,31 @@ async function syncHandler(options) {
|
|
|
5869
5922
|
if (verbose && report.localNotOnRemote.length)
|
|
5870
5923
|
console.info("Syncing missing files \u23F3");
|
|
5871
5924
|
let rdfWritten = false;
|
|
5925
|
+
let failedUploads = 0;
|
|
5872
5926
|
for (const file of report.localNotOnRemote) {
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
|
|
5927
|
+
let rawFileMetadata;
|
|
5928
|
+
try {
|
|
5929
|
+
rawFileMetadata = await uploadFile(file, space, userId, provider);
|
|
5930
|
+
await uploadFileRDF(file, rawFileMetadata, verbose);
|
|
5931
|
+
syncCount += 1;
|
|
5932
|
+
syncSize += file.size || 0;
|
|
5933
|
+
const pct = Math.floor(syncCount / report.totalCount * 100);
|
|
5934
|
+
if (verbose && report.totalCount > 0 && syncCount % Math.ceil(report.totalCount / 100) === 0) {
|
|
5935
|
+
console.info(
|
|
5936
|
+
`Progress: ${pct}% (${syncCount}/$${report.totalCount} files, ${fileSizePretty(syncSize)}/${fileSizePretty(
|
|
5937
|
+
report.totalSize
|
|
5938
|
+
)})`
|
|
5939
|
+
);
|
|
5940
|
+
}
|
|
5941
|
+
rdfWritten = true;
|
|
5942
|
+
} catch (err) {
|
|
5943
|
+
failedUploads += 1;
|
|
5944
|
+
console.error(`[syncHandler] Failed to upload file: ${file.fullPath}`);
|
|
5945
|
+
if (verbose) {
|
|
5946
|
+
console.error("[syncHandler] Upload error details:", err);
|
|
5947
|
+
}
|
|
5948
|
+
continue;
|
|
5884
5949
|
}
|
|
5885
|
-
rdfWritten = true;
|
|
5886
5950
|
}
|
|
5887
5951
|
const zipDeletePromise = zip ? deleteUnzipped(path) : Promise.resolve();
|
|
5888
5952
|
if (verbose && report.localNotOnRemotePathOnly.length)
|
|
@@ -5932,6 +5996,9 @@ async function syncHandler(options) {
|
|
|
5932
5996
|
if (verbose) {
|
|
5933
5997
|
console.info("");
|
|
5934
5998
|
console.info(`Sync finished \u{1F680}\u{1F680}\u{1F680}`);
|
|
5999
|
+
if (failedUploads > 0) {
|
|
6000
|
+
console.warn(`Total files failed to upload: ${failedUploads}`);
|
|
6001
|
+
}
|
|
5935
6002
|
}
|
|
5936
6003
|
} catch (err) {
|
|
5937
6004
|
console.error("Error:", err);
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -18,4 +18,17 @@ You need an API key in order to authenticate with the CLI tool.
|
|
|
18
18
|
### Sync a folder
|
|
19
19
|
To sync the current dir to the space with id `<space-id>` under the provider id `d_drive` (provider id is used to distinguish different document sources and if none is provided the default provider is used). The `v`-flag is for verbose logging so we can follow the progress.
|
|
20
20
|
|
|
21
|
-
`npx @qaecy/cue-cli sync -s <space-id> -p . --provider d_drive -v`
|
|
21
|
+
`npx @qaecy/cue-cli sync -s <space-id> -p . --provider d_drive -v`
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Sync command options
|
|
25
|
+
|
|
26
|
+
| Option | Description | Default |
|
|
27
|
+
|-----------------------|------------------------------------------------------------------------------------------------------|--------------|
|
|
28
|
+
| `-s, --space <id>` | Specify the space ID (required) | N/A |
|
|
29
|
+
| `-p, --path <id>` | Specify the folder path to sync (required) | N/A |
|
|
30
|
+
| `-k, --key <api-key>` | Specify the API key (or set `CUE_API_KEY` env variable) | N/A |
|
|
31
|
+
| `--provider <id>` | Specify the provider ID (e.g., sharepoint, drive, dropbox). Leave empty for default provider | `""` |
|
|
32
|
+
| `-v, --verbose` | Enable verbose output | `false` |
|
|
33
|
+
| `-e, --emulators` | Use emulators for sync | `false` |
|
|
34
|
+
| `-z, --zip` | Include zipped content. Will be unzipped to `<zip_path>_unzipped`. Max uncompressed size: 500 MB, max recursion depth: 3. Cleans up unzipped files after sync. | `false` |
|