busa-cli 0.9.4 → 0.9.6
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-5P2ZNCL5.js → chunk-5ZYF74IE.js} +156 -7
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
|
@@ -124,6 +124,7 @@ import { createHash as createHash2 } from "crypto";
|
|
|
124
124
|
import { readFileSync as readFileSync2 } from "fs";
|
|
125
125
|
import { basename, extname } from "path";
|
|
126
126
|
import {
|
|
127
|
+
CREATABLE_NODE_TYPES,
|
|
127
128
|
cloudContract,
|
|
128
129
|
createBusabaseClient,
|
|
129
130
|
DEFAULT_BASE_URL as DEFAULT_BASE_URL2,
|
|
@@ -363,9 +364,9 @@ async function oauthLogin(baseUrl, useBrowser) {
|
|
|
363
364
|
throw new Error(`Token exchange failed (HTTP ${tokenRes.status})${text ? `: ${text}` : ""}`);
|
|
364
365
|
}
|
|
365
366
|
const payload = await tokenRes.json();
|
|
366
|
-
const token = payload.token ?? payload.accessToken;
|
|
367
|
-
if (!token) throw new Error("Token exchange returned no
|
|
368
|
-
return { token, expiresAt: payload.expiresAt };
|
|
367
|
+
const token = payload.apiKey ?? payload.token ?? payload.accessToken;
|
|
368
|
+
if (!token) throw new Error("Token exchange returned no credential.");
|
|
369
|
+
return { token, expiresAt: payload.expiresAt ?? void 0 };
|
|
369
370
|
}
|
|
370
371
|
async function refreshToken(baseUrl, token) {
|
|
371
372
|
const res = await fetch(`${baseUrl}/api/oauth/refresh`, {
|
|
@@ -889,8 +890,10 @@ var GENERATED_SKIP = /* @__PURE__ */ new Set([
|
|
|
889
890
|
// `whoami`
|
|
890
891
|
"records.search",
|
|
891
892
|
// `records by-field-text`
|
|
892
|
-
"records.listChangeRequests"
|
|
893
|
+
"records.listChangeRequests",
|
|
893
894
|
// `records change-requests`
|
|
895
|
+
"airapps.listFiles"
|
|
896
|
+
// `airapps files`
|
|
894
897
|
]);
|
|
895
898
|
function registerGeneratedCommands(program, state) {
|
|
896
899
|
const getGroup = (displayName, tag) => program.commands.find((c2) => c2.name() === displayName) ?? program.command(displayName).description(tag ?? `${displayName} endpoints`);
|
|
@@ -1052,7 +1055,7 @@ The flags below skip the menu (handy for scripts / CI):
|
|
|
1052
1055
|
const nodes = program.command("nodes").description("Workspace node tree");
|
|
1053
1056
|
addGlobalFlags(nodes.command("list")).description("Workspace node tree").action(runAction(state, (client) => client.nodes.list()));
|
|
1054
1057
|
addGlobalFlags(nodes.command("create-change-request")).description("Propose a new node via a Change Request").addOption(
|
|
1055
|
-
new Option(
|
|
1058
|
+
new Option(`--type <${CREATABLE_NODE_TYPES.join("|")}>`, "node type").choices(CREATABLE_NODE_TYPES).makeOptionMandatory()
|
|
1056
1059
|
).requiredOption("--slug <slug>", "node slug").requiredOption("--name <name>", "node name").option("--description <text>", "optional node description").option("--parent-node-id <id>", "parent folder node id; omit for root").option("--message <text>", "reviewer-facing Change Request message").option("--submitted-by <name>", "producer label").option("--field <slug:name:type...>", "base field, repeatable (for --type base)").option("--fields-json <json|@file>", "base fields as JSON array (for --type base)").option("--asset-id <id>", "backing Asset id (required for --type file)").addHelpText(
|
|
1057
1060
|
"after",
|
|
1058
1061
|
`
|
|
@@ -1089,6 +1092,28 @@ Examples:
|
|
|
1089
1092
|
});
|
|
1090
1093
|
})
|
|
1091
1094
|
);
|
|
1095
|
+
addGlobalFlags(nodes.command("move")).description("Move or reorder a node (applied immediately, no review needed)").requiredOption("--node-id <id>", "node id to move").option("--parent-node-id <id>", "new parent folder node id; omit to keep the current parent").option(
|
|
1096
|
+
"--position <n>",
|
|
1097
|
+
"new position among the target parent's children",
|
|
1098
|
+
(v) => Number.parseInt(v, 10)
|
|
1099
|
+
).option("--message <text>", "Change Request message").option("--submitted-by <name>", "producer label").addHelpText(
|
|
1100
|
+
"after",
|
|
1101
|
+
`
|
|
1102
|
+
Examples:
|
|
1103
|
+
busabase-cli nodes move --node-id nod_123 --position 0
|
|
1104
|
+
busabase-cli nodes move --node-id nod_123 --parent-node-id nod_456 --position 2`
|
|
1105
|
+
).action(
|
|
1106
|
+
runAction(
|
|
1107
|
+
state,
|
|
1108
|
+
(client, opts) => client.nodes.move({
|
|
1109
|
+
nodeId: opts.nodeId,
|
|
1110
|
+
parentNodeId: opts.parentNodeId,
|
|
1111
|
+
position: opts.position,
|
|
1112
|
+
message: opts.message,
|
|
1113
|
+
submittedBy: opts.submittedBy
|
|
1114
|
+
})
|
|
1115
|
+
)
|
|
1116
|
+
);
|
|
1092
1117
|
const bases = program.command("bases").description("Bases (structured tables)");
|
|
1093
1118
|
addGlobalFlags(bases.command("list")).description("List Bases in the active space").action(runAction(state, (client) => client.bases.list()));
|
|
1094
1119
|
addGlobalFlags(bases.command("get")).description("Get one Base by slug").requiredOption("--slug <slug>", "Base slug").action(
|
|
@@ -1190,6 +1215,95 @@ Examples:
|
|
|
1190
1215
|
})
|
|
1191
1216
|
)
|
|
1192
1217
|
);
|
|
1218
|
+
const airapps = program.command("airapps").description("AirApps (sandboxed mini-apps)");
|
|
1219
|
+
addGlobalFlags(airapps.command("list")).description("List AirApps in the active space").action(runAction(state, (client) => client.airapps.list()));
|
|
1220
|
+
addGlobalFlags(airapps.command("get")).description("Get one AirApp by node id").requiredOption("--node-id <id>", "AirApp node id").action(
|
|
1221
|
+
runAction(state, (client, opts) => client.airapps.get({ nodeId: opts.nodeId }))
|
|
1222
|
+
);
|
|
1223
|
+
addGlobalFlags(airapps.command("create")).description("Create an AirApp \u2014 review-first by default: returns a pending Change Request").requiredOption("--slug <slug>", "AirApp slug").requiredOption("--name <name>", "AirApp name").option("--description <text>", "optional description").option("--parent-node-id <id>", "parent folder node id; omit for root").addOption(
|
|
1224
|
+
new Option(
|
|
1225
|
+
"--visibility <private|workspace|public>",
|
|
1226
|
+
"AirApp visibility (default private)"
|
|
1227
|
+
).choices(["private", "workspace", "public"])
|
|
1228
|
+
).option("--version <semver>", "AirApp version (default 0.1.0)").option(
|
|
1229
|
+
"--files-json <json|@file>",
|
|
1230
|
+
'files as a JSON array, or @file.json \u2014 text files {"path","content","mimeType?"} or asset-backed files {"path","assetId","displayName?","mimeType?"}'
|
|
1231
|
+
).addOption(
|
|
1232
|
+
new Option(
|
|
1233
|
+
"--merge-mode <merge|replace>",
|
|
1234
|
+
"how --files-json combines with the default scaffold (default merge)"
|
|
1235
|
+
).choices(["merge", "replace"])
|
|
1236
|
+
).option(
|
|
1237
|
+
"--auto-merge",
|
|
1238
|
+
"skip review and create the AirApp immediately (default: propose a pending Change Request)"
|
|
1239
|
+
).addHelpText(
|
|
1240
|
+
"after",
|
|
1241
|
+
`
|
|
1242
|
+
mergeMode explains how --files-json combines with the AirApp's default scaffold:
|
|
1243
|
+
merge (default) \u2014 your files are layered on top of the default Hono-template
|
|
1244
|
+
scaffold by path; supply just a few files (e.g. one custom
|
|
1245
|
+
route) and still get the rest of the scaffold for any path
|
|
1246
|
+
you didn't provide yourself.
|
|
1247
|
+
replace \u2014 your files replace the scaffold entirely; use this when
|
|
1248
|
+
handing over a complete, self-contained project (e.g. a Vite
|
|
1249
|
+
app) so you don't end up with stray unrelated default files
|
|
1250
|
+
mixed in.
|
|
1251
|
+
|
|
1252
|
+
Examples:
|
|
1253
|
+
busabase-cli airapps create --slug hello-app --name "Hello App" --files-json @files.json
|
|
1254
|
+
busabase-cli airapps create --slug vite-app --name "Vite App" --files-json @files.json --merge-mode replace
|
|
1255
|
+
busabase-cli airapps create --slug hello-app --name "Hello App" --files-json @files.json --auto-merge # skip review, create immediately`
|
|
1256
|
+
).action(
|
|
1257
|
+
runAction(
|
|
1258
|
+
state,
|
|
1259
|
+
(client, opts) => client.airapps.create({
|
|
1260
|
+
slug: opts.slug,
|
|
1261
|
+
name: opts.name,
|
|
1262
|
+
description: opts.description,
|
|
1263
|
+
parentNodeId: opts.parentNodeId,
|
|
1264
|
+
visibility: opts.visibility,
|
|
1265
|
+
version: opts.version,
|
|
1266
|
+
files: opts.filesJson ? parseJsonValue(opts.filesJson, "files-json") : void 0,
|
|
1267
|
+
mergeMode: opts.mergeMode,
|
|
1268
|
+
...opts.autoMerge ? { autoMerge: true } : {}
|
|
1269
|
+
})
|
|
1270
|
+
)
|
|
1271
|
+
);
|
|
1272
|
+
addGlobalFlags(airapps.command("files")).description("List an AirApp's files").requiredOption("--node-id <id>", "AirApp node id").action(
|
|
1273
|
+
runAction(
|
|
1274
|
+
state,
|
|
1275
|
+
(client, opts) => client.airapps.listFiles({ nodeId: opts.nodeId })
|
|
1276
|
+
)
|
|
1277
|
+
);
|
|
1278
|
+
addGlobalFlags(airapps.command("read-file")).description("Read one AirApp file's content").requiredOption("--node-id <id>", "AirApp node id").requiredOption("--path <path>", "file path within the AirApp").action(
|
|
1279
|
+
runAction(
|
|
1280
|
+
state,
|
|
1281
|
+
(client, opts) => client.airapps.readFile({ nodeId: opts.nodeId, filePath: opts.path })
|
|
1282
|
+
)
|
|
1283
|
+
);
|
|
1284
|
+
addGlobalFlags(airapps.command("create-change-request")).description("Propose file changes to an existing AirApp via a Change Request").requiredOption("--node-id <id>", "AirApp node id").requiredOption(
|
|
1285
|
+
"--operations-json <json|@file>",
|
|
1286
|
+
'file operations as a JSON array, or @file.json \u2014 "create"/"update" (text {"kind","path","content","mimeType?"} or asset-backed {"kind","path","assetId","displayName?","mimeType?"}), "delete" {"kind","path"}, or "metadata_update" {"kind","metadata":{"entryFile?","visibility?","version?"}}'
|
|
1287
|
+
).option("--message <text>", "reviewer-facing Change Request message").option("--submitted-by <name>", "producer label").addHelpText(
|
|
1288
|
+
"after",
|
|
1289
|
+
`
|
|
1290
|
+
Examples:
|
|
1291
|
+
busabase-cli airapps create-change-request --node-id nod_123 --operations-json @operations.json
|
|
1292
|
+
busabase-cli airapps create-change-request --node-id nod_123 --operations-json '[{"kind":"update","path":"index.js","content":"..."}]' --message "Fix handler bug"`
|
|
1293
|
+
).action(
|
|
1294
|
+
runAction(
|
|
1295
|
+
state,
|
|
1296
|
+
(client, opts) => client.airapps.createChangeRequest({
|
|
1297
|
+
nodeId: opts.nodeId,
|
|
1298
|
+
message: opts.message,
|
|
1299
|
+
submittedBy: opts.submittedBy,
|
|
1300
|
+
operations: parseJsonValue(
|
|
1301
|
+
opts.operationsJson,
|
|
1302
|
+
"operations-json"
|
|
1303
|
+
)
|
|
1304
|
+
})
|
|
1305
|
+
)
|
|
1306
|
+
);
|
|
1193
1307
|
const records = program.command("records").description("Records");
|
|
1194
1308
|
addGlobalFlags(records.command("list")).description("List records").option("--limit <n>", "max results (1-100)", parseLimit).option("--base-id <id>", "restrict to one Base").option("--cursor <cursor>", "opaque nextCursor from a previous page").action(
|
|
1195
1309
|
runAction(state, (_client, opts, config) => {
|
|
@@ -1261,16 +1375,51 @@ Examples:
|
|
|
1261
1375
|
(client, opts) => client.changeRequests.merge({ changeRequestId: opts.changeRequestId })
|
|
1262
1376
|
)
|
|
1263
1377
|
);
|
|
1264
|
-
addGlobalFlags(program.command("search")).description("Full-text search").requiredOption("--query <q>", "search query").option("--limit <n>", "max results", parseNum).option("--offset <n>", "results offset", parseNum).
|
|
1378
|
+
addGlobalFlags(program.command("search")).description("Full-text search").requiredOption("--query <q>", "search query").option("--limit <n>", "max results", parseNum).option("--offset <n>", "results offset", parseNum).option(
|
|
1379
|
+
"--sources <sources...>",
|
|
1380
|
+
'restrict which content to search: "records", "files", and/or "names" (default: all three)'
|
|
1381
|
+
).action(
|
|
1265
1382
|
runAction(
|
|
1266
1383
|
state,
|
|
1267
1384
|
(client, opts) => client.search({
|
|
1268
1385
|
query: opts.query,
|
|
1269
1386
|
limit: opts.limit,
|
|
1270
|
-
offset: opts.offset
|
|
1387
|
+
offset: opts.offset,
|
|
1388
|
+
sources: opts.sources
|
|
1271
1389
|
})
|
|
1272
1390
|
)
|
|
1273
1391
|
);
|
|
1392
|
+
addGlobalFlags(program.command("grep")).description(
|
|
1393
|
+
"Search files, Docs, and Base records with one pattern (unified grep; use `assets grep` for files-only)"
|
|
1394
|
+
).requiredOption("--pattern <regex>", "literal or regex pattern").option("--flags <flags>", 'RegExp flags, e.g. "i" for case-insensitive').option(
|
|
1395
|
+
"--sources <sources...>",
|
|
1396
|
+
'sources to scan: "files", "docs", and/or "records" (default: all three)'
|
|
1397
|
+
).option("--asset-ids <ids...>", "files scope: specific asset ids").option("--drive-path <path>", "files scope: Drive/Skill mounted path prefix").option("--mime-types <types...>", "files scope: MIME types").option("--node-ids <ids...>", "docs scope: specific Doc node ids").option("--base-ids <ids...>", "records scope: specific Base ids").option("--base-slugs <slugs...>", "records scope: specific Base slugs").option(
|
|
1398
|
+
"--max-matches <n>",
|
|
1399
|
+
"max matches, shared across sources (default 100, cap 1000)",
|
|
1400
|
+
parsePositiveInt
|
|
1401
|
+
).option("--context-lines <n>", "lines of before/after context (default 0, cap 10)", parseNum).action(
|
|
1402
|
+
runAction(state, (client, opts) => {
|
|
1403
|
+
const filesScope = opts.assetIds || opts.drivePath || opts.mimeTypes ? {
|
|
1404
|
+
assetIds: opts.assetIds,
|
|
1405
|
+
drivePath: opts.drivePath,
|
|
1406
|
+
mimeTypes: opts.mimeTypes
|
|
1407
|
+
} : void 0;
|
|
1408
|
+
const docsScope = opts.nodeIds ? { nodeIds: opts.nodeIds } : void 0;
|
|
1409
|
+
const recordsScope = opts.baseIds || opts.baseSlugs ? {
|
|
1410
|
+
baseIds: opts.baseIds,
|
|
1411
|
+
baseSlugs: opts.baseSlugs
|
|
1412
|
+
} : void 0;
|
|
1413
|
+
return client.grep({
|
|
1414
|
+
pattern: opts.pattern,
|
|
1415
|
+
flags: opts.flags,
|
|
1416
|
+
sources: opts.sources,
|
|
1417
|
+
scope: filesScope || docsScope || recordsScope ? { files: filesScope, docs: docsScope, records: recordsScope } : void 0,
|
|
1418
|
+
maxMatches: opts.maxMatches,
|
|
1419
|
+
contextLines: opts.contextLines
|
|
1420
|
+
});
|
|
1421
|
+
})
|
|
1422
|
+
);
|
|
1274
1423
|
const addUploadCommand = (parent, hidden = false) => addGlobalFlags(parent.command("upload", { noHelp: hidden })).description("Upload a file and print an asset ref for record fields").requiredOption("--file <path>", "local file to upload").option("--file-name <name>", "stored file name (default: basename of --file)").option("--mime-type <mime>", "MIME type (default: inferred from extension)").option("--context <value>", "upload context (default record-field)").addHelpText(
|
|
1275
1424
|
"after",
|
|
1276
1425
|
`
|
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.6",
|
|
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.6",
|
|
35
35
|
"commander": "^14.0.0"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|