busabase-sdk 0.17.3 → 0.19.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/dist/airapp.d.ts CHANGED
@@ -1,56 +1,11 @@
1
- import { B as BusabaseClient } from './client-BgQn-yGL.js';
2
- import '@orpc/contract';
3
- import '@orpc/shared';
4
- import 'zod';
5
-
6
- /**
7
- * AirApp resource provisioning — how an app claims (or creates) the Folder and
8
- * Bases it declares, exactly once, without ever taking over someone else's.
9
- *
10
- * Every App-in-Skill shipped a byte-identical copy of this module (280 lines ×
11
- * 65 apps, two spellings). That is the wrong place for it: the rules encoded
12
- * here are not app preferences, they are the safety boundary that keeps an app
13
- * from adopting a Folder a human created for something else. A third party
14
- * re-deriving them from scratch gets the happy path right and the conflict
15
- * cases wrong, and the failure is silent — the app happily writes into data it
16
- * does not own.
17
- *
18
- * The contract, in one line: **an app owns a node only if it stamped it.**
19
- * Ownership lives in `node.metadata` as `{ appId, resourceKey, schemaVersion }`.
20
- * Anything else is either a legacy node this app plausibly created before
21
- * stamping existed (claimable *only* after a full structural fingerprint match)
22
- * or someone else's (never touched, always a `SETUP_CONFLICT`).
23
- *
24
- * This module is isomorphic — browser and Node both — and holds no I/O beyond
25
- * the passed-in client.
26
- *
27
- * @example
28
- * ```ts
29
- * import { createBusabaseClient } from "busabase-sdk";
30
- * import { inspectProvisionedResources, provisionDeclaredResources } from "busabase-sdk/airapp";
31
- *
32
- * const client = createBusabaseClient({ baseUrl: window.location.origin });
33
- * const config = {
34
- * appId: "kelly-crm",
35
- * appName: "Kelly CRM",
36
- * schemaVersion: 1,
37
- * folder: { slug: "kelly-crm", name: "Kelly CRM", description: "CRM workspace" },
38
- * bases: [{ key: "contacts", slug: "kelly-crm-contacts-v1", name: "Contacts", fields: [...] }],
39
- * };
40
- *
41
- * let resources = await inspectProvisionedResources(client, config);
42
- * if (!resources.folder || resources.missing.length) {
43
- * resources = await provisionDeclaredResources(client, config); // one idempotent ChangeRequest
44
- * }
45
- * ```
46
- */
47
-
1
+ import { t as BusabaseClient } from "./client-slzL_ils.js";
2
+ //#region src/airapp.d.ts
48
3
  type NodeChangeRequestInput = Parameters<BusabaseClient["nodes"]["createChangeRequest"]>[0];
49
4
  type NodeOperationInput = NodeChangeRequestInput["operations"][number];
50
5
  type FileTreeChangeRequestInput = Parameters<BusabaseClient["fileTrees"]["createChangeRequest"]>[0];
51
6
  type FileTreeOperationInput = FileTreeChangeRequestInput["operations"][number];
52
7
  type FileTreeCreateOrUpdateOperation = Extract<FileTreeOperationInput, {
53
- kind: "create" | "update";
8
+ kind: "create" | "update";
54
9
  }>;
55
10
  /**
56
11
  * A Base field, as an app declares it.
@@ -65,35 +20,35 @@ type FileTreeCreateOrUpdateOperation = Extract<FileTreeOperationInput, {
65
20
  * surface to match how declarations are actually written.
66
21
  */
67
22
  interface AirAppFieldDeclaration {
68
- slug: string;
69
- name: string;
70
- type: string;
71
- required?: boolean;
72
- options?: Record<string, unknown>;
23
+ slug: string;
24
+ name: string;
25
+ type: string;
26
+ required?: boolean;
27
+ options?: Record<string, unknown>;
73
28
  }
74
29
  /** The client surface provisioning needs. Both `BusabaseClient` and `Busabase` satisfy it. */
75
30
  type AirAppProvisioningClient = Pick<BusabaseClient, "nodes" | "bases">;
76
31
  /** One Base the app declares it needs. `key` is the app's stable internal handle. */
77
32
  interface AirAppBaseDeclaration {
78
- /** Stable internal handle, e.g. `"contacts"`. Also the node's `resourceKey`. */
79
- key: string;
80
- slug: string;
81
- name: string;
82
- description?: string;
83
- fields: AirAppFieldDeclaration[];
84
- /** Resolved at provision time; ignore when declaring. */
85
- nodeId?: string;
86
- /** Resolved at provision time; ignore when declaring. */
87
- baseId?: string;
88
- /** Free-form extras an app keeps alongside its declaration (e.g. `readLimit`). */
89
- [extra: string]: unknown;
33
+ /** Stable internal handle, e.g. `"contacts"`. Also the node's `resourceKey`. */
34
+ key: string;
35
+ slug: string;
36
+ name: string;
37
+ description?: string;
38
+ fields: AirAppFieldDeclaration[];
39
+ /** Resolved at provision time; ignore when declaring. */
40
+ nodeId?: string;
41
+ /** Resolved at provision time; ignore when declaring. */
42
+ baseId?: string;
43
+ /** Free-form extras an app keeps alongside its declaration (e.g. `readLimit`). */
44
+ [extra: string]: unknown;
90
45
  }
91
46
  interface AirAppFolderDeclaration {
92
- slug: string;
93
- name: string;
94
- description?: string;
95
- /** Pin the Folder by id once known; otherwise it is discovered by slug. */
96
- nodeId?: string;
47
+ slug: string;
48
+ name: string;
49
+ description?: string;
50
+ /** Pin the Folder by id once known; otherwise it is discovered by slug. */
51
+ nodeId?: string;
97
52
  }
98
53
  /**
99
54
  * The app's own AirApp node, when it ships one inside its Folder.
@@ -109,76 +64,85 @@ interface AirAppFolderDeclaration {
109
64
  * unattributable stranger, and the legacy claim would be refused.
110
65
  */
111
66
  interface AirAppNodeDeclaration {
112
- slug: string;
113
- name: string;
114
- description?: string;
115
- /** Ownership key written into the node's metadata, e.g. `"airapp"`. */
116
- resourceKey: string;
67
+ slug: string;
68
+ name: string;
69
+ description?: string;
70
+ /** Ownership key written into the node's metadata, e.g. `"airapp"`. */
71
+ resourceKey: string;
117
72
  }
118
73
  /** Everything an app declares about the workspace shape it needs. */
119
74
  interface AirAppResourceConfig {
120
- appId: string;
121
- appName: string;
122
- /**
123
- * Bump when the declared shape changes. A node stamped with an older version
124
- * is re-stamped (a "repair"), not recreated — the data survives.
125
- */
126
- schemaVersion: number;
127
- folder: AirAppFolderDeclaration;
128
- bases: AirAppBaseDeclaration[];
129
- /** The app's own AirApp node inside the Folder, when it ships one. */
130
- airApp?: AirAppNodeDeclaration;
75
+ appId: string;
76
+ appName: string;
77
+ /**
78
+ * Bump when the declared shape changes. A node stamped with an older version
79
+ * is re-stamped (a "repair"), not recreated — the data survives.
80
+ */
81
+ schemaVersion: number;
82
+ folder: AirAppFolderDeclaration;
83
+ bases: AirAppBaseDeclaration[];
84
+ /** The app's own AirApp node inside the Folder, when it ships one. */
85
+ airApp?: AirAppNodeDeclaration;
131
86
  }
132
87
  /**
133
88
  * The ownership stamp written into `node.metadata`.
134
89
  *
90
+ * Structurally identical to (and kept in lockstep with) the contract package's
91
+ * `AppResourceOwnership`, which `busabase-package`'s installer writes for the
92
+ * SAME resources when a user installs the app from the Template Center instead
93
+ * of running its `setup.mjs`. The two writers only recognise each other's work
94
+ * by this shape — drift means a user who installed through the UI and then ran
95
+ * the skill in their shell hits `SETUP_CONFLICT` on their own data. The
96
+ * assertion below is what makes that drift a compile error rather than a
97
+ * support ticket.
98
+ *
135
99
  * A type alias rather than an `interface` on purpose: `nodes.updateMetadata`
136
100
  * and the create operations take `Record<string, unknown>`, and an interface —
137
101
  * being open to declaration merging — is not assignable to an index signature.
138
102
  */
139
103
  type AirAppResourceOwnership = {
140
- appId: string;
141
- resourceKey: string;
142
- schemaVersion: number;
104
+ appId: string;
105
+ resourceKey: string;
106
+ schemaVersion: number;
143
107
  };
144
108
  /** A node this app owns but whose ownership stamp needs (re)writing. */
145
109
  interface AirAppOwnershipRepair {
146
- nodeId: string;
147
- baseId?: string;
148
- resourceKey: string;
149
- metadata: AirAppResourceOwnership;
110
+ nodeId: string;
111
+ baseId?: string;
112
+ resourceKey: string;
113
+ metadata: AirAppResourceOwnership;
150
114
  }
151
115
  interface AirAppProvisionedBase extends AirAppBaseDeclaration {
152
- nodeId: string;
153
- baseId: string;
116
+ nodeId: string;
117
+ baseId: string;
154
118
  }
155
119
  interface AirAppResources {
156
- /** The app's root Folder, or `null` when it does not exist yet. */
157
- folder: (AirAppFolderDeclaration & {
158
- nodeId: string;
159
- }) | null;
160
- /** Declared Bases that exist and are owned, with their resolved ids. */
161
- bases: AirAppProvisionedBase[];
162
- /** Declared Bases that do not exist yet. */
163
- missing: AirAppBaseDeclaration[];
164
- /** Owned nodes whose ownership stamp is missing or stale. */
165
- repairs: AirAppOwnershipRepair[];
166
- /**
167
- * The app's own AirApp node (see `AirAppNodeDeclaration`), when `config.airApp`
168
- * is declared and a matching node exists under the Folder — owned or legacy,
169
- * stamped or not; a pending stamp repair is reported separately via `repairs`.
170
- * `null` when not declared, or declared but not found — the latter is what
171
- * `publishAirApp` treats as "create", not a `missing`-array entry, because
172
- * unlike a Base it is never auto-created just by finding it absent.
173
- */
174
- airApp: {
175
- nodeId: string;
176
- } | null;
177
- /**
178
- * Set when the server is too old for `nodes.updateMetadata`, so ownership was
179
- * established by full structural fingerprint instead of a stamp.
180
- */
181
- compatibilityMode?: "verified-legacy-fingerprint";
120
+ /** The app's root Folder, or `null` when it does not exist yet. */
121
+ folder: (AirAppFolderDeclaration & {
122
+ nodeId: string;
123
+ }) | null;
124
+ /** Declared Bases that exist and are owned, with their resolved ids. */
125
+ bases: AirAppProvisionedBase[];
126
+ /** Declared Bases that do not exist yet. */
127
+ missing: AirAppBaseDeclaration[];
128
+ /** Owned nodes whose ownership stamp is missing or stale. */
129
+ repairs: AirAppOwnershipRepair[];
130
+ /**
131
+ * The app's own AirApp node (see `AirAppNodeDeclaration`), when `config.airApp`
132
+ * is declared and a matching node exists under the Folder — owned or legacy,
133
+ * stamped or not; a pending stamp repair is reported separately via `repairs`.
134
+ * `null` when not declared, or declared but not found — the latter is what
135
+ * `publishAirApp` treats as "create", not a `missing`-array entry, because
136
+ * unlike a Base it is never auto-created just by finding it absent.
137
+ */
138
+ airApp: {
139
+ nodeId: string;
140
+ } | null;
141
+ /**
142
+ * Set when the server is too old for `nodes.updateMetadata`, so ownership was
143
+ * established by full structural fingerprint instead of a stamp.
144
+ */
145
+ compatibilityMode?: "verified-legacy-fingerprint";
182
146
  }
183
147
  /**
184
148
  * Why setup cannot proceed. These are the app's five distinguishable states —
@@ -199,27 +163,27 @@ type AirAppSetupCode = "SETUP_REQUIRED" | "SETUP_PENDING" | "SETUP_CONFLICT" | "
199
163
  * this class without touching its rendering code, then move to `error.code`.
200
164
  */
201
165
  declare class AirAppSetupError extends Error {
202
- readonly code: AirAppSetupCode;
203
- /** The human-readable half, without the `CODE: ` prefix. */
204
- readonly detail: string;
205
- constructor(code: AirAppSetupCode, detail: string);
166
+ readonly code: AirAppSetupCode;
167
+ /** The human-readable half, without the `CODE: ` prefix. */
168
+ readonly detail: string;
169
+ constructor(code: AirAppSetupCode, detail: string);
206
170
  }
207
171
  /** True for a 404 / NOT_FOUND from any of the client's transports. */
208
172
  declare const isNotFound: (error: unknown) => boolean;
209
173
  /** A node as this module reads it — the fields provisioning actually looks at. */
210
174
  interface ReadNode {
211
- id: string;
212
- type: string;
213
- slug: string;
214
- name: string;
215
- description: string;
216
- baseId: string | null;
217
- metadata: Record<string, unknown>;
218
- children?: ReadNode[];
175
+ id: string;
176
+ type: string;
177
+ slug: string;
178
+ name: string;
179
+ description: string;
180
+ baseId: string | null;
181
+ metadata: Record<string, unknown>;
182
+ children?: ReadNode[];
219
183
  }
220
184
  interface ReadFolderDetail {
221
- node: ReadNode;
222
- children: ReadNode[];
185
+ node: ReadNode;
186
+ children: ReadNode[];
223
187
  }
224
188
  /**
225
189
  * Decide, from one already-read Folder, what exists / is missing / needs
@@ -237,7 +201,7 @@ declare function resolveProvisionedFolder(folder: ReadFolderDetail | null | unde
237
201
  * structure lands in a single reviewable change.
238
202
  */
239
203
  declare function buildProvisionOperations(config: AirAppResourceConfig, folder: {
240
- nodeId: string;
204
+ nodeId: string;
241
205
  } | null, missingBases: AirAppBaseDeclaration[]): NodeOperationInput[];
242
206
  /** Read the current state of this app's declared resources. Never mutates. */
243
207
  declare function inspectProvisionedResources(client: AirAppProvisioningClient, config: AirAppResourceConfig): Promise<AirAppResources>;
@@ -254,19 +218,19 @@ declare function provisionDeclaredResources(client: AirAppProvisioningClient, co
254
218
  type AirAppPublishClient = AirAppProvisioningClient & Pick<BusabaseClient, "fileTrees" | "changeRequests">;
255
219
  /** One file of the app's built AirApp bundle, as `publishAirApp` receives it. */
256
220
  interface AirAppFileInput {
257
- path: string;
258
- content: string;
259
- mimeType?: string;
221
+ path: string;
222
+ content: string;
223
+ mimeType?: string;
260
224
  }
261
225
  type AirAppPublishResult = {
262
- status: "created";
263
- changeRequestId: string;
226
+ status: "created";
227
+ changeRequestId: string;
264
228
  } | {
265
- status: "updated";
266
- changeRequestId: string;
229
+ status: "updated";
230
+ changeRequestId: string;
267
231
  } | {
268
- status: "pending";
269
- changeRequestId: string;
232
+ status: "pending";
233
+ changeRequestId: string;
270
234
  };
271
235
  /**
272
236
  * The create-vs-update operation list for one AirApp publish. Pure — no I/O —
@@ -297,5 +261,5 @@ declare function buildAirAppFileOperations(localFiles: AirAppFileInput[], deploy
297
261
  * `airApp`; `SETUP_REQUIRED` when the Folder does not exist yet.
298
262
  */
299
263
  declare function publishAirApp(client: AirAppPublishClient, config: AirAppResourceConfig, files: AirAppFileInput[]): Promise<AirAppPublishResult>;
300
-
301
- export { type AirAppBaseDeclaration, type AirAppFieldDeclaration, type AirAppFileInput, type AirAppFolderDeclaration, type AirAppNodeDeclaration, type AirAppOwnershipRepair, type AirAppProvisionedBase, type AirAppProvisioningClient, type AirAppPublishClient, type AirAppPublishResult, type AirAppResourceConfig, type AirAppResourceOwnership, type AirAppResources, type AirAppSetupCode, AirAppSetupError, buildAirAppFileOperations, buildProvisionOperations, inspectProvisionedResources, isNotFound, provisionDeclaredResources, publishAirApp, resolveProvisionedFolder };
264
+ //#endregion
265
+ export { AirAppBaseDeclaration, AirAppFieldDeclaration, AirAppFileInput, AirAppFolderDeclaration, AirAppNodeDeclaration, AirAppOwnershipRepair, AirAppProvisionedBase, AirAppProvisioningClient, AirAppPublishClient, AirAppPublishResult, AirAppResourceConfig, AirAppResourceOwnership, AirAppResources, AirAppSetupCode, AirAppSetupError, buildAirAppFileOperations, buildProvisionOperations, inspectProvisionedResources, isNotFound, provisionDeclaredResources, publishAirApp, resolveProvisionedFolder };