@standards/cli 1.0.0-alpha.445 → 1.0.0-alpha.447
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/dist/bin.mjs +52 -31
- package/package.json +4 -4
package/dist/bin.mjs
CHANGED
|
@@ -3,17 +3,17 @@
|
|
|
3
3
|
import { t as discoverBundles } from "./discover-bundles-DPpEZVv0.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { styleText } from "node:util";
|
|
6
|
-
import { BundleConflictError, StandardsRequestError, createTransport, previewBundleSync, syncBundle } from "@standards/client";
|
|
6
|
+
import { BundleConflictError, StandardsRequestError, createTransport, previewBundleSync, syncBundle, uploadAll } from "@standards/client";
|
|
7
7
|
import { Command, Option } from "commander";
|
|
8
8
|
import { BUNDLE_LOCALES, COUNT_MODES, DECISION_TYPE_AGENT_SETUP, DECISION_TYPE_BUNDLE_SETUP, ENVIRONMENT_HARNESSES, ENVIRONMENT_IMAGES, ENVIRONMENT_SIZES, LINK_MAX_MS, NotFoundError, PROVIDER_NAMES, RECORD_ACCESS_ROLES, RESOURCE_VISIBILITIES, SchemaError, SchemaErrorCode, ValidationError, canonicalStringify, diffSchemaState, environmentHarness, formatByteSize, formatDecisionLink, isEnvironmentHarnessId, isPlainRecord, isSkillRepository, parseRecordAccessRole, parseSchemaState, parseSkillSource, schemaStateSourcePayload } from "@standards/schema";
|
|
9
|
-
import { createWriteStream } from "node:fs";
|
|
9
|
+
import { createWriteStream, openAsBlob } from "node:fs";
|
|
10
10
|
import { chmod, lstat, mkdir, readFile, readdir, readlink, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
11
11
|
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
12
12
|
import Table from "cli-table3";
|
|
13
13
|
import { StandardsRequestError as StandardsRequestError$1, TURN_END_TYPES, createAppClient, openAgentStream, schemaApiErrorCode } from "@standards/client/app";
|
|
14
|
-
import { homedir, hostname } from "node:os";
|
|
15
14
|
import { Readable } from "node:stream";
|
|
16
15
|
import { pipeline } from "node:stream/promises";
|
|
16
|
+
import { homedir, hostname } from "node:os";
|
|
17
17
|
import { buildOperationPath, recordsOperations } from "@standards/schema/api";
|
|
18
18
|
import { stdin } from "node:process";
|
|
19
19
|
import { createInterface } from "node:readline/promises";
|
|
@@ -960,6 +960,36 @@ function registerEnvironmentsCommand(program) {
|
|
|
960
960
|
printDone(`Environment ${id} archived.`);
|
|
961
961
|
});
|
|
962
962
|
}
|
|
963
|
+
// src/commands/transfer.ts
|
|
964
|
+
/**
|
|
965
|
+
* Local files sent straight to storage, resumable, read from disk as they go
|
|
966
|
+
* (never whole in memory). One answer per path, in order; the first file the
|
|
967
|
+
* API refuses stops the command with its reason, and the files of the batch
|
|
968
|
+
* already stored are deleted.
|
|
969
|
+
*/
|
|
970
|
+
async function uploadLocalFiles(client, paths, options = {}) {
|
|
971
|
+
const files = await Promise.all(paths.map(async (path) => Object.assign(await openAsBlob(path), { name: basename(path) })));
|
|
972
|
+
return await uploadAll(client, {
|
|
973
|
+
files,
|
|
974
|
+
protocol: "tus",
|
|
975
|
+
...options.attachTo === void 0 ? {} : { attachTo: options.attachTo }
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
/**
|
|
979
|
+
* Streams a response's body to `output`, or to stdout without one. A file
|
|
980
|
+
* left half written is removed: a truncated file would pass for a whole one.
|
|
981
|
+
*/
|
|
982
|
+
async function writeBody(response, output) {
|
|
983
|
+
if (!response.body) throw new StandardsRequestError(response.status, "The response had no body");
|
|
984
|
+
const source = Readable.fromWeb(response.body);
|
|
985
|
+
if (!output) return await pipeline(source, process.stdout);
|
|
986
|
+
try {
|
|
987
|
+
await pipeline(source, createWriteStream(output));
|
|
988
|
+
} catch (error) {
|
|
989
|
+
await unlink(output).catch(() => void 0);
|
|
990
|
+
throw error;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
963
993
|
// src/commands/files.ts
|
|
964
994
|
function registerFilesCommand(program) {
|
|
965
995
|
const files = program.command("files").description("Upload, list, download and delete files");
|
|
@@ -975,15 +1005,17 @@ function registerFilesCommand(program) {
|
|
|
975
1005
|
files.command("get").description("Get a file by ID").argument("<id>", "file ID").action(async (id, _opts, cmd) => {
|
|
976
1006
|
formatOutput(await getAppClientFromCommand(cmd).files.get({ id }), getFormat(cmd));
|
|
977
1007
|
});
|
|
978
|
-
files.command("upload").description("Upload local files (private); prints the stored files and their IDs").argument("<paths...>", "local file paths
|
|
979
|
-
|
|
980
|
-
formatOutput(await getAppClientFromCommand(cmd).files.upload({ files: uploads }), getFormat(cmd));
|
|
1008
|
+
files.command("upload").description("Upload local files (private), resuming after a dropped connection; prints the stored files and their IDs").argument("<paths...>", "local file paths").action(async (paths, _opts, cmd) => {
|
|
1009
|
+
formatOutput((await uploadLocalFiles(getAppClientFromCommand(cmd), paths)).map(({ file }) => file), getFormat(cmd));
|
|
981
1010
|
});
|
|
982
1011
|
files.command("content").description("Download a file's bytes (to stdout, or -o <file>)").argument("<id>", "file ID").option("-o, --output <file>", "write to a file instead of stdout").action(async (id, opts, cmd) => {
|
|
983
|
-
const {
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
1012
|
+
const { url } = await getAppClientFromCommand(cmd).files.signedUrl({
|
|
1013
|
+
id,
|
|
1014
|
+
download: true
|
|
1015
|
+
});
|
|
1016
|
+
const response = await fetch(url);
|
|
1017
|
+
if (!response.ok) throw new StandardsRequestError(response.status, `Storage refused the download (HTTP ${response.status})`);
|
|
1018
|
+
await writeBody(response, opts.output);
|
|
987
1019
|
});
|
|
988
1020
|
files.command("delete").description("Delete a file you uploaded and its stored bytes (not a file in a document pack)").argument("<id>", "file ID").option("--yes", "delete without confirmation").action(async (id, opts, cmd) => {
|
|
989
1021
|
requireConfirmation(opts.yes, "Deleting a file purges its bytes. Re-run with \"--yes\" to confirm.");
|
|
@@ -1453,22 +1485,13 @@ function registerRecordsCommand(program) {
|
|
|
1453
1485
|
filter: opts.filter,
|
|
1454
1486
|
sort: opts.sort
|
|
1455
1487
|
});
|
|
1456
|
-
|
|
1488
|
+
await writeBody(await client.postRaw(buildOperationPath(recordsOperations.export, { objectName }), {
|
|
1457
1489
|
q: opts.query ?? "",
|
|
1458
1490
|
columns: parseCsvList(opts.columns),
|
|
1459
1491
|
...filters ? { filters } : {},
|
|
1460
1492
|
...sorts ? { sorts } : {},
|
|
1461
1493
|
timezone: opts.timezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
1462
|
-
});
|
|
1463
|
-
if (!response.body) throw new StandardsRequestError(response.status, "The export response had no body");
|
|
1464
|
-
const source = Readable.fromWeb(response.body);
|
|
1465
|
-
if (!opts.output) return await pipeline(source, process.stdout);
|
|
1466
|
-
try {
|
|
1467
|
-
await pipeline(source, createWriteStream(opts.output));
|
|
1468
|
-
} catch (error) {
|
|
1469
|
-
await unlink(opts.output).catch(() => void 0);
|
|
1470
|
-
throw error;
|
|
1471
|
-
}
|
|
1494
|
+
}), opts.output);
|
|
1472
1495
|
});
|
|
1473
1496
|
records.command("set-logo").description("Set a record's image to the logo of a company's domain").argument("<object>", "object name (e.g. companies)").argument("<recordId>", "record ID").argument("<domain>", "website or bare domain (e.g. acme.com)").action(async (objectName, recordId, domain, _opts, cmd) => {
|
|
1474
1497
|
formatOutput(await getAppClientFromCommand(cmd).records.setLogo({
|
|
@@ -1478,16 +1501,14 @@ function registerRecordsCommand(program) {
|
|
|
1478
1501
|
}), getFormat(cmd));
|
|
1479
1502
|
});
|
|
1480
1503
|
records.command("attach-document").description("Upload and attach a local file to a record").argument("<object>", "object name (e.g. contacts)").argument("<recordId>", "record ID").requiredOption("--file <path>", "local file path to upload").option("--attribute <attr>", "attribute name to attach the document to").option("--parent-id <folderId>", "parent folder ID").option("--title <title>", "document title (defaults to filename)").action(async (objectName, recordId, opts, cmd) => {
|
|
1481
|
-
const
|
|
1482
|
-
const fileName = basename(opts.file);
|
|
1483
|
-
formatOutput(await getAppClientFromCommand(cmd).records.attachDocument({
|
|
1504
|
+
const [uploaded] = await uploadLocalFiles(getAppClientFromCommand(cmd), [opts.file], { attachTo: {
|
|
1484
1505
|
objectName,
|
|
1485
|
-
|
|
1486
|
-
title: opts.title ??
|
|
1506
|
+
recordId,
|
|
1507
|
+
title: opts.title ?? basename(opts.file),
|
|
1487
1508
|
...opts.attribute ? { attributeName: opts.attribute } : {},
|
|
1488
|
-
...opts.parentId ? { parentId: opts.parentId } : {}
|
|
1489
|
-
|
|
1490
|
-
|
|
1509
|
+
...opts.parentId ? { parentId: opts.parentId } : {}
|
|
1510
|
+
} });
|
|
1511
|
+
formatOutput(uploaded?.attached, getFormat(cmd));
|
|
1491
1512
|
});
|
|
1492
1513
|
records.command("attach-file").description("Attach an already uploaded file to a record").argument("<object>", "object name (e.g. contacts)").argument("<recordId>", "record ID").requiredOption("--file-id <fileId>", "ID of a private uploaded file").option("--attribute <attr>", "document attribute (defaults to the record's attachments)").option("--document-id <documentId>", "append to this document's pack instead of creating one").option("--title <title>", "title of a new document (defaults to the file name without its extension)").action(async (objectName, recordId, opts, cmd) => {
|
|
1493
1514
|
formatOutput(await getAppClientFromCommand(cmd).records.attachFile({
|
|
@@ -2586,11 +2607,11 @@ async function readFolder(client, dir, skipped) {
|
|
|
2586
2607
|
});
|
|
2587
2608
|
continue;
|
|
2588
2609
|
}
|
|
2589
|
-
const [stored] = await client
|
|
2610
|
+
const [stored] = await uploadLocalFiles(client, [absolute]);
|
|
2590
2611
|
if (!stored) throw new Error(`The upload of ${absolute} answered no file`);
|
|
2591
2612
|
files.push({
|
|
2592
2613
|
path,
|
|
2593
|
-
fileId: stored.id
|
|
2614
|
+
fileId: stored.file.id
|
|
2594
2615
|
});
|
|
2595
2616
|
}
|
|
2596
2617
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@standards/cli",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.447",
|
|
4
4
|
"description": "CLI tool to interact with Standards API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"node": ">=22"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@standards/client": "1.0.0-alpha.
|
|
28
|
-
"@standards/constants": "1.0.0-alpha.
|
|
29
|
-
"@standards/schema": "1.0.0-alpha.
|
|
27
|
+
"@standards/client": "1.0.0-alpha.447",
|
|
28
|
+
"@standards/constants": "1.0.0-alpha.447",
|
|
29
|
+
"@standards/schema": "1.0.0-alpha.447",
|
|
30
30
|
"cli-table3": "^0.6.5",
|
|
31
31
|
"commander": "^13.1.0",
|
|
32
32
|
"jiti": "2.7.0",
|