@qaecy/cue-cli 0.0.42 → 0.0.44
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 +117 -34
- package/package.json +1 -1
package/main.js
CHANGED
|
@@ -8347,6 +8347,9 @@ WHERE {
|
|
|
8347
8347
|
{ relativePath: file.relativePath, md5: file.md5, size: file.size, providerId, fileContentExists: false }
|
|
8348
8348
|
);
|
|
8349
8349
|
}
|
|
8350
|
+
async getTierNames() {
|
|
8351
|
+
return this._fetchTierNames();
|
|
8352
|
+
}
|
|
8350
8353
|
async _fetchTierNames() {
|
|
8351
8354
|
try {
|
|
8352
8355
|
const text = await this._blob.downloadPublic("tier-names.json");
|
|
@@ -9202,7 +9205,7 @@ function askConfirm(question) {
|
|
|
9202
9205
|
});
|
|
9203
9206
|
}
|
|
9204
9207
|
async function syncHandler(options) {
|
|
9205
|
-
const {
|
|
9208
|
+
const { path, verbose, provider, emulators, zip, legacy, metadataOnly } = options;
|
|
9206
9209
|
try {
|
|
9207
9210
|
const cue = new CueNode({
|
|
9208
9211
|
apiKey: FIREBASE_CONFIG().apiKey,
|
|
@@ -9218,6 +9221,45 @@ async function syncHandler(options) {
|
|
|
9218
9221
|
);
|
|
9219
9222
|
process.exit(1);
|
|
9220
9223
|
}
|
|
9224
|
+
let space = options.space;
|
|
9225
|
+
if (!space) {
|
|
9226
|
+
const tempUser = await cue.auth.signInWithApiKey(key).catch((err) => {
|
|
9227
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
9228
|
+
console.error(`Couldn't authenticate. ${cause}`);
|
|
9229
|
+
process.exit(1);
|
|
9230
|
+
});
|
|
9231
|
+
const allProjects = await cue.projects.listProjects();
|
|
9232
|
+
const syncable = allProjects.filter(
|
|
9233
|
+
(p) => p.syncers?.includes(tempUser.uid) || p.admins?.includes(tempUser.uid)
|
|
9234
|
+
);
|
|
9235
|
+
if (syncable.length === 0) {
|
|
9236
|
+
console.error("You do not have syncer or admin rights on any project.");
|
|
9237
|
+
process.exit(1);
|
|
9238
|
+
}
|
|
9239
|
+
if (syncable.length === 1) {
|
|
9240
|
+
space = syncable[0].id;
|
|
9241
|
+
console.info(`Using project: ${syncable[0].name} (${space})`);
|
|
9242
|
+
} else {
|
|
9243
|
+
console.log("\nProjects you can sync to:");
|
|
9244
|
+
syncable.forEach((p, i) => console.log(` ${i + 1}. ${p.name} (${p.id})`));
|
|
9245
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
9246
|
+
space = await new Promise((resolveInput) => {
|
|
9247
|
+
rl.question(`Enter number (1-${syncable.length}): `, (answer) => {
|
|
9248
|
+
rl.close();
|
|
9249
|
+
const idx = parseInt(answer.trim(), 10) - 1;
|
|
9250
|
+
if (idx >= 0 && idx < syncable.length) {
|
|
9251
|
+
resolveInput(syncable[idx].id);
|
|
9252
|
+
} else {
|
|
9253
|
+
console.error("Invalid selection.");
|
|
9254
|
+
process.exit(1);
|
|
9255
|
+
}
|
|
9256
|
+
});
|
|
9257
|
+
});
|
|
9258
|
+
}
|
|
9259
|
+
}
|
|
9260
|
+
if (!space) {
|
|
9261
|
+
process.exit(1);
|
|
9262
|
+
}
|
|
9221
9263
|
if (verbose)
|
|
9222
9264
|
console.info("Building sync base \u23F3");
|
|
9223
9265
|
const resolvedPath = (0, import_path3.resolve)(path);
|
|
@@ -9546,39 +9588,66 @@ Triples only in file 2 (${result.triplesOnlyInFile2.size}):`);
|
|
|
9546
9588
|
|
|
9547
9589
|
// apps/desktop/cue-cli/src/cue-cli-create-project.ts
|
|
9548
9590
|
var readline2 = __toESM(require("readline"));
|
|
9549
|
-
function
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9591
|
+
function createAsker(rl) {
|
|
9592
|
+
const lineQueue = [];
|
|
9593
|
+
const waiters = [];
|
|
9594
|
+
let closed = false;
|
|
9595
|
+
rl.on("line", (line) => {
|
|
9596
|
+
if (waiters.length > 0) {
|
|
9597
|
+
const waiter = waiters.shift();
|
|
9598
|
+
if (waiter) {
|
|
9599
|
+
process.stdout.write(line + "\n");
|
|
9600
|
+
waiter.resolve(line.trim());
|
|
9558
9601
|
}
|
|
9602
|
+
} else {
|
|
9603
|
+
lineQueue.push(line);
|
|
9559
9604
|
}
|
|
9560
9605
|
});
|
|
9606
|
+
rl.on("close", () => {
|
|
9607
|
+
closed = true;
|
|
9608
|
+
for (const waiter of waiters.splice(0)) {
|
|
9609
|
+
waiter.reject(new Error("INPUT_CLOSED"));
|
|
9610
|
+
}
|
|
9611
|
+
});
|
|
9612
|
+
return (question) => {
|
|
9613
|
+
process.stdout.write(question);
|
|
9614
|
+
if (lineQueue.length > 0) {
|
|
9615
|
+
const answer = lineQueue.shift() ?? "";
|
|
9616
|
+
process.stdout.write(answer + "\n");
|
|
9617
|
+
return Promise.resolve(answer.trim());
|
|
9618
|
+
}
|
|
9619
|
+
if (closed) {
|
|
9620
|
+
return Promise.reject(new Error("INPUT_CLOSED"));
|
|
9621
|
+
}
|
|
9622
|
+
return new Promise((resolve2, reject) => {
|
|
9623
|
+
waiters.push({ resolve: resolve2, reject });
|
|
9624
|
+
});
|
|
9625
|
+
};
|
|
9561
9626
|
}
|
|
9562
|
-
async function pickOne(
|
|
9627
|
+
async function pickOne(ask, label, items, display) {
|
|
9563
9628
|
console.log(`
|
|
9564
9629
|
${label}`);
|
|
9565
9630
|
items.forEach((item, i) => console.log(` ${i + 1}. ${display(item)}`));
|
|
9566
|
-
|
|
9567
|
-
|
|
9631
|
+
let selected = [];
|
|
9632
|
+
while (selected.length === 0 || items.length === 1) {
|
|
9633
|
+
const answer = await ask(`Enter number (1-${items.length}): `);
|
|
9568
9634
|
const idx = parseInt(answer, 10) - 1;
|
|
9569
|
-
if (idx >= 0 && idx < items.length)
|
|
9570
|
-
|
|
9635
|
+
if (idx >= 0 && idx < items.length) {
|
|
9636
|
+
selected = [items[idx]];
|
|
9637
|
+
break;
|
|
9638
|
+
}
|
|
9571
9639
|
console.log(" Invalid selection, try again.");
|
|
9572
9640
|
}
|
|
9641
|
+
return selected[0];
|
|
9573
9642
|
}
|
|
9574
|
-
async function pickMultipleOrAll(
|
|
9643
|
+
async function pickMultipleOrAll(ask, label, items, display) {
|
|
9575
9644
|
if (items.length === 0)
|
|
9576
9645
|
return [];
|
|
9577
9646
|
console.log(`
|
|
9578
9647
|
${label}`);
|
|
9579
9648
|
items.forEach((item, i) => console.log(` ${i + 1}. ${display(item)}`));
|
|
9580
9649
|
console.log(` 0. All`);
|
|
9581
|
-
const answer = await ask(
|
|
9650
|
+
const answer = await ask(`Enter comma-separated numbers or 0 for all: `);
|
|
9582
9651
|
if (answer === "0")
|
|
9583
9652
|
return items;
|
|
9584
9653
|
const indices = answer.split(",").map((s) => parseInt(s.trim(), 10) - 1).filter((i) => i >= 0 && i < items.length);
|
|
@@ -9586,7 +9655,8 @@ ${label}`);
|
|
|
9586
9655
|
}
|
|
9587
9656
|
async function createProjectHandler(options) {
|
|
9588
9657
|
const { emulators, verbose } = options;
|
|
9589
|
-
const rl = readline2.createInterface({ input: process.stdin,
|
|
9658
|
+
const rl = readline2.createInterface({ input: process.stdin, terminal: process.stdout.isTTY });
|
|
9659
|
+
const ask = createAsker(rl);
|
|
9590
9660
|
try {
|
|
9591
9661
|
const key = options.key ?? process.env.CUE_API_KEY;
|
|
9592
9662
|
if (!key) {
|
|
@@ -9623,7 +9693,7 @@ async function createProjectHandler(options) {
|
|
|
9623
9693
|
console.error("No organisations found on the platform.");
|
|
9624
9694
|
process.exit(1);
|
|
9625
9695
|
}
|
|
9626
|
-
const picked = await pickOne(
|
|
9696
|
+
const picked = await pickOne(ask, "Select organisation:", allOrgs, (o) => `${o.name} (${o.id})`);
|
|
9627
9697
|
orgId = picked.id;
|
|
9628
9698
|
orgName = picked.name;
|
|
9629
9699
|
callerIsOrgAdmin = picked.admins?.includes(user.uid) ?? false;
|
|
@@ -9637,7 +9707,7 @@ async function createProjectHandler(options) {
|
|
|
9637
9707
|
console.error("You are not an admin of any organisation. Cannot create a project.");
|
|
9638
9708
|
process.exit(1);
|
|
9639
9709
|
}
|
|
9640
|
-
const picked = await pickOne(
|
|
9710
|
+
const picked = await pickOne(ask, "Select organisation:", adminOrgs, (o) => `${o.name} (${o.id})`);
|
|
9641
9711
|
orgId = picked.id;
|
|
9642
9712
|
orgName = picked.name;
|
|
9643
9713
|
callerIsOrgAdmin = true;
|
|
@@ -9645,13 +9715,18 @@ async function createProjectHandler(options) {
|
|
|
9645
9715
|
}
|
|
9646
9716
|
console.log(`
|
|
9647
9717
|
Organisation: ${orgName} (${orgId})`);
|
|
9648
|
-
const projectName = await ask(
|
|
9718
|
+
const projectName = await ask("\nProject name: ");
|
|
9649
9719
|
if (!projectName) {
|
|
9650
9720
|
console.error("Project name is required.");
|
|
9651
9721
|
process.exit(1);
|
|
9652
9722
|
}
|
|
9723
|
+
const tierNames = await cue.api.sync.getTierNames().catch(() => ({}));
|
|
9724
|
+
const tierLabel = (key2, fallback, isDefault = false) => {
|
|
9725
|
+
const name = tierNames[key2] ?? fallback;
|
|
9726
|
+
return isDefault ? `${name} (default)` : name;
|
|
9727
|
+
};
|
|
9653
9728
|
const graphType = await pickOne(
|
|
9654
|
-
|
|
9729
|
+
ask,
|
|
9655
9730
|
"Select graph backend (default: QLever):",
|
|
9656
9731
|
[
|
|
9657
9732
|
{ value: "qlever", label: "QLever (recommended)" },
|
|
@@ -9660,12 +9735,12 @@ Organisation: ${orgName} (${orgId})`);
|
|
|
9660
9735
|
(item) => item.label
|
|
9661
9736
|
).then((item) => item.value);
|
|
9662
9737
|
const tier = await pickOne(
|
|
9663
|
-
|
|
9664
|
-
"Select processing tier
|
|
9738
|
+
ask,
|
|
9739
|
+
"Select processing tier:",
|
|
9665
9740
|
[
|
|
9666
|
-
{ value: "l", label: "
|
|
9667
|
-
{ value: "m", label: "
|
|
9668
|
-
{ value: "s", label: "
|
|
9741
|
+
{ value: "l", label: tierLabel("l", "Large", true) },
|
|
9742
|
+
{ value: "m", label: tierLabel("m", "Medium") },
|
|
9743
|
+
{ value: "s", label: tierLabel("s", "Small") }
|
|
9669
9744
|
],
|
|
9670
9745
|
(item) => item.label
|
|
9671
9746
|
).then((item) => item.value);
|
|
@@ -9680,7 +9755,7 @@ Organisation: ${orgName} (${orgId})`);
|
|
|
9680
9755
|
}
|
|
9681
9756
|
while (selectedAdmins.length === 0) {
|
|
9682
9757
|
selectedAdmins = await pickMultipleOrAll(
|
|
9683
|
-
|
|
9758
|
+
ask,
|
|
9684
9759
|
"Select project admin(s) \u2014 at least one required:",
|
|
9685
9760
|
orgAdmins,
|
|
9686
9761
|
(m) => `${m.name} <${m.email}>`
|
|
@@ -9692,20 +9767,20 @@ Organisation: ${orgName} (${orgId})`);
|
|
|
9692
9767
|
const nonAdminMembers = orgMembers.filter((m) => !selectedAdmins.some((a5) => a5.uid === m.uid));
|
|
9693
9768
|
if (nonAdminMembers.length > 0) {
|
|
9694
9769
|
selectedMembers = await pickMultipleOrAll(
|
|
9695
|
-
|
|
9770
|
+
ask,
|
|
9696
9771
|
"Select project members:",
|
|
9697
9772
|
nonAdminMembers,
|
|
9698
9773
|
(m) => `${m.name} <${m.email}>${m.isAdmin ? " (org admin)" : ""}`
|
|
9699
9774
|
);
|
|
9700
9775
|
}
|
|
9701
9776
|
if (selectedMembers.length > 0) {
|
|
9702
|
-
const answer = await ask(
|
|
9777
|
+
const answer = await ask(`
|
|
9703
9778
|
Set all selected members as syncers as well? (Y/n): `);
|
|
9704
9779
|
if (answer.toLowerCase() !== "n") {
|
|
9705
9780
|
selectedSyncers = selectedMembers;
|
|
9706
9781
|
} else {
|
|
9707
9782
|
selectedSyncers = await pickMultipleOrAll(
|
|
9708
|
-
|
|
9783
|
+
ask,
|
|
9709
9784
|
"Select project syncers:",
|
|
9710
9785
|
selectedMembers,
|
|
9711
9786
|
(m) => `${m.name} <${m.email}>`
|
|
@@ -9725,7 +9800,7 @@ Set all selected members as syncers as well? (Y/n): `);
|
|
|
9725
9800
|
console.log(` Members : ${selectedMembers.length === 0 ? "(none)" : selectedMembers.map((m) => m.email).join(", ")}`);
|
|
9726
9801
|
console.log(` Syncers : ${selectedSyncers.length === 0 ? "(none)" : selectedSyncers.map((m) => m.email).join(", ")}`);
|
|
9727
9802
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
9728
|
-
const confirm = await ask(
|
|
9803
|
+
const confirm = await ask("\nCreate project? (Y/n): ");
|
|
9729
9804
|
if (confirm.toLowerCase() === "n") {
|
|
9730
9805
|
console.log("Aborted.");
|
|
9731
9806
|
process.exit(0);
|
|
@@ -9770,10 +9845,18 @@ Project created \u2705`);
|
|
|
9770
9845
|
console.log(` ID : ${created["id"]}`);
|
|
9771
9846
|
console.log(` Name : ${created["name"]}`);
|
|
9772
9847
|
} catch (err) {
|
|
9773
|
-
if (err.message === "INPUT_CLOSED") {
|
|
9848
|
+
if (err instanceof Error && err.message === "INPUT_CLOSED") {
|
|
9774
9849
|
console.error("Aborted: input stream closed before all prompts were answered.");
|
|
9775
9850
|
process.exit(1);
|
|
9776
9851
|
}
|
|
9852
|
+
if (err instanceof Error && err.message.includes("403")) {
|
|
9853
|
+
console.error("You do not have permission to create a project. Only organization admins can create projects.");
|
|
9854
|
+
process.exit(1);
|
|
9855
|
+
}
|
|
9856
|
+
if (err instanceof Error && /\b5\d\d\b/.test(err.message)) {
|
|
9857
|
+
console.error(`Server error: Project creation failed. Contact your administrator.`);
|
|
9858
|
+
process.exit(1);
|
|
9859
|
+
}
|
|
9777
9860
|
throw err;
|
|
9778
9861
|
} finally {
|
|
9779
9862
|
rl.close();
|
|
@@ -9794,7 +9877,7 @@ try {
|
|
|
9794
9877
|
}
|
|
9795
9878
|
var program = new import_commander.Command();
|
|
9796
9879
|
program.name("cue-cli").description("Cue Command Line Interface").version(packageJson.version);
|
|
9797
|
-
program.command("sync").description("Sync files to Cue").
|
|
9880
|
+
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);
|
|
9798
9881
|
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);
|
|
9799
9882
|
program.command("compare").description("Compares folder content to files already updated to Cue").requiredOption("-s, --space <id>", "Specify the space ID (required)").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 temporarily unzip files with same logic as when syncing and delete them again after the comparison)", false).action(compareHandler);
|
|
9800
9883
|
program.command("dump-processed").description("Dump processed files to local folder").requiredOption("-s, --space <id>", "Specify the space ID (required)").requiredOption("-p, --processor <id>", "Id of the processor to dump processed files from (required) [eg. writers-blob, processors-cad-files]").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).action(dumpProcessedHandler);
|