busa-cli 0.9.3 → 0.9.4
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/{chunk-C5BGRNMU.js → chunk-5P2ZNCL5.js} +80 -7
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
|
@@ -792,6 +792,34 @@ async function uploadAsset(config, opts) {
|
|
|
792
792
|
size: file.byteLength
|
|
793
793
|
};
|
|
794
794
|
}
|
|
795
|
+
var INLINE_TEXT_MAX_BYTES = 1024 * 1024;
|
|
796
|
+
async function putTextCommand(client, opts) {
|
|
797
|
+
const assetId = opts.assetId;
|
|
798
|
+
const text = opts.file ? readFileSync2(opts.file, "utf8") : opts.text;
|
|
799
|
+
if (opts.none) {
|
|
800
|
+
return client.assets.putText({ assetId, none: true });
|
|
801
|
+
}
|
|
802
|
+
if (text === void 0) {
|
|
803
|
+
throw new Error("Provide --text <string>, --file <path>, or --none.");
|
|
804
|
+
}
|
|
805
|
+
const sizeBytes = Buffer.byteLength(text, "utf8");
|
|
806
|
+
if (sizeBytes <= INLINE_TEXT_MAX_BYTES) {
|
|
807
|
+
return client.assets.putText({ assetId, text });
|
|
808
|
+
}
|
|
809
|
+
const upload = await client.assets.createTextUploadUrl({ assetId, sizeBytes });
|
|
810
|
+
const uploadResponse = await fetch(upload.uploadUrl, {
|
|
811
|
+
method: "PUT",
|
|
812
|
+
headers: { "content-type": "text/plain; charset=utf-8" },
|
|
813
|
+
body: text
|
|
814
|
+
});
|
|
815
|
+
if (!uploadResponse.ok) {
|
|
816
|
+
const body = await uploadResponse.text();
|
|
817
|
+
throw new Error(
|
|
818
|
+
`Text byte upload failed (${uploadResponse.status} ${uploadResponse.statusText})${body ? `: ${body}` : ""}`
|
|
819
|
+
);
|
|
820
|
+
}
|
|
821
|
+
return client.assets.putText({ assetId, storageKey: upload.storageKey });
|
|
822
|
+
}
|
|
795
823
|
function runAction(state, handler) {
|
|
796
824
|
return async (_opts, cmd) => {
|
|
797
825
|
const opts = cmd.optsWithGlobals();
|
|
@@ -840,9 +868,12 @@ function classifyKind(inner) {
|
|
|
840
868
|
return { kind: "json" };
|
|
841
869
|
}
|
|
842
870
|
function inputFields(inputSchema) {
|
|
871
|
+
if (inputSchema === void 0) return [];
|
|
843
872
|
const { inner } = unwrapSchema(inputSchema);
|
|
844
873
|
const shape = inner?.shape ?? (inner?.def?.type === "object" ? inner.def.shape : void 0);
|
|
845
|
-
if (!shape || typeof shape !== "object")
|
|
874
|
+
if (!shape || typeof shape !== "object") {
|
|
875
|
+
return [{ key: "input", kind: "json", required: true, root: true }];
|
|
876
|
+
}
|
|
846
877
|
const fields = [];
|
|
847
878
|
for (const [key, sub] of Object.entries(shape)) {
|
|
848
879
|
const { inner: unwrapped, optional } = unwrapSchema(sub);
|
|
@@ -900,13 +931,15 @@ function registerGeneratedCommands(program, state) {
|
|
|
900
931
|
OpenAPI: ${route.method} ${route.path}`);
|
|
901
932
|
leaf.action(
|
|
902
933
|
runAction(state, (client, opts) => {
|
|
903
|
-
|
|
934
|
+
let input = {};
|
|
904
935
|
for (const f of fields) {
|
|
905
936
|
if (GLOBAL_LONG_FLAGS.has(`--${kebab(f.key)}`)) continue;
|
|
906
937
|
const optKey = f.kind === "json" ? `${f.key}Json` : f.key;
|
|
907
938
|
const value = opts[optKey];
|
|
908
939
|
if (value === void 0) continue;
|
|
909
|
-
|
|
940
|
+
const parsed = f.kind === "json" ? parseJsonValue(value, `${kebab(f.key)}-json`) : value;
|
|
941
|
+
if (f.root) input = parsed;
|
|
942
|
+
else input[f.key] = parsed;
|
|
910
943
|
}
|
|
911
944
|
let target = client;
|
|
912
945
|
for (const segment of navPath) target = target[segment];
|
|
@@ -1066,12 +1099,16 @@ Examples:
|
|
|
1066
1099
|
return found;
|
|
1067
1100
|
})
|
|
1068
1101
|
);
|
|
1069
|
-
addGlobalFlags(bases.command("create")).description("Create a Base").requiredOption("--slug <slug>", "Base slug").requiredOption("--name <name>", "Base name").option("--field <slug:name:type...>", "field definition, repeatable").option("--fields-json <json|@file>", "field definitions as JSON array").option("--description <text>", "optional description").option("--parent-node-id <id>", "parent folder node id; omit for root").
|
|
1102
|
+
addGlobalFlags(bases.command("create")).description("Create a Base \u2014 review-first by default: returns a pending Change Request").requiredOption("--slug <slug>", "Base slug").requiredOption("--name <name>", "Base name").option("--field <slug:name:type...>", "field definition, repeatable").option("--fields-json <json|@file>", "field definitions as JSON array").option("--description <text>", "optional description").option("--parent-node-id <id>", "parent folder node id; omit for root").option(
|
|
1103
|
+
"--auto-merge",
|
|
1104
|
+
"skip review and create the Base immediately (default: propose a pending Change Request)"
|
|
1105
|
+
).addHelpText(
|
|
1070
1106
|
"after",
|
|
1071
1107
|
`
|
|
1072
1108
|
Examples:
|
|
1073
1109
|
busabase-cli bases create --slug products --name "\u4EA7\u54C1\u76EE\u5F55 Products" --field product_name:"Product Name":text
|
|
1074
|
-
busabase-cli bases create --slug products --name "\u4EA7\u54C1\u76EE\u5F55 Products" --fields-json @fields.json
|
|
1110
|
+
busabase-cli bases create --slug products --name "\u4EA7\u54C1\u76EE\u5F55 Products" --fields-json @fields.json
|
|
1111
|
+
busabase-cli bases create --slug products --name "Products" --auto-merge # skip review, create immediately`
|
|
1075
1112
|
).action(
|
|
1076
1113
|
runAction(
|
|
1077
1114
|
state,
|
|
@@ -1080,7 +1117,8 @@ Examples:
|
|
|
1080
1117
|
name: opts.name,
|
|
1081
1118
|
description: opts.description,
|
|
1082
1119
|
parentNodeId: opts.parentNodeId,
|
|
1083
|
-
fields: parseFieldDefinitions(opts)
|
|
1120
|
+
fields: parseFieldDefinitions(opts),
|
|
1121
|
+
...opts.autoMerge ? { autoMerge: true } : {}
|
|
1084
1122
|
})
|
|
1085
1123
|
)
|
|
1086
1124
|
);
|
|
@@ -1241,7 +1279,42 @@ Example:
|
|
|
1241
1279
|
|
|
1242
1280
|
Use the JSON output directly in an attachment field value, e.g. {"cover_image":[<output>]}.`
|
|
1243
1281
|
).action(runAction(state, (_client, opts, config) => uploadAsset(config, opts)));
|
|
1244
|
-
|
|
1282
|
+
const assetsCommand = program.command("assets").description("Assets");
|
|
1283
|
+
addUploadCommand(assetsCommand);
|
|
1284
|
+
addGlobalFlags(assetsCommand.command("put-text")).description("Write (or mark none) an asset's Drive Grep Retrieval text slot").requiredOption("--asset-id <id>", "asset id").option("--text <string>", "inline text (\u22641MB)").option("--file <path>", "read text from a local file instead of --text").option("--none", "mark as having no extractable text (e.g. a scanned, image-only PDF)").addHelpText(
|
|
1285
|
+
"after",
|
|
1286
|
+
`
|
|
1287
|
+
Examples:
|
|
1288
|
+
busabase-cli assets put-text --asset-id ast_123 --file ./extracted.txt
|
|
1289
|
+
busabase-cli assets put-text --asset-id ast_123 --text "plain text"
|
|
1290
|
+
busabase-cli assets put-text --asset-id ast_123 --none`
|
|
1291
|
+
).action(runAction(state, (client, opts) => putTextCommand(client, opts)));
|
|
1292
|
+
addGlobalFlags(assetsCommand.command("grep")).description("Search every text-bearing asset in scope").requiredOption("--pattern <regex>", "literal or regex pattern").option("--flags <flags>", 'RegExp flags, e.g. "i" for case-insensitive').option("--asset-ids <ids...>", "scope: specific asset ids").option("--drive-path <path>", "scope: Drive/Skill mounted path prefix").option("--mime-types <types...>", "scope: MIME types").option("--max-matches <n>", "max matches (default 100, cap 1000)", parsePositiveInt).option("--context-lines <n>", "lines of before/after context (default 0, cap 10)", parseNum).action(
|
|
1293
|
+
runAction(
|
|
1294
|
+
state,
|
|
1295
|
+
(client, opts) => client.assets.grep({
|
|
1296
|
+
pattern: opts.pattern,
|
|
1297
|
+
flags: opts.flags,
|
|
1298
|
+
scope: opts.assetIds || opts.drivePath || opts.mimeTypes ? {
|
|
1299
|
+
assetIds: opts.assetIds,
|
|
1300
|
+
drivePath: opts.drivePath,
|
|
1301
|
+
mimeTypes: opts.mimeTypes
|
|
1302
|
+
} : void 0,
|
|
1303
|
+
maxMatches: opts.maxMatches,
|
|
1304
|
+
contextLines: opts.contextLines
|
|
1305
|
+
})
|
|
1306
|
+
)
|
|
1307
|
+
);
|
|
1308
|
+
addGlobalFlags(assetsCommand.command("read-lines")).description("Read an exact line range from an asset's text (range capped at 2000 lines)").requiredOption("--asset-id <id>", "asset id").requiredOption("--start-line <n>", "first line (1-based)", parsePositiveInt).requiredOption("--end-line <n>", "last line (1-based)", parsePositiveInt).action(
|
|
1309
|
+
runAction(
|
|
1310
|
+
state,
|
|
1311
|
+
(client, opts) => client.assets.readTextLines({
|
|
1312
|
+
assetId: opts.assetId,
|
|
1313
|
+
startLine: opts.startLine,
|
|
1314
|
+
endLine: opts.endLine
|
|
1315
|
+
})
|
|
1316
|
+
)
|
|
1317
|
+
);
|
|
1245
1318
|
addGlobalFlags(program.command("api")).description("Raw request to any /api/v1 endpoint").addOption(
|
|
1246
1319
|
new Option("--method <get|post|put|delete>", "HTTP method").choices(["get", "post", "put", "delete"]).makeOptionMandatory()
|
|
1247
1320
|
).requiredOption("--path <p>", "path under /api/v1, e.g. /bases").option("--query <k=v...>", "query-string param, repeatable").option("--body-json <json>", "JSON request body").action(
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "busa-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.4",
|
|
4
4
|
"description": "Command-line client for the Busabase OpenAPI REST API. Talks to a local or remote `busabase server`. Short-name alias for busabase-cli.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/busabase/busabase/tree/main/apps/busabase-cli",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"busabase-sdk": "0.9.
|
|
34
|
+
"busabase-sdk": "0.9.4",
|
|
35
35
|
"commander": "^14.0.0"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|