busabase-sdk 0.10.1 → 0.10.2

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +4570 -11634
  2. package/dist/index.js +156 -234
  3. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -220,6 +220,15 @@ var restoreFieldChangeRequestInputSchema = z.object({
220
220
  message: z.string().optional(),
221
221
  submittedBy: z.string().optional().default("local-editor")
222
222
  });
223
+ var withBaseId = { baseId: z.string().min(1) };
224
+ var fieldChangeRequestInputSchema = z.discriminatedUnion("operation", [
225
+ createFieldChangeRequestInputSchema.extend({ operation: z.literal("create"), ...withBaseId }),
226
+ updateFieldChangeRequestInputSchema.extend({ operation: z.literal("update"), ...withBaseId }),
227
+ deleteFieldChangeRequestInputSchema.extend({ operation: z.literal("delete"), ...withBaseId }),
228
+ convertFieldChangeRequestInputSchema.extend({ operation: z.literal("convert"), ...withBaseId }),
229
+ reorderFieldsChangeRequestInputSchema.extend({ operation: z.literal("reorder"), ...withBaseId }),
230
+ restoreFieldChangeRequestInputSchema.extend({ operation: z.literal("restore"), ...withBaseId })
231
+ ]);
223
232
 
224
233
  // ../../packages/busabase-contract/src/domains/filetree/definition.ts
225
234
  var fileTreeOperations = (type) => [
@@ -521,7 +530,13 @@ var listNodesInputSchema = z.object({
521
530
  parentId: z.string().nullable().optional().describe("Node to start from. Omit or null to start from the space root."),
522
531
  depth: z.coerce.number().int().min(1).max(5).optional().describe(
523
532
  "How many levels beneath the start point to eagerly include (default 2 once either field is set). Capped at 5."
524
- )
533
+ ),
534
+ /**
535
+ * `active` (default) walks the live tree. `archived` returns the flat set of
536
+ * soft-archived nodes for the Trash view — no `parentId`/`depth` walk, since
537
+ * archived nodes are shown as a list, not a tree.
538
+ */
539
+ status: z.enum(["active", "archived"]).optional().default("active")
525
540
  }).optional();
526
541
  var isDescendantInputSchema = z.object({
527
542
  nodeId: z.string(),
@@ -850,6 +865,9 @@ var createCommentInputSchema = commentSubjectInputSchema.extend({
850
865
  var listInputSchema = z.object({
851
866
  limit: z.coerce.number().int().min(1).max(100).optional().default(50)
852
867
  }).optional().default({ limit: 50 });
868
+ var listByStatusInputSchema = z.object({
869
+ status: z.enum(["active", "archived"]).optional().default("active")
870
+ });
853
871
  var listChangeRequestsPagedInputSchema = z.object({
854
872
  limit: z.coerce.number().int().min(1).max(100).optional().default(50),
855
873
  /** Opaque base64 cursor (`createdAt|id`) for keyset pagination. */
@@ -1032,74 +1050,75 @@ var createFileTreeChangeRequestInputSchema = z.object({
1032
1050
  submittedBy: z.string().optional().default("local-producer"),
1033
1051
  operations: z.array(fileTreeFileOperationInputSchema).min(1)
1034
1052
  });
1035
- var makeFileTreeContract = (routeBase, tag) => {
1036
- const label = tag.endsWith("s") ? tag.slice(0, -1) : tag;
1037
- const basePath = `/${routeBase}`;
1038
- return {
1039
- list: oc.route({
1040
- method: "GET",
1041
- path: basePath,
1042
- tags: [tag],
1043
- summary: `List ${label} nodes`,
1044
- successDescription: `${label} nodes with their Asset-backed file trees.`
1045
- }).output(z.array(fileTreeNodeSchema)),
1046
- create: oc.route({
1047
- method: "POST",
1048
- path: basePath,
1049
- tags: [tag],
1050
- summary: `Create ${label} node`,
1051
- successDescription: `Review-first by default: a pending ChangeRequest proposing the ${label} node (\`materialized: false\`). Returns the materialized ${label} node instead (\`materialized: true\`) when \`autoMerge: true\` is passed.`
1052
- }).input(createFileTreeInputSchema).output(
1053
- z.union([
1054
- fileTreeNodeSchema.extend({ materialized: z.literal(true) }),
1055
- changeRequestSchema.extend({ materialized: z.literal(false) })
1056
- ])
1057
- ),
1058
- get: oc.route({
1059
- method: "GET",
1060
- path: `${basePath}/{nodeId}`,
1061
- tags: [tag],
1062
- summary: `Get ${label} node`,
1063
- successDescription: `${label} node detail and file tree.`
1064
- }).input(z.object({ nodeId: z.string() })).output(fileTreeNodeSchema),
1065
- listFiles: oc.route({
1066
- method: "GET",
1067
- path: `${basePath}/{nodeId}/files`,
1068
- tags: [tag],
1069
- summary: `List ${label} files`,
1070
- successDescription: `Asset-backed files mounted under the ${label} node.`
1071
- }).input(z.object({ nodeId: z.string() })).output(z.array(fileTreeFileSchema)),
1072
- readFile: oc.route({
1073
- method: "GET",
1074
- path: `${basePath}/{nodeId}/files/{+filePath}`,
1075
- tags: [tag],
1076
- summary: `Read ${label} file`,
1077
- successDescription: `${label} file content and content hash.`
1078
- }).input(z.object({ nodeId: z.string(), filePath: z.string() })).output(
1079
- z.object({
1080
- nodeId: z.string(),
1081
- path: z.string(),
1082
- encoding: z.enum(["utf8", "url"]),
1083
- content: z.string(),
1084
- mimeType: z.string(),
1085
- assetId: z.string(),
1086
- displayName: z.string().nullable(),
1087
- assetUrl: z.string().nullable(),
1088
- contentHash: z.string()
1089
- })
1090
- ),
1091
- createChangeRequest: oc.route({
1092
- method: "POST",
1093
- path: `${basePath}/{nodeId}/change-requests`,
1094
- tags: [tag, "Change Requests"],
1095
- summary: `Create ${label} change request`,
1096
- successDescription: `Created file-tree change request for a ${label} node.`
1097
- }).input(createFileTreeChangeRequestInputSchema.extend({ nodeId: z.string() })).output(changeRequestSchema)
1098
- };
1053
+ var FILE_TREE_NODE_TYPES = ["skill", "drive", "airapp"];
1054
+ var fileTreeNodeTypeSchema = z.enum(FILE_TREE_NODE_TYPES);
1055
+ var fileTreeRefSchema = z.object({
1056
+ nodeId: z.string(),
1057
+ type: fileTreeNodeTypeSchema.optional()
1058
+ });
1059
+ 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
+ create: oc.route({
1068
+ method: "POST",
1069
+ path: "/file-trees",
1070
+ tags: ["File Trees"],
1071
+ summary: "Create file-tree node",
1072
+ successDescription: "Review-first by default: a pending ChangeRequest proposing the node (`materialized: false`). Returns the materialized node instead (`materialized: true`) when `autoMerge: true` is passed."
1073
+ }).input(createFileTreeInputSchema.extend({ type: fileTreeNodeTypeSchema })).output(
1074
+ z.union([
1075
+ fileTreeNodeSchema.extend({ materialized: z.literal(true) }),
1076
+ changeRequestSchema.extend({ materialized: z.literal(false) })
1077
+ ])
1078
+ ),
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
+ listFiles: oc.route({
1087
+ method: "GET",
1088
+ path: "/file-trees/{nodeId}/files",
1089
+ tags: ["File Trees"],
1090
+ summary: "List file-tree files",
1091
+ successDescription: "Asset-backed files mounted under the node."
1092
+ }).input(fileTreeRefSchema).output(z.array(fileTreeFileSchema)),
1093
+ readFile: oc.route({
1094
+ method: "GET",
1095
+ path: "/file-trees/{nodeId}/files/{+filePath}",
1096
+ tags: ["File Trees"],
1097
+ summary: "Read file-tree file",
1098
+ successDescription: "File content and content hash."
1099
+ }).input(fileTreeRefSchema.extend({ filePath: z.string() })).output(
1100
+ z.object({
1101
+ nodeId: z.string(),
1102
+ path: z.string(),
1103
+ encoding: z.enum(["utf8", "url"]),
1104
+ content: z.string(),
1105
+ mimeType: z.string(),
1106
+ assetId: z.string(),
1107
+ displayName: z.string().nullable(),
1108
+ assetUrl: z.string().nullable(),
1109
+ contentHash: z.string()
1110
+ })
1111
+ ),
1112
+ createChangeRequest: oc.route({
1113
+ method: "POST",
1114
+ path: "/file-trees/{nodeId}/change-requests",
1115
+ tags: ["File Trees", "Change Requests"],
1116
+ summary: "Create file-tree change request",
1117
+ successDescription: "Created file-tree change request for the node."
1118
+ }).input(createFileTreeChangeRequestInputSchema.extend(fileTreeRefSchema.shape)).output(changeRequestSchema)
1099
1119
  };
1100
1120
 
1101
1121
  // ../../packages/busabase-contract/src/domains/airapp/contract.ts
1102
- var airappContract = makeFileTreeContract("airapps", "AirApps");
1103
1122
  var airAppRunLocalNodeInputSchema = z.object({
1104
1123
  nodeId: z.string(),
1105
1124
  /** Text files to mount into the sandbox workdir before installing, keyed by
@@ -1531,6 +1550,24 @@ var restoreViewInputSchema = z.object({
1531
1550
  message: z.string().optional().default("Restore view"),
1532
1551
  submittedBy: z.string().optional().default("local-producer")
1533
1552
  });
1553
+ var viewChangeRequestInputSchema = z.discriminatedUnion("operation", [
1554
+ createViewInputSchema.extend({
1555
+ operation: z.literal("create"),
1556
+ baseId: z.string().min(1).describe("Base the new view belongs to.")
1557
+ }),
1558
+ updateViewInputSchema.extend({
1559
+ operation: z.literal("update"),
1560
+ viewId: z.string().min(1)
1561
+ }),
1562
+ deleteViewInputSchema.extend({
1563
+ operation: z.literal("delete"),
1564
+ viewId: z.string().min(1)
1565
+ }),
1566
+ restoreViewInputSchema.extend({
1567
+ operation: z.literal("restore"),
1568
+ viewId: z.string().min(1)
1569
+ })
1570
+ ]);
1534
1571
 
1535
1572
  // ../../packages/busabase-contract/src/domains/base/contract/record-schemas.ts
1536
1573
  var recordSchema = z.object({
@@ -1564,21 +1601,21 @@ var listRecordsInputSchema = z.object({
1564
1601
  baseId: z.string().optional(),
1565
1602
  /** Opaque base64 cursor for keyset pagination (createdAt-keyed, or sort-keyed when `sort` is set). */
1566
1603
  cursor: z.string().optional(),
1604
+ /**
1605
+ * `active` (default) is the live table; `archived` is the Base's trash — the
1606
+ * same keyset pagination either way, which is why these are one endpoint
1607
+ * rather than a `/records/archived` twin.
1608
+ */
1609
+ status: z.enum(["active", "archived"]).optional().default("active"),
1567
1610
  /** View filters for server-side push-down (superset; client still narrows). */
1568
1611
  filters: z.array(listRecordsFilterSchema).optional(),
1569
1612
  /** View sort for server-side push-down (number/date fields only). */
1570
1613
  sort: listRecordsSortSchema.optional()
1571
- }).optional().default({ limit: 50 });
1614
+ }).optional().default({ limit: 50, status: "active" });
1572
1615
  var listRecordsResponseSchema = z.object({
1573
1616
  records: z.array(recordSchema),
1574
1617
  nextCursor: z.string().nullable()
1575
1618
  });
1576
- var listArchivedRecordsPagedInputSchema = z.object({
1577
- baseId: z.string(),
1578
- limit: z.coerce.number().int().min(1).max(100).optional().default(50),
1579
- /** Opaque base64 cursor (createdAt-keyed) for keyset pagination. */
1580
- cursor: z.string().optional()
1581
- });
1582
1619
  var countRecordsInputSchema = z.object({
1583
1620
  baseId: z.string().optional()
1584
1621
  }).optional().default({});
@@ -1633,6 +1670,16 @@ var restoreRecordInputSchema = z.object({
1633
1670
  message: z.string().optional(),
1634
1671
  submittedBy: z.string().optional().default("local-editor")
1635
1672
  });
1673
+ var withRecordId = { recordId: z.string().min(1) };
1674
+ var recordChangeRequestInputSchema = z.discriminatedUnion("operation", [
1675
+ reviseOperationInputSchema.extend({
1676
+ operation: z.literal("update"),
1677
+ autoMerge: z.boolean().optional(),
1678
+ ...withRecordId
1679
+ }),
1680
+ createDeleteChangeRequestInputSchema.extend({ operation: z.literal("delete"), ...withRecordId }),
1681
+ restoreRecordInputSchema.extend({ operation: z.literal("restore"), ...withRecordId })
1682
+ ]);
1636
1683
  var recordLinkSchema = z.object({
1637
1684
  id: z.string(),
1638
1685
  baseId: z.string(),
@@ -1652,22 +1699,15 @@ var baseContract = {
1652
1699
  path: "/bases",
1653
1700
  tags: ["Bases"],
1654
1701
  summary: "List Bases",
1655
- successDescription: "Flat list of developer-facing Bases."
1656
- }).output(z.array(baseSchema)),
1657
- listArchived: oc.route({
1658
- method: "GET",
1659
- path: "/bases/archived",
1660
- tags: ["Bases"],
1661
- summary: "List archived bases",
1662
- successDescription: "Bases that have been archived."
1663
- }).output(z.array(baseSchema)),
1702
+ successDescription: "Developer-facing Bases. `status=archived` returns the archived ones instead of the active ones."
1703
+ }).input(listByStatusInputSchema).output(z.array(baseSchema)),
1664
1704
  get: oc.route({
1665
1705
  method: "GET",
1666
1706
  path: "/bases/{baseId}",
1667
1707
  tags: ["Bases"],
1668
1708
  summary: "Get Base",
1669
- successDescription: "Single Base by id or slug."
1670
- }).input(z.object({ baseId: z.string() })).output(baseSchema.nullable()),
1709
+ successDescription: "Single Base by id or slug, or 404 when it does not exist or is not visible."
1710
+ }).input(z.object({ baseId: z.string() })).output(baseSchema),
1671
1711
  listDeletedFields: oc.route({
1672
1712
  method: "GET",
1673
1713
  path: "/bases/{baseId}/fields/deleted",
@@ -1679,30 +1719,9 @@ var baseContract = {
1679
1719
  method: "GET",
1680
1720
  path: "/bases/{baseId}/views",
1681
1721
  tags: ["Views"],
1682
- summary: "List active views for a Base",
1683
- successDescription: "Saved table views for a Base."
1684
- }).input(z.object({ baseId: z.string() })).output(z.array(viewSchema)),
1685
- listArchivedViews: oc.route({
1686
- method: "GET",
1687
- path: "/bases/{baseId}/views/archived",
1688
- tags: ["Views"],
1689
- summary: "List archived views for a Base",
1690
- successDescription: "Views that have been archived (soft-deleted) from a Base."
1691
- }).input(z.object({ baseId: z.string() })).output(z.array(viewSchema)),
1692
- listArchivedRecords: oc.route({
1693
- method: "GET",
1694
- path: "/bases/{baseId}/records/archived",
1695
- tags: ["Records"],
1696
- summary: "List archived records for a Base",
1697
- successDescription: "Records that have been archived (soft-deleted) from a Base."
1698
- }).input(z.object({ baseId: z.string() })).output(z.array(recordSchema)),
1699
- listArchivedRecordsPaged: oc.route({
1700
- method: "GET",
1701
- path: "/bases/{baseId}/records/archived/paged",
1702
- tags: ["Records"],
1703
- summary: "List archived records for a Base with keyset pagination",
1704
- successDescription: "A page of archived (soft-deleted) records plus an opaque nextCursor (null at the end)."
1705
- }).input(listArchivedRecordsPagedInputSchema).output(listRecordsResponseSchema),
1722
+ summary: "List views for a Base",
1723
+ successDescription: "Saved table views for a Base. `status=archived` returns the soft-deleted ones instead."
1724
+ }).input(listByStatusInputSchema.extend({ baseId: z.string() })).output(z.array(viewSchema)),
1706
1725
  create: oc.route({
1707
1726
  method: "POST",
1708
1727
  path: "/bases",
@@ -1741,34 +1760,13 @@ var baseContract = {
1741
1760
  summary: "Create Base field",
1742
1761
  successDescription: "Created Base field."
1743
1762
  }).input(createBaseFieldInputSchema.extend({ baseId: z.string() })).output(baseSchema),
1744
- createFieldChangeRequest: oc.route({
1745
- method: "POST",
1746
- path: "/bases/{baseId}/fields/change-requests",
1747
- tags: ["Bases", "Change Requests"],
1748
- summary: "Create Add Field change request",
1749
- successDescription: "Created change request that proposes a new field."
1750
- }).input(createFieldChangeRequestInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1751
- createViewChangeRequest: oc.route({
1763
+ fieldChangeRequest: oc.route({
1752
1764
  method: "POST",
1753
- path: "/bases/{baseId}/views/change-requests",
1754
- tags: ["Views", "Change Requests"],
1755
- summary: "Create View change request",
1756
- successDescription: "Created change request that proposes a new View."
1757
- }).input(createViewInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1758
- deleteFieldChangeRequest: oc.route({
1759
- method: "DELETE",
1760
- path: "/bases/{baseId}/fields/change-requests",
1761
- tags: ["Bases", "Change Requests"],
1762
- summary: "Create Delete Field change request",
1763
- successDescription: "Created change request that soft-deletes a field."
1764
- }).input(deleteFieldChangeRequestInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1765
- updateFieldChangeRequest: oc.route({
1766
- method: "PATCH",
1767
1765
  path: "/bases/{baseId}/fields/change-requests",
1768
1766
  tags: ["Bases", "Change Requests"],
1769
- summary: "Create Update Field change request",
1770
- successDescription: "Created change request that updates field metadata (name, required, options)."
1771
- }).input(updateFieldChangeRequestInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1767
+ summary: "Create field change request",
1768
+ successDescription: "Created change request proposing a field change. `operation` selects what to propose: `create`, `update`, `delete`, `convert` (change type), `reorder`, or `restore` (undo a soft delete)."
1769
+ }).input(fieldChangeRequestInputSchema).output(changeRequestSchema),
1772
1770
  previewFieldConversion: oc.route({
1773
1771
  method: "POST",
1774
1772
  path: "/bases/{baseId}/fields/convert/preview",
@@ -1776,20 +1774,6 @@ var baseContract = {
1776
1774
  summary: "Preview field type conversion",
1777
1775
  successDescription: "Dry-run statistics for converting a field to a different type."
1778
1776
  }).input(previewFieldConversionInputSchema.extend({ baseId: z.string() })).output(previewFieldConversionOutputSchema),
1779
- convertFieldChangeRequest: oc.route({
1780
- method: "POST",
1781
- path: "/bases/{baseId}/fields/convert/change-requests",
1782
- tags: ["Bases", "Change Requests"],
1783
- summary: "Create Convert Field change request",
1784
- successDescription: "Created change request that converts a field to a different type."
1785
- }).input(convertFieldChangeRequestInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1786
- reorderFieldsChangeRequest: oc.route({
1787
- method: "POST",
1788
- path: "/bases/{baseId}/fields/reorder/change-requests",
1789
- tags: ["Bases", "Change Requests"],
1790
- summary: "Reorder fields",
1791
- successDescription: "Created change request that reorders fields."
1792
- }).input(reorderFieldsChangeRequestInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1793
1777
  archiveChangeRequest: oc.route({
1794
1778
  method: "POST",
1795
1779
  path: "/bases/{baseId}/archive/change-requests",
@@ -1803,29 +1787,19 @@ var baseContract = {
1803
1787
  tags: ["Bases", "Change Requests"],
1804
1788
  summary: "Restore base",
1805
1789
  successDescription: "Created change request that restores an archived base."
1806
- }).input(restoreBaseInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema),
1807
- restoreFieldChangeRequest: oc.route({
1808
- method: "POST",
1809
- path: "/bases/{baseId}/fields/restore/change-requests",
1810
- tags: ["Bases", "Change Requests"],
1811
- summary: "Restore deleted field",
1812
- successDescription: "Created change request that restores a soft-deleted field."
1813
- }).input(restoreFieldChangeRequestInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema)
1790
+ }).input(restoreBaseInputSchema.extend({ baseId: z.string() })).output(changeRequestSchema)
1814
1791
  };
1815
1792
  var recordContract = {
1793
+ // One listing for records: always keyset-paginated, `baseId` always honoured,
1794
+ // `status` picking live rows or the trash. The old unpaginated `/records`
1795
+ // silently dropped `baseId` (its schema had no such field), so a caller
1796
+ // scoping to one Base quietly got the whole space back.
1816
1797
  list: oc.route({
1817
1798
  method: "GET",
1818
1799
  path: "/records",
1819
1800
  tags: ["Records"],
1820
1801
  summary: "List records",
1821
- successDescription: "Canonical records created from merged change requests."
1822
- }).input(listInputSchema).output(z.array(recordSchema)),
1823
- listPaged: oc.route({
1824
- method: "GET",
1825
- path: "/records/paged",
1826
- tags: ["Records"],
1827
- summary: "List records with keyset pagination",
1828
- successDescription: "A page of canonical records plus an opaque nextCursor (null at the end)."
1802
+ 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."
1829
1803
  }).input(listRecordsInputSchema).output(listRecordsResponseSchema),
1830
1804
  count: oc.route({
1831
1805
  method: "GET",
@@ -1855,30 +1829,18 @@ var recordContract = {
1855
1829
  summary: "Get record by field value",
1856
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."
1857
1831
  }).input(recordFieldGetInputSchema).output(recordSchema.nullable()),
1858
- updateChangeRequest: oc.route({
1859
- method: "PUT",
1832
+ changeRequest: oc.route({
1833
+ method: "POST",
1860
1834
  path: "/records/{recordId}/change-requests",
1861
1835
  tags: ["Records", "Change Requests"],
1862
- summary: "Create record update change request",
1863
- successDescription: "Permission-aware by default: updates the record immediately when the actor has write access, otherwise returns a pending ChangeRequest. Pass `autoMerge: false` to force review."
1864
- }).input(
1865
- reviseOperationInputSchema.extend({
1866
- recordId: z.string(),
1867
- autoMerge: z.boolean().optional()
1868
- })
1869
- ).output(
1836
+ summary: "Create record change request",
1837
+ successDescription: "Creates a record change request selected by `operation`. Updates auto-merge when the actor has write access unless `autoMerge: false`; delete and restore remain review-first."
1838
+ }).input(recordChangeRequestInputSchema).output(
1870
1839
  z.union([
1871
1840
  recordSchema.extend({ materialized: z.literal(true) }),
1872
1841
  changeRequestSchema.extend({ materialized: z.literal(false) })
1873
1842
  ])
1874
1843
  ),
1875
- deleteChangeRequest: oc.route({
1876
- method: "DELETE",
1877
- path: "/records/{recordId}/change-requests",
1878
- tags: ["Records", "Change Requests"],
1879
- summary: "Create record delete change request",
1880
- successDescription: "Created change request that proposes archiving or deleting a record."
1881
- }).input(createDeleteChangeRequestInputSchema.extend({ recordId: z.string() })).output(changeRequestSchema),
1882
1844
  listChangeRequests: oc.route({
1883
1845
  method: "GET",
1884
1846
  path: "/records/{recordId}/change-requests",
@@ -1886,13 +1848,6 @@ var recordContract = {
1886
1848
  summary: "List record change request history",
1887
1849
  successDescription: "Change requests and operations connected to the canonical record."
1888
1850
  }).input(z.object({ recordId: z.string() })).output(z.array(changeRequestSchema)),
1889
- restoreChangeRequest: oc.route({
1890
- method: "POST",
1891
- path: "/records/{recordId}/restore/change-requests",
1892
- tags: ["Records", "Change Requests"],
1893
- summary: "Create record restore change request",
1894
- successDescription: "Created change request that restores an archived record."
1895
- }).input(restoreRecordInputSchema.extend({ recordId: z.string() })).output(changeRequestSchema),
1896
1851
  listLinks: oc.route({
1897
1852
  method: "GET",
1898
1853
  path: "/records/{recordId}/links",
@@ -1902,27 +1857,13 @@ var recordContract = {
1902
1857
  }).input(z.object({ recordId: z.string() })).output(z.array(recordLinkSchema))
1903
1858
  };
1904
1859
  var viewContract = {
1905
- updateChangeRequest: oc.route({
1906
- method: "PUT",
1907
- path: "/views/{viewId}/change-requests",
1908
- tags: ["Views", "Change Requests"],
1909
- summary: "Create View update change request",
1910
- successDescription: "Created change request that proposes updating a View."
1911
- }).input(updateViewInputSchema.extend({ viewId: z.string() })).output(changeRequestSchema),
1912
- deleteChangeRequest: oc.route({
1913
- method: "DELETE",
1914
- path: "/views/{viewId}/change-requests",
1915
- tags: ["Views", "Change Requests"],
1916
- summary: "Create View delete change request",
1917
- successDescription: "Created change request that proposes archiving a View."
1918
- }).input(deleteViewInputSchema.extend({ viewId: z.string() })).output(changeRequestSchema),
1919
- restoreChangeRequest: oc.route({
1860
+ changeRequest: oc.route({
1920
1861
  method: "POST",
1921
- path: "/views/{viewId}/restore/change-requests",
1862
+ path: "/views/change-requests",
1922
1863
  tags: ["Views", "Change Requests"],
1923
- summary: "Create View restore change request",
1924
- successDescription: "Created change request that restores an archived View."
1925
- }).input(restoreViewInputSchema.extend({ viewId: z.string() })).output(changeRequestSchema)
1864
+ summary: "Create view change request",
1865
+ successDescription: "Created change request proposing a view change. `operation` selects what to propose: `create` (addressed by `baseId`), or `update` / `delete` / `restore` (addressed by `viewId`)."
1866
+ }).input(viewChangeRequestInputSchema).output(changeRequestSchema)
1926
1867
  };
1927
1868
  var ReadDocLinesInputSchema = z.object({
1928
1869
  nodeId: z.string(),
@@ -2009,9 +1950,6 @@ var docContract = {
2009
1950
  successDescription: "Created a change request that proposes a new Doc body."
2010
1951
  }).input(createDocChangeRequestInputSchema.extend({ nodeId: z.string() })).output(changeRequestSchema)
2011
1952
  };
2012
-
2013
- // ../../packages/busabase-contract/src/domains/drive/contract.ts
2014
- var driveContract = makeFileTreeContract("drives", "Drives");
2015
1953
  var DumpTableSchema = z.enum([
2016
1954
  "nodes",
2017
1955
  /** Node-level access grants (permissions). Not secret — restore must keep them
@@ -2466,9 +2404,6 @@ var installContract = {
2466
2404
  successDescription: "Created counts plus the number of change requests left for review. Structure (folders, Bases, fields, views) is created immediately \u2014 a pending Base has no id to attach a view or record to; content (records, docs, skills, AirApps) lands as change requests unless `autoMerge` is set."
2467
2405
  }).input(InstallFromGithubDTOSchema).output(InstallResultVOSchema)
2468
2406
  };
2469
-
2470
- // ../../packages/busabase-contract/src/domains/skill/contract.ts
2471
- var skillContract = makeFileTreeContract("skills", "Skills");
2472
2407
  var VaultItemKeySchema = z.string().trim().min(1).max(128).regex(/^[A-Z_][A-Z0-9_]*$/, "Use uppercase letters, numbers, and underscores");
2473
2408
  var VaultItemValueSchema = z.string().max(8192);
2474
2409
  var VaultItemKindSchema = z.enum(["secret", "variable"]);
@@ -2905,13 +2840,6 @@ var busabaseContractRoutes = {
2905
2840
  summary: "Check whether a node is a descendant of another",
2906
2841
  successDescription: "Server-authoritative parentId-chain walk from nodeId up to potentialAncestorId. Used to gate cross-branch drag-and-drop drops in the sidebar, since the full tree is no longer guaranteed to be loaded client-side (depth-bounded lazy load) \u2014 a purely local walk could wrongly allow dropping a folder into its own unloaded descendant."
2907
2842
  }).input(isDescendantInputSchema).output(isDescendantOutputSchema),
2908
- listArchived: oc.route({
2909
- method: "GET",
2910
- path: "/nodes/archived",
2911
- tags: ["Nodes"],
2912
- summary: "List archived nodes",
2913
- successDescription: "Soft-archived folders, docs, and skills (for the Trash view)."
2914
- }).output(z.array(nodeSchema)),
2915
2843
  createChangeRequest: oc.route({
2916
2844
  method: "POST",
2917
2845
  path: "/nodes/change-requests",
@@ -3093,9 +3021,10 @@ var busabaseContractRoutes = {
3093
3021
  subscribe: oc.output(eventIterator(liveEventSchema))
3094
3022
  },
3095
3023
  bases: baseContract,
3096
- skills: skillContract,
3097
- drives: driveContract,
3098
- airapps: { ...airappContract, ...airappRuntimeContract },
3024
+ // Skills, Drives, and AirApps share one transport surface — they differ only
3025
+ // in seed files and entry file, which is a server-side config concern.
3026
+ fileTrees: fileTreeContract,
3027
+ airapps: airappRuntimeContract,
3099
3028
  files: fileContract,
3100
3029
  docs: docContract,
3101
3030
  folders: folderContract,
@@ -3106,18 +3035,13 @@ var busabaseContractRoutes = {
3106
3035
  dump: dumpContract,
3107
3036
  install: installContract,
3108
3037
  changeRequests: {
3038
+ // Always keyset-paginated — the unpaginated twin returned a bare array that
3039
+ // silently truncated at `limit` with no way to ask for the next page.
3109
3040
  list: oc.route({
3110
3041
  method: "GET",
3111
3042
  path: "/change-requests",
3112
3043
  tags: ["Change Requests"],
3113
3044
  summary: "List change requests",
3114
- successDescription: "Change requests waiting for review or ready to merge."
3115
- }).input(listInputSchema).output(z.array(changeRequestSchema)),
3116
- listPaged: oc.route({
3117
- method: "GET",
3118
- path: "/change-requests/paged",
3119
- tags: ["Change Requests"],
3120
- summary: "List change requests with keyset pagination",
3121
3045
  successDescription: "A page of change requests plus an opaque nextCursor (null at the end). Filter with `status` and/or `mine`."
3122
3046
  }).input(listChangeRequestsPagedInputSchema).output(listChangeRequestsResponseSchema),
3123
3047
  counts: oc.route({
@@ -3552,11 +3476,9 @@ var Busabase = class {
3552
3476
  get assets() {
3553
3477
  return this.client.assets;
3554
3478
  }
3555
- get skills() {
3556
- return this.client.skills;
3557
- }
3558
- get drives() {
3559
- return this.client.drives;
3479
+ /** Skills, Drives, and AirApps — one surface, discriminated by `type`. */
3480
+ get fileTrees() {
3481
+ return this.client.fileTrees;
3560
3482
  }
3561
3483
  get files() {
3562
3484
  return this.client.files;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "busabase-sdk",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Typed TypeScript/JavaScript SDK for the Busabase OpenAPI REST API. Talks to a local or remote `busabase server` (or Busabase Cloud).",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/busabase/busabase/tree/main/apps/busabase-sdk",
@@ -41,7 +41,7 @@
41
41
  "tsx": "^4.20.5",
42
42
  "typescript": "^5.9.3",
43
43
  "vitest": "^2.1.8",
44
- "busabase-contract": "0.10.1",
44
+ "busabase-contract": "0.10.2",
45
45
  "open-domains": "0.0.2",
46
46
  "openlib": "0.1.1"
47
47
  },