busabase-sdk 0.10.2 → 0.11.0
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/README.md +42 -2
- package/dist/chunk-5NYQX65A.js +6 -0
- package/dist/chunk-J2DZKX7A.js +175 -0
- package/dist/index.d.ts +18542 -18143
- package/dist/index.js +326 -151
- package/dist/oauth-node.d.ts +33 -0
- package/dist/oauth-node.js +147 -0
- package/dist/oauth.d.ts +55 -0
- package/dist/oauth.js +2 -0
- package/package.json +12 -4
package/dist/index.js
CHANGED
|
@@ -1,9 +1,34 @@
|
|
|
1
|
+
import { normalizeBaseUrl } from './chunk-5NYQX65A.js';
|
|
2
|
+
export { normalizeBaseUrl } from './chunk-5NYQX65A.js';
|
|
1
3
|
import { createORPCClient, ORPCError } from '@orpc/client';
|
|
2
4
|
import { OpenAPILink } from '@orpc/openapi-client/fetch';
|
|
3
5
|
import { oc, eventIterator } from '@orpc/contract';
|
|
4
6
|
import { z } from 'zod';
|
|
5
7
|
|
|
6
|
-
// src/
|
|
8
|
+
// src/asset-grep.ts
|
|
9
|
+
var toUnifiedFilesGrepInput = (input) => ({
|
|
10
|
+
pattern: input.pattern,
|
|
11
|
+
flags: input.flags,
|
|
12
|
+
sources: ["files"],
|
|
13
|
+
scope: input.scope ? { files: input.scope } : void 0,
|
|
14
|
+
maxMatches: input.maxMatches,
|
|
15
|
+
contextLines: input.contextLines
|
|
16
|
+
});
|
|
17
|
+
var toFilesOnlyGrepResult = (result) => ({
|
|
18
|
+
matches: result.matches.flatMap((match) => {
|
|
19
|
+
if (match.source !== "files") return [];
|
|
20
|
+
const { source: _source, ...fileMatch } = match;
|
|
21
|
+
return [fileMatch];
|
|
22
|
+
}),
|
|
23
|
+
filesScanned: result.coverage.files.scanned,
|
|
24
|
+
missing: result.coverage.files.missing,
|
|
25
|
+
stale: result.coverage.files.stale,
|
|
26
|
+
unsearchable: result.coverage.files.unsearchable,
|
|
27
|
+
errored: result.coverage.files.errored,
|
|
28
|
+
notReached: result.coverage.files.notReached,
|
|
29
|
+
truncated: result.truncated
|
|
30
|
+
});
|
|
31
|
+
var grepAssets = async (client, input) => toFilesOnlyGrepResult(await client.grep(toUnifiedFilesGrepInput(input)));
|
|
7
32
|
var i18n = {
|
|
8
33
|
locales: ["en", "zh-CN", "zh-TW", "ja", "ko", "de", "fr", "es", "pt"]};
|
|
9
34
|
var LocaleSchema = z.enum(i18n.locales);
|
|
@@ -536,7 +561,33 @@ var listNodesInputSchema = z.object({
|
|
|
536
561
|
* soft-archived nodes for the Trash view — no `parentId`/`depth` walk, since
|
|
537
562
|
* archived nodes are shown as a list, not a tree.
|
|
538
563
|
*/
|
|
539
|
-
status: z.enum(["active", "archived"]).optional().default("active")
|
|
564
|
+
status: z.enum(["active", "archived"]).optional().default("active"),
|
|
565
|
+
/**
|
|
566
|
+
* Narrow to specific node types and return a FLAT list of lightweight node
|
|
567
|
+
* summaries (`children: []`) instead of walking the tree. This is what
|
|
568
|
+
* replaced the four retired narrow listings (`GET /docs`, `/files`,
|
|
569
|
+
* `/folders`, `/file-trees`); file-trees are selected with their real
|
|
570
|
+
* discriminators `skill` / `drive` / `airapp`, since there is no synthetic
|
|
571
|
+
* "file-tree" node type.
|
|
572
|
+
*
|
|
573
|
+
* Omitting `types` leaves every existing caller on exactly today's
|
|
574
|
+
* behaviour (full tree, or a `parentId`/`depth`-bounded walk, or the
|
|
575
|
+
* archived flat list) — the two modes never interfere.
|
|
576
|
+
*
|
|
577
|
+
* NOTE — no `projection` parameter, deliberately. The consolidation roadmap
|
|
578
|
+
* sketched `?projection=summary`, but it also rules out adding
|
|
579
|
+
* `projection=detail` in this batch (the retired detail lists were the
|
|
580
|
+
* N+1 payloads this change exists to remove). That would leave a parameter
|
|
581
|
+
* with exactly one legal value, which is noise in OpenAPI/MCP/CLI rather
|
|
582
|
+
* than a decision a caller gets to make. Detail is `GET /nodes/{nodeId}`.
|
|
583
|
+
*
|
|
584
|
+
* A GET query param that occurs exactly once (`?types=doc`) arrives as a
|
|
585
|
+
* bare string, not a 1-element array — only a REPEATED occurrence
|
|
586
|
+
* (`?types=doc&types=file`) becomes an array. Accept both and normalize.
|
|
587
|
+
*/
|
|
588
|
+
types: z.union([z.array(z.enum(NODE_TYPES)), z.enum(NODE_TYPES)]).transform((value) => Array.isArray(value) ? value : [value]).optional().describe(
|
|
589
|
+
"Return a flat list of lightweight summaries for these node types instead of the tree. Read one node's full detail with GET /nodes/{nodeId}."
|
|
590
|
+
)
|
|
540
591
|
}).optional();
|
|
541
592
|
var isDescendantInputSchema = z.object({
|
|
542
593
|
nodeId: z.string(),
|
|
@@ -704,11 +755,19 @@ var liveEventSchema = z.object({
|
|
|
704
755
|
// via the audit funnel, but nothing needs reviewing). Consumed by
|
|
705
756
|
// `use-live-sync.ts` to pop a desktop Notification, and by
|
|
706
757
|
// busabase-cloud's host hook to persist an inbox notification row.
|
|
707
|
-
"change_request.pending_review"
|
|
758
|
+
"change_request.pending_review",
|
|
759
|
+
// A node's metadata was written directly, outside the change-request flow
|
|
760
|
+
// (`PATCH /api/v1/nodes/{nodeId}/metadata` — agents, the SDK, an MCP tool,
|
|
761
|
+
// and every rich-node editor's own Save). Carries the touched node in
|
|
762
|
+
// `nodeIds` so open dashboards refetch the node tree instead of showing a
|
|
763
|
+
// stale whiteboard/workflow/HTML document until the next reload.
|
|
764
|
+
"node.metadata_updated"
|
|
708
765
|
]),
|
|
709
766
|
spaceId: z.string(),
|
|
710
767
|
actorId: z.string(),
|
|
711
|
-
|
|
768
|
+
// Null for events that aren't about a change request at all
|
|
769
|
+
// (`node.metadata_updated`), which is every direct, auto-audited write.
|
|
770
|
+
changeRequestId: z.string().nullable(),
|
|
712
771
|
baseId: z.string().nullable(),
|
|
713
772
|
nodeIds: z.array(z.string()),
|
|
714
773
|
recordIds: z.array(z.string()),
|
|
@@ -1057,13 +1116,6 @@ var fileTreeRefSchema = z.object({
|
|
|
1057
1116
|
type: fileTreeNodeTypeSchema.optional()
|
|
1058
1117
|
});
|
|
1059
1118
|
var fileTreeContract = {
|
|
1060
|
-
list: oc.route({
|
|
1061
|
-
method: "GET",
|
|
1062
|
-
path: "/file-trees",
|
|
1063
|
-
tags: ["File Trees"],
|
|
1064
|
-
summary: "List file-tree nodes",
|
|
1065
|
-
successDescription: "Skill, Drive, and AirApp nodes with their Asset-backed file trees. Pass `type` to narrow to one kind."
|
|
1066
|
-
}).input(z.object({ type: fileTreeNodeTypeSchema.optional() })).output(z.array(fileTreeNodeSchema)),
|
|
1067
1119
|
create: oc.route({
|
|
1068
1120
|
method: "POST",
|
|
1069
1121
|
path: "/file-trees",
|
|
@@ -1076,13 +1128,6 @@ var fileTreeContract = {
|
|
|
1076
1128
|
changeRequestSchema.extend({ materialized: z.literal(false) })
|
|
1077
1129
|
])
|
|
1078
1130
|
),
|
|
1079
|
-
get: oc.route({
|
|
1080
|
-
method: "GET",
|
|
1081
|
-
path: "/file-trees/{nodeId}",
|
|
1082
|
-
tags: ["File Trees"],
|
|
1083
|
-
summary: "Get file-tree node",
|
|
1084
|
-
successDescription: "File-tree node detail and its file list."
|
|
1085
|
-
}).input(fileTreeRefSchema).output(fileTreeNodeSchema),
|
|
1086
1131
|
listFiles: oc.route({
|
|
1087
1132
|
method: "GET",
|
|
1088
1133
|
path: "/file-trees/{nodeId}/files",
|
|
@@ -1277,7 +1322,7 @@ var GREP_DEFAULT_MAX_MATCHES = 100;
|
|
|
1277
1322
|
var GREP_HARD_MAX_MATCHES = 1e3;
|
|
1278
1323
|
var GREP_DEFAULT_CONTEXT_LINES = 0;
|
|
1279
1324
|
var GREP_MAX_CONTEXT_LINES = 10;
|
|
1280
|
-
|
|
1325
|
+
z.object({
|
|
1281
1326
|
pattern: z.string().min(1),
|
|
1282
1327
|
/** JS RegExp flags, e.g. `"i"` for case-insensitive. `g`/`y` are ignored (grep always scans every match per line). */
|
|
1283
1328
|
flags: z.string().optional().default(""),
|
|
@@ -1298,7 +1343,7 @@ var GrepMatchVOSchema = z.object({
|
|
|
1298
1343
|
before: z.array(z.string()),
|
|
1299
1344
|
after: z.array(z.string())
|
|
1300
1345
|
});
|
|
1301
|
-
|
|
1346
|
+
z.object({
|
|
1302
1347
|
matches: z.array(GrepMatchVOSchema),
|
|
1303
1348
|
filesScanned: z.number().int().nonnegative(),
|
|
1304
1349
|
/** Asset ids in scope with no text yet (contentKind text-or-writable-binary, no row). */
|
|
@@ -1432,13 +1477,6 @@ var assetsContract = {
|
|
|
1432
1477
|
summary: "Request a presigned upload URL for large text",
|
|
1433
1478
|
successDescription: "Presigned (or dev) upload URL for a temporary text object; PUT the bytes there, then call putText with the returned storageKey to bind, verify, and content-address it."
|
|
1434
1479
|
}).input(CreateTextUploadUrlInputSchema).output(CreateTextUploadUrlVOSchema),
|
|
1435
|
-
grep: oc.route({
|
|
1436
|
-
method: "POST",
|
|
1437
|
-
path: "/assets/grep",
|
|
1438
|
-
tags: ["Assets"],
|
|
1439
|
-
summary: "Search every text-bearing asset in scope",
|
|
1440
|
-
successDescription: "Streaming regex/literal matches with real file + line + column numbers and context, across every asset with text \u2014 any size, no 256KB cap. Honest coverage: missing/stale/unsearchable/errored name assets that were not (fully or successfully) searched, notReached counts present assets the scan never got to, and truncated flags a capped response."
|
|
1441
|
-
}).input(GrepInputSchema).output(GrepResultVOSchema),
|
|
1442
1480
|
readTextLines: oc.route({
|
|
1443
1481
|
method: "GET",
|
|
1444
1482
|
path: "/assets/{assetId}/text/lines",
|
|
@@ -1525,6 +1563,9 @@ var viewSchema = z.object({
|
|
|
1525
1563
|
createdAt: z.string(),
|
|
1526
1564
|
updatedAt: z.string()
|
|
1527
1565
|
});
|
|
1566
|
+
var autoMergeSchema = z.boolean().optional().describe(
|
|
1567
|
+
"Whether to approve and merge this view change immediately. Omitted defaults to merging immediately if the actor has write access on the Base's node, otherwise falling back to a pending Change Request; pass explicit false to force review even with write access."
|
|
1568
|
+
);
|
|
1528
1569
|
var createViewInputSchema = z.object({
|
|
1529
1570
|
config: viewConfigSchema.optional().default({ filters: [], sorts: [] }),
|
|
1530
1571
|
description: z.string().optional().default(""),
|
|
@@ -1532,7 +1573,8 @@ var createViewInputSchema = z.object({
|
|
|
1532
1573
|
name: z.string().min(1),
|
|
1533
1574
|
type: viewTypeSchema.optional().default("table"),
|
|
1534
1575
|
slug: z.string().min(1).regex(/^[a-z0-9-]+$/).optional(),
|
|
1535
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
1576
|
+
submittedBy: z.string().optional().default("local-producer"),
|
|
1577
|
+
autoMerge: autoMergeSchema
|
|
1536
1578
|
});
|
|
1537
1579
|
var updateViewInputSchema = z.object({
|
|
1538
1580
|
config: viewConfigSchema.optional(),
|
|
@@ -1540,15 +1582,18 @@ var updateViewInputSchema = z.object({
|
|
|
1540
1582
|
message: z.string().optional().default("Update view"),
|
|
1541
1583
|
name: z.string().min(1).optional(),
|
|
1542
1584
|
type: viewTypeSchema.optional(),
|
|
1543
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
1585
|
+
submittedBy: z.string().optional().default("local-producer"),
|
|
1586
|
+
autoMerge: autoMergeSchema
|
|
1544
1587
|
});
|
|
1545
1588
|
var deleteViewInputSchema = z.object({
|
|
1546
1589
|
message: z.string().optional().default("Delete view"),
|
|
1547
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
1590
|
+
submittedBy: z.string().optional().default("local-producer"),
|
|
1591
|
+
autoMerge: autoMergeSchema
|
|
1548
1592
|
});
|
|
1549
1593
|
var restoreViewInputSchema = z.object({
|
|
1550
1594
|
message: z.string().optional().default("Restore view"),
|
|
1551
|
-
submittedBy: z.string().optional().default("local-producer")
|
|
1595
|
+
submittedBy: z.string().optional().default("local-producer"),
|
|
1596
|
+
autoMerge: autoMergeSchema
|
|
1552
1597
|
});
|
|
1553
1598
|
var viewChangeRequestInputSchema = z.discriminatedUnion("operation", [
|
|
1554
1599
|
createViewInputSchema.extend({
|
|
@@ -1616,6 +1661,19 @@ var listRecordsResponseSchema = z.object({
|
|
|
1616
1661
|
records: z.array(recordSchema),
|
|
1617
1662
|
nextCursor: z.string().nullable()
|
|
1618
1663
|
});
|
|
1664
|
+
var listRecordsPageInputSchema = z.object({
|
|
1665
|
+
baseId: z.string().min(1),
|
|
1666
|
+
viewId: z.string().min(1).optional(),
|
|
1667
|
+
page: z.coerce.number().int().min(1).optional().default(1),
|
|
1668
|
+
pageSize: z.coerce.number().int().min(1).max(100).optional().default(50)
|
|
1669
|
+
});
|
|
1670
|
+
var listRecordsPageResponseSchema = z.object({
|
|
1671
|
+
records: z.array(recordSchema),
|
|
1672
|
+
total: z.number().int().nonnegative(),
|
|
1673
|
+
totalPages: z.number().int().nonnegative(),
|
|
1674
|
+
page: z.number().int().min(1),
|
|
1675
|
+
pageSize: z.number().int().min(1).max(100)
|
|
1676
|
+
});
|
|
1619
1677
|
var countRecordsInputSchema = z.object({
|
|
1620
1678
|
baseId: z.string().optional()
|
|
1621
1679
|
}).optional().default({});
|
|
@@ -1662,10 +1720,16 @@ var recordFieldFilterInputSchema = z.object({
|
|
|
1662
1720
|
limit: z.coerce.number().int().min(1).max(100).optional().default(50)
|
|
1663
1721
|
});
|
|
1664
1722
|
var recordFieldGetInputSchema = z.object({
|
|
1665
|
-
baseId: z.string(),
|
|
1666
|
-
fieldSlug: z.string().min(1),
|
|
1667
|
-
valueText: z.string().min(1)
|
|
1723
|
+
baseId: z.string().describe("Field selector: Base id. Requires fieldSlug and valueText."),
|
|
1724
|
+
fieldSlug: z.string().min(1).describe("Field selector: exact field slug. Requires baseId and valueText."),
|
|
1725
|
+
valueText: z.string().min(1).describe("Field selector: exact text value. Requires baseId and fieldSlug.")
|
|
1668
1726
|
});
|
|
1727
|
+
var recordGetInputSchema = z.union([
|
|
1728
|
+
z.object({
|
|
1729
|
+
recordId: z.string().min(1).describe("Record id selector. Use alone; do not combine with field selector fields.")
|
|
1730
|
+
}).strict(),
|
|
1731
|
+
recordFieldGetInputSchema.strict()
|
|
1732
|
+
]);
|
|
1669
1733
|
var restoreRecordInputSchema = z.object({
|
|
1670
1734
|
message: z.string().optional(),
|
|
1671
1735
|
submittedBy: z.string().optional().default("local-editor")
|
|
@@ -1801,6 +1865,13 @@ var recordContract = {
|
|
|
1801
1865
|
summary: "List records",
|
|
1802
1866
|
successDescription: "A page of canonical records plus an opaque nextCursor (null at the end). `status=archived` lists the Base's trash instead of its live rows."
|
|
1803
1867
|
}).input(listRecordsInputSchema).output(listRecordsResponseSchema),
|
|
1868
|
+
listPage: oc.route({
|
|
1869
|
+
method: "GET",
|
|
1870
|
+
path: "/records/page",
|
|
1871
|
+
tags: ["Records"],
|
|
1872
|
+
summary: "List a numbered record page",
|
|
1873
|
+
successDescription: "A random-access page of active records. When viewId is supplied, the saved view is authoritatively filtered and sorted before total and page slicing are calculated."
|
|
1874
|
+
}).input(listRecordsPageInputSchema).output(listRecordsPageResponseSchema),
|
|
1804
1875
|
count: oc.route({
|
|
1805
1876
|
method: "GET",
|
|
1806
1877
|
path: "/records/count",
|
|
@@ -1810,11 +1881,15 @@ var recordContract = {
|
|
|
1810
1881
|
}).input(countRecordsInputSchema).output(countRecordsResponseSchema),
|
|
1811
1882
|
get: oc.route({
|
|
1812
1883
|
method: "GET",
|
|
1813
|
-
path: "/records/
|
|
1884
|
+
path: "/records/get",
|
|
1814
1885
|
tags: ["Records"],
|
|
1815
1886
|
summary: "Get record",
|
|
1816
|
-
|
|
1817
|
-
|
|
1887
|
+
description: "Provide exactly one selector: recordId alone, or the complete baseId + fieldSlug + valueText tuple. Other combinations return 400.",
|
|
1888
|
+
successDescription: "One canonical record selected by id or exact field value."
|
|
1889
|
+
}).errors({
|
|
1890
|
+
BAD_REQUEST: { status: 400, message: "Exactly one record selector is required" },
|
|
1891
|
+
NOT_FOUND: { status: 404, message: "Record not found" }
|
|
1892
|
+
}).input(recordGetInputSchema).output(recordSchema),
|
|
1818
1893
|
search: oc.route({
|
|
1819
1894
|
method: "GET",
|
|
1820
1895
|
path: "/records/search",
|
|
@@ -1822,13 +1897,6 @@ var recordContract = {
|
|
|
1822
1897
|
summary: "Filter records by field text",
|
|
1823
1898
|
successDescription: "Canonical records matching a field text filter."
|
|
1824
1899
|
}).input(recordFieldFilterInputSchema).output(z.array(recordSchema)),
|
|
1825
|
-
getByField: oc.route({
|
|
1826
|
-
method: "GET",
|
|
1827
|
-
path: "/records/by-field",
|
|
1828
|
-
tags: ["Records"],
|
|
1829
|
-
summary: "Get record by field value",
|
|
1830
|
-
successDescription: "Single canonical record whose field value exactly matches, or null when none does \u2014 a scoped point lookup (e.g. by a unique slug or path field), not a list."
|
|
1831
|
-
}).input(recordFieldGetInputSchema).output(recordSchema.nullable()),
|
|
1832
1900
|
changeRequest: oc.route({
|
|
1833
1901
|
method: "POST",
|
|
1834
1902
|
path: "/records/{recordId}/change-requests",
|
|
@@ -1862,8 +1930,13 @@ var viewContract = {
|
|
|
1862
1930
|
path: "/views/change-requests",
|
|
1863
1931
|
tags: ["Views", "Change Requests"],
|
|
1864
1932
|
summary: "Create view change request",
|
|
1865
|
-
successDescription: "
|
|
1866
|
-
}).input(viewChangeRequestInputSchema).output(
|
|
1933
|
+
successDescription: "Proposes a view change. `operation` selects what to propose: `create` (addressed by `baseId`), or `update` / `delete` / `restore` (addressed by `viewId`). Review-first when the actor lacks write access or passes `autoMerge: false` \u2014 a pending ChangeRequest (`materialized: false`). Otherwise the change is approved and merged in the same call and the materialized View comes back instead (`materialized: true`)."
|
|
1934
|
+
}).input(viewChangeRequestInputSchema).output(
|
|
1935
|
+
z.union([
|
|
1936
|
+
viewSchema.extend({ materialized: z.literal(true) }),
|
|
1937
|
+
changeRequestSchema.extend({ materialized: z.literal(false) })
|
|
1938
|
+
])
|
|
1939
|
+
)
|
|
1867
1940
|
};
|
|
1868
1941
|
var ReadDocLinesInputSchema = z.object({
|
|
1869
1942
|
nodeId: z.string(),
|
|
@@ -1902,13 +1975,6 @@ var createDocChangeRequestInputSchema = z.object({
|
|
|
1902
1975
|
submittedBy: z.string().optional().default("local-producer")
|
|
1903
1976
|
});
|
|
1904
1977
|
var docContract = {
|
|
1905
|
-
list: oc.route({
|
|
1906
|
-
method: "GET",
|
|
1907
|
-
path: "/docs",
|
|
1908
|
-
tags: ["Docs"],
|
|
1909
|
-
summary: "List Doc nodes",
|
|
1910
|
-
successDescription: "Doc nodes with their storage-backed bodies."
|
|
1911
|
-
}).output(z.array(docSchema)),
|
|
1912
1978
|
create: oc.route({
|
|
1913
1979
|
method: "POST",
|
|
1914
1980
|
path: "/docs",
|
|
@@ -1921,19 +1987,12 @@ var docContract = {
|
|
|
1921
1987
|
changeRequestSchema.extend({ materialized: z.literal(false) })
|
|
1922
1988
|
])
|
|
1923
1989
|
),
|
|
1924
|
-
get: oc.route({
|
|
1925
|
-
method: "GET",
|
|
1926
|
-
path: "/docs/{nodeId}",
|
|
1927
|
-
tags: ["Docs"],
|
|
1928
|
-
summary: "Get Doc node",
|
|
1929
|
-
successDescription: "Doc node detail and body."
|
|
1930
|
-
}).input(z.object({ nodeId: z.string() })).output(docSchema),
|
|
1931
1990
|
readLines: oc.route({
|
|
1932
1991
|
method: "GET",
|
|
1933
1992
|
path: "/docs/{nodeId}/lines",
|
|
1934
1993
|
tags: ["Docs"],
|
|
1935
1994
|
summary: "Read an exact line range from a Doc body",
|
|
1936
|
-
successDescription: "Lines [startLine, endLine] (range capped at 2000 lines / ~2MB response) sliced from the Doc's full body \u2014 Docs are KB-scale, so the whole body is read in memory; no byte-range/checkpoint machinery like assets.readTextLines uses for potentially multi-GB files. The Doc-domain follow-up to a Unified Grep match with `source: \"docs\"`, so an agent can read just the lines around a match instead of `get`'s entire body."
|
|
1995
|
+
successDescription: "Lines [startLine, endLine] (range capped at 2000 lines / ~2MB response) sliced from the Doc's full body \u2014 Docs are KB-scale, so the whole body is read in memory; no byte-range/checkpoint machinery like assets.readTextLines uses for potentially multi-GB files. The Doc-domain follow-up to a Unified Grep match with `source: \"docs\"`, so an agent can read just the lines around a match instead of `nodes.get`'s entire body."
|
|
1937
1996
|
}).input(ReadDocLinesInputSchema).output(ReadLinesVOSchema),
|
|
1938
1997
|
updateBody: oc.route({
|
|
1939
1998
|
method: "PUT",
|
|
@@ -2099,13 +2158,6 @@ var createFileNodeInputSchema = z.object({
|
|
|
2099
2158
|
autoMerge: z.boolean().optional()
|
|
2100
2159
|
});
|
|
2101
2160
|
var fileContract = {
|
|
2102
|
-
list: oc.route({
|
|
2103
|
-
method: "GET",
|
|
2104
|
-
path: "/files",
|
|
2105
|
-
tags: ["Files"],
|
|
2106
|
-
summary: "List File nodes",
|
|
2107
|
-
successDescription: "Workspace File nodes with their backing Asset metadata."
|
|
2108
|
-
}).output(z.array(FileNodeVOSchema)),
|
|
2109
2161
|
create: oc.route({
|
|
2110
2162
|
method: "POST",
|
|
2111
2163
|
path: "/files",
|
|
@@ -2117,34 +2169,7 @@ var fileContract = {
|
|
|
2117
2169
|
FileNodeVOSchema.extend({ materialized: z.literal(true) }),
|
|
2118
2170
|
changeRequestSchema.extend({ materialized: z.literal(false) })
|
|
2119
2171
|
])
|
|
2120
|
-
)
|
|
2121
|
-
get: oc.route({
|
|
2122
|
-
method: "GET",
|
|
2123
|
-
path: "/files/{nodeId}",
|
|
2124
|
-
tags: ["Files"],
|
|
2125
|
-
summary: "Get File node",
|
|
2126
|
-
successDescription: "File node detail and backing Asset metadata."
|
|
2127
|
-
}).input(z.object({ nodeId: z.string() })).output(FileNodeVOSchema)
|
|
2128
|
-
};
|
|
2129
|
-
var folderSchema = z.object({
|
|
2130
|
-
node: nodeSchema,
|
|
2131
|
-
children: z.array(nodeSchema)
|
|
2132
|
-
});
|
|
2133
|
-
var folderContract = {
|
|
2134
|
-
list: oc.route({
|
|
2135
|
-
method: "GET",
|
|
2136
|
-
path: "/folders",
|
|
2137
|
-
tags: ["Folders"],
|
|
2138
|
-
summary: "List Folder nodes",
|
|
2139
|
-
successDescription: "Folder nodes with their direct children."
|
|
2140
|
-
}).output(z.array(folderSchema)),
|
|
2141
|
-
get: oc.route({
|
|
2142
|
-
method: "GET",
|
|
2143
|
-
path: "/folders/{nodeId}",
|
|
2144
|
-
tags: ["Folders"],
|
|
2145
|
-
summary: "Get Folder node",
|
|
2146
|
-
successDescription: "Folder node and its direct children."
|
|
2147
|
-
}).input(z.object({ nodeId: z.string() })).output(folderSchema)
|
|
2172
|
+
)
|
|
2148
2173
|
};
|
|
2149
2174
|
var FormFieldBindingSchema = z.object({
|
|
2150
2175
|
inputName: z.string().min(1),
|
|
@@ -2697,7 +2722,7 @@ var UnifiedGrepScopeSchema = z.object({
|
|
|
2697
2722
|
});
|
|
2698
2723
|
var UnifiedGrepInputSchema = z.object({
|
|
2699
2724
|
pattern: z.string().min(1),
|
|
2700
|
-
/** JS RegExp flags, e.g. `"i"` for case-insensitive
|
|
2725
|
+
/** JS RegExp flags, e.g. `"i"` for case-insensitive. */
|
|
2701
2726
|
flags: z.string().optional().default(""),
|
|
2702
2727
|
/** Which sources to scan. Omitted = all three (`files`, `docs`, `records`). */
|
|
2703
2728
|
sources: z.array(GrepSourceSchema).optional(),
|
|
@@ -2777,16 +2802,86 @@ var UnifiedGrepResultVOSchema = z.object({
|
|
|
2777
2802
|
/** True when any source truncated, or any source has `notReached > 0`. */
|
|
2778
2803
|
truncated: z.boolean()
|
|
2779
2804
|
});
|
|
2805
|
+
var folderSchema = z.object({
|
|
2806
|
+
node: nodeSchema,
|
|
2807
|
+
children: z.array(nodeSchema)
|
|
2808
|
+
});
|
|
2809
|
+
|
|
2810
|
+
// ../../packages/busabase-contract/src/contract/node-detail-schemas.ts
|
|
2811
|
+
var genericNodeDetailSchema = (type) => z.object({
|
|
2812
|
+
type: z.literal(type),
|
|
2813
|
+
node: nodeSchema
|
|
2814
|
+
});
|
|
2815
|
+
var NODE_DETAIL_VARIANTS = {
|
|
2816
|
+
folder: folderSchema.extend({ type: z.literal("folder") }),
|
|
2817
|
+
doc: docSchema.extend({ type: z.literal("doc") }),
|
|
2818
|
+
file: FileNodeVOSchema.extend({ type: z.literal("file") }),
|
|
2819
|
+
// Skills, Drives, and AirApps are one server-side shape (`fileTreeNodeSchema`)
|
|
2820
|
+
// but three real node types — there is no synthetic "file-tree" node type, so
|
|
2821
|
+
// each gets its own discriminated variant rather than a shared alias.
|
|
2822
|
+
skill: fileTreeNodeSchema.extend({ type: z.literal("skill") }),
|
|
2823
|
+
drive: fileTreeNodeSchema.extend({ type: z.literal("drive") }),
|
|
2824
|
+
airapp: fileTreeNodeSchema.extend({ type: z.literal("airapp") }),
|
|
2825
|
+
base: genericNodeDetailSchema("base"),
|
|
2826
|
+
form: genericNodeDetailSchema("form"),
|
|
2827
|
+
whiteboard: genericNodeDetailSchema("whiteboard"),
|
|
2828
|
+
workflow: genericNodeDetailSchema("workflow"),
|
|
2829
|
+
html: genericNodeDetailSchema("html")
|
|
2830
|
+
};
|
|
2831
|
+
var NodeDetailVOSchema = z.discriminatedUnion("type", [
|
|
2832
|
+
NODE_DETAIL_VARIANTS.folder,
|
|
2833
|
+
NODE_DETAIL_VARIANTS.doc,
|
|
2834
|
+
NODE_DETAIL_VARIANTS.file,
|
|
2835
|
+
NODE_DETAIL_VARIANTS.skill,
|
|
2836
|
+
NODE_DETAIL_VARIANTS.drive,
|
|
2837
|
+
NODE_DETAIL_VARIANTS.airapp,
|
|
2838
|
+
NODE_DETAIL_VARIANTS.base,
|
|
2839
|
+
NODE_DETAIL_VARIANTS.form,
|
|
2840
|
+
NODE_DETAIL_VARIANTS.whiteboard,
|
|
2841
|
+
NODE_DETAIL_VARIANTS.workflow,
|
|
2842
|
+
NODE_DETAIL_VARIANTS.html
|
|
2843
|
+
]);
|
|
2844
|
+
var getNodeInputSchema = z.object({
|
|
2845
|
+
nodeId: z.string().describe("Node id, or a slug that is unique within its type."),
|
|
2846
|
+
type: z.enum(NODE_TYPES).optional().describe(
|
|
2847
|
+
"Optional disambiguation hint, only needed when `nodeId` is a slug that exists under more than one node type."
|
|
2848
|
+
)
|
|
2849
|
+
});
|
|
2780
2850
|
|
|
2781
2851
|
// ../../packages/busabase-contract/src/contract/busabase.ts
|
|
2782
|
-
var
|
|
2852
|
+
var changeRequestBatchFailureSchema = z.object({
|
|
2853
|
+
changeRequestId: z.string(),
|
|
2854
|
+
ok: z.literal(false),
|
|
2855
|
+
error: z.string(),
|
|
2856
|
+
code: z.string().optional(),
|
|
2857
|
+
data: z.unknown().optional()
|
|
2858
|
+
});
|
|
2859
|
+
var changeRequestReviewBatchResultSchema = z.object({
|
|
2783
2860
|
results: z.array(
|
|
2784
|
-
z.
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2861
|
+
z.discriminatedUnion("ok", [
|
|
2862
|
+
z.object({
|
|
2863
|
+
changeRequestId: z.string(),
|
|
2864
|
+
ok: z.literal(true),
|
|
2865
|
+
status: z.string(),
|
|
2866
|
+
changeRequest: changeRequestSchema
|
|
2867
|
+
}),
|
|
2868
|
+
changeRequestBatchFailureSchema
|
|
2869
|
+
])
|
|
2870
|
+
)
|
|
2871
|
+
});
|
|
2872
|
+
var changeRequestMergeBatchResultSchema = z.object({
|
|
2873
|
+
results: z.array(
|
|
2874
|
+
z.discriminatedUnion("ok", [
|
|
2875
|
+
z.object({
|
|
2876
|
+
changeRequestId: z.string(),
|
|
2877
|
+
ok: z.literal(true),
|
|
2878
|
+
status: z.string(),
|
|
2879
|
+
changeRequest: changeRequestSchema,
|
|
2880
|
+
record: recordSchema.nullable(),
|
|
2881
|
+
view: viewSchema.nullable()
|
|
2882
|
+
}),
|
|
2883
|
+
changeRequestBatchFailureSchema
|
|
2884
|
+
])
|
|
2790
2885
|
)
|
|
2791
2886
|
});
|
|
2792
2887
|
var busabaseContractRoutes = {
|
|
@@ -2806,11 +2901,9 @@ var busabaseContractRoutes = {
|
|
|
2806
2901
|
summary: "Search Busabase",
|
|
2807
2902
|
successDescription: "Paginated search results across records, change requests, Bases, File nodes, and Assets."
|
|
2808
2903
|
}).input(searchInputSchema).output(searchResponseSchema),
|
|
2809
|
-
// Unified Grep (P2a files+docs, P2b records) —
|
|
2810
|
-
//
|
|
2811
|
-
//
|
|
2812
|
-
// unchanged and stays the dedicated endpoint for its fuller
|
|
2813
|
-
// missing/stale/unsearchable reporting.
|
|
2904
|
+
// Unified Grep (P2a files+docs, P2b records) — the single public pattern
|
|
2905
|
+
// search endpoint. Files-only callers use `sources: ["files"]` and retain
|
|
2906
|
+
// the full missing/stale/unsearchable coverage block.
|
|
2814
2907
|
grep: oc.route({
|
|
2815
2908
|
method: "POST",
|
|
2816
2909
|
path: "/grep",
|
|
@@ -2823,8 +2916,8 @@ var busabaseContractRoutes = {
|
|
|
2823
2916
|
method: "GET",
|
|
2824
2917
|
path: "/nodes",
|
|
2825
2918
|
tags: ["Nodes"],
|
|
2826
|
-
summary: "List
|
|
2827
|
-
successDescription: "Workspace node tree including folders, Bases, files, and agents. With no `parentId`/`depth`, returns the FULL tree (legacy behavior, still what every non-sidebar caller gets). Passing `parentId` and/or `depth` switches to a depth-bounded fetch: `parentId` omitted/null starts from the space root and returns it wrapped exactly like the legacy call (just depth-limited); an explicit `parentId` returns that node's children directly, ready to merge into its `NodeVO.children` for a sidebar's lazy per-folder expand. See `NodeVO.hasChildren` for how a depth boundary is surfaced."
|
|
2919
|
+
summary: "List nodes (workspace tree, or a flat summary list by type)",
|
|
2920
|
+
successDescription: "Workspace node tree including folders, Bases, files, and agents. With no `parentId`/`depth`, returns the FULL tree (legacy behavior, still what every non-sidebar caller gets). Passing `parentId` and/or `depth` switches to a depth-bounded fetch: `parentId` omitted/null starts from the space root and returns it wrapped exactly like the legacy call (just depth-limited); an explicit `parentId` returns that node's children directly, ready to merge into its `NodeVO.children` for a sidebar's lazy per-folder expand. See `NodeVO.hasChildren` for how a depth boundary is surfaced. Passing `types` instead returns a FLAT, ACL-filtered list of lightweight summaries (`children: []`) for just those node types \u2014 this is what replaced `GET /docs`, `/files`, `/folders`, and `/file-trees`, and it deliberately hydrates nothing heavy (no Doc bodies, backing Assets, folder children, or file inventories). Open one item with `GET /nodes/{nodeId}`."
|
|
2828
2921
|
}).input(listNodesInputSchema).output(z.array(nodeSchema)),
|
|
2829
2922
|
searchByName: oc.route({
|
|
2830
2923
|
method: "GET",
|
|
@@ -2894,6 +2987,21 @@ var busabaseContractRoutes = {
|
|
|
2894
2987
|
summary: "List the current actor's favorited nodes",
|
|
2895
2988
|
successDescription: "The acting user's favorited nodes, newest-favorited first, filtered through the same archived/deleted/visibility rules as the main tree \u2014 a favorited node that's later archived, purged, or (cloud) hidden from this actor silently drops out rather than erroring."
|
|
2896
2989
|
}).output(z.array(nodeSchema)),
|
|
2990
|
+
// Registered LAST among the `/nodes/...` GETs on purpose. `GET /nodes/search`
|
|
2991
|
+
// and `GET /nodes/favorites` are literal paths that now share a prefix with
|
|
2992
|
+
// this template. The oRPC OpenAPI matcher is a rou3 radix trie, which
|
|
2993
|
+
// prefers a static segment over a param segment independently of insertion
|
|
2994
|
+
// order — but keeping the literals declared first means the source order
|
|
2995
|
+
// matches the resolution order, so nobody has to know that to read this
|
|
2996
|
+
// file. `tests/openapi-node-routes.test.ts` proves the literals still win
|
|
2997
|
+
// against a real handler rather than resolving as `nodeId: "search"`.
|
|
2998
|
+
get: oc.route({
|
|
2999
|
+
method: "GET",
|
|
3000
|
+
path: "/nodes/{nodeId}",
|
|
3001
|
+
tags: ["Nodes"],
|
|
3002
|
+
summary: "Get one node's typed detail",
|
|
3003
|
+
successDescription: "The node's full detail, discriminated by its `type`. One entry point for every node type, so a caller holding an id never has to discover the type first: `folder` carries its direct `children`, `doc` its storage-backed `body`, `file` its backing `asset`, and `skill`/`drive`/`airapp` their Asset-backed `files`. Types with no richer detail yet (`base`, `form`, `whiteboard`, `workflow`, `html`) return just `node`. `nodeId` accepts an id or a slug; pass `type` when a slug exists under more than one type. Archived nodes are not returned (404), matching the typed gets this replaced."
|
|
3004
|
+
}).input(getNodeInputSchema).output(NodeDetailVOSchema),
|
|
2897
3005
|
principals: {
|
|
2898
3006
|
list: oc.route({
|
|
2899
3007
|
method: "GET",
|
|
@@ -3027,7 +3135,9 @@ var busabaseContractRoutes = {
|
|
|
3027
3135
|
airapps: airappRuntimeContract,
|
|
3028
3136
|
files: fileContract,
|
|
3029
3137
|
docs: docContract,
|
|
3030
|
-
folders:
|
|
3138
|
+
// No `folders` key: the Folder domain's only two operations were `GET /folders`
|
|
3139
|
+
// and `GET /folders/{nodeId}`, both now served by the unified Node surface
|
|
3140
|
+
// (`nodes.list({ types: ["folder"] })` / `nodes.get`).
|
|
3031
3141
|
forms: formContract,
|
|
3032
3142
|
assets: assetsContract,
|
|
3033
3143
|
vault: vaultContract,
|
|
@@ -3059,23 +3169,16 @@ var busabaseContractRoutes = {
|
|
|
3059
3169
|
successDescription: "Change Request detail."
|
|
3060
3170
|
}).input(z.object({ changeRequestId: z.string() })).output(changeRequestSchema),
|
|
3061
3171
|
review: oc.route({
|
|
3062
|
-
method: "POST",
|
|
3063
|
-
path: "/change-requests/{changeRequestId}/reviews",
|
|
3064
|
-
tags: ["Change Requests"],
|
|
3065
|
-
summary: "Review change request",
|
|
3066
|
-
successDescription: "Reviewed change request."
|
|
3067
|
-
}).input(reviewChangeRequestInputSchema.extend({ changeRequestId: z.string() })).output(changeRequestSchema),
|
|
3068
|
-
reviewMany: oc.route({
|
|
3069
3172
|
method: "POST",
|
|
3070
3173
|
path: "/change-requests/reviews",
|
|
3071
3174
|
tags: ["Change Requests"],
|
|
3072
|
-
summary: "Review
|
|
3175
|
+
summary: "Review change requests",
|
|
3073
3176
|
successDescription: "Per-change-request review results (failures isolated \u2014 one bad id does not abort the rest)."
|
|
3074
3177
|
}).input(
|
|
3075
3178
|
reviewChangeRequestInputSchema.extend({
|
|
3076
3179
|
changeRequestIds: z.array(z.string()).min(1).max(100)
|
|
3077
3180
|
})
|
|
3078
|
-
).output(
|
|
3181
|
+
).output(changeRequestReviewBatchResultSchema),
|
|
3079
3182
|
close: oc.route({
|
|
3080
3183
|
method: "POST",
|
|
3081
3184
|
path: "/change-requests/{changeRequestId}/close",
|
|
@@ -3084,25 +3187,12 @@ var busabaseContractRoutes = {
|
|
|
3084
3187
|
successDescription: "Closed change request (terminal \u2014 distinct from request changes)."
|
|
3085
3188
|
}).input(z.object({ changeRequestId: z.string(), reason: z.string().optional() })).output(changeRequestSchema),
|
|
3086
3189
|
merge: oc.route({
|
|
3087
|
-
method: "POST",
|
|
3088
|
-
path: "/change-requests/{changeRequestId}/merge",
|
|
3089
|
-
tags: ["Change Requests"],
|
|
3090
|
-
summary: "Merge change request into Base",
|
|
3091
|
-
successDescription: "Merged change request and canonical record."
|
|
3092
|
-
}).input(z.object({ changeRequestId: z.string() })).output(
|
|
3093
|
-
z.object({
|
|
3094
|
-
changeRequest: changeRequestSchema,
|
|
3095
|
-
record: recordSchema.nullable(),
|
|
3096
|
-
view: viewSchema.nullable()
|
|
3097
|
-
})
|
|
3098
|
-
),
|
|
3099
|
-
mergeMany: oc.route({
|
|
3100
3190
|
method: "POST",
|
|
3101
3191
|
path: "/change-requests/merge",
|
|
3102
3192
|
tags: ["Change Requests"],
|
|
3103
|
-
summary: "Merge
|
|
3193
|
+
summary: "Merge change requests",
|
|
3104
3194
|
successDescription: "Per-change-request merge results (each merged in its own transaction; failures isolated)."
|
|
3105
|
-
}).input(z.object({ changeRequestIds: z.array(z.string()).min(1).max(100) })).output(
|
|
3195
|
+
}).input(z.object({ changeRequestIds: z.array(z.string()).min(1).max(100) })).output(changeRequestMergeBatchResultSchema)
|
|
3106
3196
|
},
|
|
3107
3197
|
operations: {
|
|
3108
3198
|
revise: oc.route({
|
|
@@ -3384,9 +3474,6 @@ var env = (key) => {
|
|
|
3384
3474
|
const value = process.env[key];
|
|
3385
3475
|
return value && value.length > 0 ? value : void 0;
|
|
3386
3476
|
};
|
|
3387
|
-
function normalizeBaseUrl(raw) {
|
|
3388
|
-
return raw.replace(/\/+$/, "").replace(/\/api\/v1$/, "");
|
|
3389
|
-
}
|
|
3390
3477
|
function resolveConfig(config = {}) {
|
|
3391
3478
|
return {
|
|
3392
3479
|
baseUrl: normalizeBaseUrl(config.baseUrl ?? env("BUSABASE_BASE_URL") ?? DEFAULT_BASE_URL),
|
|
@@ -3434,7 +3521,22 @@ function createBusabaseClient(config = {}) {
|
|
|
3434
3521
|
return createORPCClient(link);
|
|
3435
3522
|
}
|
|
3436
3523
|
|
|
3524
|
+
// src/record-get.ts
|
|
3525
|
+
var isNotFound = (error) => typeof error === "object" && error !== null && ("status" in error && error.status === 404 || "code" in error && error.code === "NOT_FOUND");
|
|
3526
|
+
var getRecordByField = async (client, input) => {
|
|
3527
|
+
try {
|
|
3528
|
+
return await client.records.get(input);
|
|
3529
|
+
} catch (error) {
|
|
3530
|
+
if (isNotFound(error)) return null;
|
|
3531
|
+
throw error;
|
|
3532
|
+
}
|
|
3533
|
+
};
|
|
3534
|
+
|
|
3437
3535
|
// src/index.ts
|
|
3536
|
+
var batchItemError = (result) => Object.assign(new Error(result?.error ?? "Change request action returned no result"), {
|
|
3537
|
+
...result?.code ? { code: result.code } : {},
|
|
3538
|
+
...result?.data === void 0 ? {} : { data: result.data }
|
|
3539
|
+
});
|
|
3438
3540
|
var Busabase = class {
|
|
3439
3541
|
/** The underlying fully-typed oRPC client. Use it for anything not surfaced here. */
|
|
3440
3542
|
client;
|
|
@@ -3450,17 +3552,67 @@ var Busabase = class {
|
|
|
3450
3552
|
return this.client.bases;
|
|
3451
3553
|
}
|
|
3452
3554
|
get records() {
|
|
3453
|
-
|
|
3555
|
+
const getByField = (input) => getRecordByField(this.client, input);
|
|
3556
|
+
return new Proxy(this.client.records, {
|
|
3557
|
+
get(target, property, receiver) {
|
|
3558
|
+
if (property === "getByField") return getByField;
|
|
3559
|
+
return Reflect.get(target, property, receiver);
|
|
3560
|
+
}
|
|
3561
|
+
});
|
|
3454
3562
|
}
|
|
3455
3563
|
get views() {
|
|
3456
3564
|
return this.client.views;
|
|
3457
3565
|
}
|
|
3458
3566
|
get changeRequests() {
|
|
3459
|
-
|
|
3567
|
+
const review = async (input) => {
|
|
3568
|
+
if ("changeRequestIds" in input) return this.client.changeRequests.review(input);
|
|
3569
|
+
const { changeRequestId, ...reviewInput } = input;
|
|
3570
|
+
const { results } = await this.client.changeRequests.review({
|
|
3571
|
+
...reviewInput,
|
|
3572
|
+
changeRequestIds: [changeRequestId]
|
|
3573
|
+
});
|
|
3574
|
+
const result = results[0];
|
|
3575
|
+
if (!result?.ok) throw batchItemError(result);
|
|
3576
|
+
return result.changeRequest;
|
|
3577
|
+
};
|
|
3578
|
+
const merge = async (input) => {
|
|
3579
|
+
if ("changeRequestIds" in input) return this.client.changeRequests.merge(input);
|
|
3580
|
+
const { results } = await this.client.changeRequests.merge({
|
|
3581
|
+
changeRequestIds: [input.changeRequestId]
|
|
3582
|
+
});
|
|
3583
|
+
const result = results[0];
|
|
3584
|
+
if (!result?.ok) throw batchItemError(result);
|
|
3585
|
+
return {
|
|
3586
|
+
changeRequest: result.changeRequest,
|
|
3587
|
+
record: result.record,
|
|
3588
|
+
view: result.view
|
|
3589
|
+
};
|
|
3590
|
+
};
|
|
3591
|
+
return new Proxy(this.client.changeRequests, {
|
|
3592
|
+
get(target, property, receiver) {
|
|
3593
|
+
if (property === "review") return review;
|
|
3594
|
+
if (property === "merge") return merge;
|
|
3595
|
+
return Reflect.get(target, property, receiver);
|
|
3596
|
+
}
|
|
3597
|
+
});
|
|
3460
3598
|
}
|
|
3461
3599
|
get operations() {
|
|
3462
3600
|
return this.client.operations;
|
|
3463
3601
|
}
|
|
3602
|
+
/**
|
|
3603
|
+
* The workspace node surface, and the single entry point for reading ONE node
|
|
3604
|
+
* of any type: `bb.nodes.get({ nodeId })` returns a `NodeDetailVO`
|
|
3605
|
+
* discriminated by `type` (`folder` carries `children`, `doc` a `body`, `file`
|
|
3606
|
+
* its `asset`, `skill`/`drive`/`airapp` their `files`). It replaced the four
|
|
3607
|
+
* typed gets (`docs`/`files`/`folders`/`fileTrees`), so a caller holding an id
|
|
3608
|
+
* no longer has to know the node's type before it can read it.
|
|
3609
|
+
*
|
|
3610
|
+
* `bb.nodes.list({ types })` is the matching list: a flat array of lightweight
|
|
3611
|
+
* summaries for just those types. Without `types` it still returns the full
|
|
3612
|
+
* workspace tree.
|
|
3613
|
+
*
|
|
3614
|
+
* There is no `bb.folders` any more — folders are `type: "folder"` here.
|
|
3615
|
+
*/
|
|
3464
3616
|
get nodes() {
|
|
3465
3617
|
return this.client.nodes;
|
|
3466
3618
|
}
|
|
@@ -3474,21 +3626,46 @@ var Busabase = class {
|
|
|
3474
3626
|
return this.client.agent;
|
|
3475
3627
|
}
|
|
3476
3628
|
get assets() {
|
|
3477
|
-
|
|
3629
|
+
const filesOnlyGrep = (input) => grepAssets(this.client, input);
|
|
3630
|
+
return new Proxy(this.client.assets, {
|
|
3631
|
+
get(target, property, receiver) {
|
|
3632
|
+
if (property === "grep") return filesOnlyGrep;
|
|
3633
|
+
return Reflect.get(target, property, receiver);
|
|
3634
|
+
}
|
|
3635
|
+
});
|
|
3478
3636
|
}
|
|
3479
|
-
/**
|
|
3637
|
+
/**
|
|
3638
|
+
* Skills, Drives, and AirApps — one surface, discriminated by `type`.
|
|
3639
|
+
*
|
|
3640
|
+
* Creation and per-file reads/writes live here. Listing them and reading one
|
|
3641
|
+
* node's detail moved to the unified Node surface:
|
|
3642
|
+
* `bb.nodes.list({ types: ["skill", "drive", "airapp"] })` and
|
|
3643
|
+
* `bb.nodes.get({ nodeId, type })`.
|
|
3644
|
+
*/
|
|
3480
3645
|
get fileTrees() {
|
|
3481
3646
|
return this.client.fileTrees;
|
|
3482
3647
|
}
|
|
3648
|
+
/**
|
|
3649
|
+
* File nodes. `create` only — list with `bb.nodes.list({ types: ["file"] })`
|
|
3650
|
+
* and read one (backing Asset included) with `bb.nodes.get({ nodeId })`.
|
|
3651
|
+
*/
|
|
3483
3652
|
get files() {
|
|
3484
3653
|
return this.client.files;
|
|
3485
3654
|
}
|
|
3655
|
+
/**
|
|
3656
|
+
* Docs. Create / read a line range / update the body / open a Change Request.
|
|
3657
|
+
* List with `bb.nodes.list({ types: ["doc"] })` and read one (body included)
|
|
3658
|
+
* with `bb.nodes.get({ nodeId })`.
|
|
3659
|
+
*
|
|
3660
|
+
* There is deliberately no `bb.docs.list()` shim. The retired `GET /docs`
|
|
3661
|
+
* returned every Doc *with its body*; the one-call replacement returns
|
|
3662
|
+
* lightweight summaries, and the only way to keep the old shape would be a
|
|
3663
|
+
* detail request per Doc. An SDK convenience that quietly turns one call into
|
|
3664
|
+
* N is worse than a compile error that points at `bb.nodes`.
|
|
3665
|
+
*/
|
|
3486
3666
|
get docs() {
|
|
3487
3667
|
return this.client.docs;
|
|
3488
3668
|
}
|
|
3489
|
-
get folders() {
|
|
3490
|
-
return this.client.folders;
|
|
3491
|
-
}
|
|
3492
3669
|
get agentTasks() {
|
|
3493
3670
|
return this.client.agentTasks;
|
|
3494
3671
|
}
|
|
@@ -3507,10 +3684,8 @@ var Busabase = class {
|
|
|
3507
3684
|
* source (Drive/Skill files, Doc bodies, and Base records — records read
|
|
3508
3685
|
* the canonical `headCommit.fields`, never the truncated search
|
|
3509
3686
|
* projection), with a shared `maxMatches`/deadline budget and per-source
|
|
3510
|
-
* honest coverage.
|
|
3511
|
-
*
|
|
3512
|
-
* about files and want its fuller `missing`/`stale`/`unsearchable`
|
|
3513
|
-
* file-only reporting.
|
|
3687
|
+
* honest coverage. `bb.assets.grep` remains available as a files-only SDK
|
|
3688
|
+
* convenience and delegates here with `sources: ["files"]`.
|
|
3514
3689
|
*/
|
|
3515
3690
|
grep(input) {
|
|
3516
3691
|
return this.client.grep(input);
|
|
@@ -3560,4 +3735,4 @@ var Busabase = class {
|
|
|
3560
3735
|
}
|
|
3561
3736
|
};
|
|
3562
3737
|
|
|
3563
|
-
export { Busabase, CREATABLE_NODE_TYPES, DEFAULT_BASE_URL, cloudContract, createBusabaseClient,
|
|
3738
|
+
export { Busabase, CREATABLE_NODE_TYPES, DEFAULT_BASE_URL, cloudContract, createBusabaseClient, getRecordByField, grepAssets, resolveConfig, toFilesOnlyGrepResult, toUnifiedFilesGrepInput };
|