@oxy-hq/sdk 1.0.0 → 2.0.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 +64 -443
- package/dist/index.cjs +1585 -1018
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +464 -897
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +464 -897
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1571 -988
- package/dist/index.mjs.map +1 -1
- package/package.json +73 -78
- package/dist/postMessage-Cb5PCtcE.cjs +0 -233
- package/dist/postMessage-Cb5PCtcE.cjs.map +0 -1
- package/dist/postMessage-Gnhr_wnw.mjs +0 -207
- package/dist/postMessage-Gnhr_wnw.mjs.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,967 +1,534 @@
|
|
|
1
1
|
|
|
2
|
-
import * as
|
|
3
|
-
import React, { ReactNode } from "react";
|
|
2
|
+
import * as React from "react";
|
|
4
3
|
|
|
5
|
-
//#region src/
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
*/
|
|
9
|
-
|
|
4
|
+
//#region src/customer-app/manifest.d.ts
|
|
5
|
+
/** Wire shape of `oxy-app.json` (v2 only). */
|
|
6
|
+
interface OxyAppManifest {
|
|
7
|
+
/** Must be 2. v1 manifests are no longer supported. */
|
|
8
|
+
schemaVersion: 2;
|
|
10
9
|
/**
|
|
11
|
-
*
|
|
10
|
+
* Optional display name. The admin "Link existing" dialog prefills
|
|
11
|
+
* its Name field from this. Omit to let oxy fall back to the
|
|
12
|
+
* folder basename.
|
|
12
13
|
*/
|
|
13
|
-
|
|
14
|
+
name?: string;
|
|
14
15
|
/**
|
|
15
|
-
*
|
|
16
|
+
* URL slug. **Required.** The canonical source of truth — the
|
|
17
|
+
* dialog locks the slug field to this value, and
|
|
18
|
+
* `OXY_APP_BASE_PATH=/customer-apps/<org>/<slug>/` baked into the
|
|
19
|
+
* build must match.
|
|
16
20
|
*/
|
|
17
|
-
|
|
21
|
+
slug: string;
|
|
18
22
|
/**
|
|
19
|
-
*
|
|
23
|
+
* Optional org slug. Prefills the dialog's org picker; operator
|
|
24
|
+
* can still override. Carries no security weight — the actual
|
|
25
|
+
* access check is on the linked row.
|
|
20
26
|
*/
|
|
21
|
-
|
|
27
|
+
orgSlug?: string;
|
|
22
28
|
/**
|
|
23
|
-
* Optional
|
|
29
|
+
* Optional project (workspace) uuid the bundle expects to read
|
|
30
|
+
* from. Used by `useQuery` to construct the
|
|
31
|
+
* `/api/projects/:id/query` URL.
|
|
24
32
|
*/
|
|
25
|
-
|
|
33
|
+
projectId?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Manifest + runtime-injected identity needed to call oxy. Callers
|
|
37
|
+
* should treat this as the only source of truth for "which org/app
|
|
38
|
+
* does this bundle belong to."
|
|
39
|
+
*/
|
|
40
|
+
interface ResolvedCustomerAppManifest {
|
|
41
|
+
manifest: OxyAppManifest;
|
|
26
42
|
/**
|
|
27
|
-
*
|
|
43
|
+
* Always an empty array for v2 manifests. Kept for API compatibility;
|
|
44
|
+
* callers that previously iterated product names should switch to
|
|
45
|
+
* explicit `useQuery` calls.
|
|
46
|
+
* @deprecated Will be removed in a future version.
|
|
28
47
|
*/
|
|
29
|
-
|
|
48
|
+
productNames: string[];
|
|
49
|
+
/** Org slug injected by oxy. */
|
|
50
|
+
orgSlug: string;
|
|
51
|
+
/** App slug injected by oxy. */
|
|
52
|
+
appSlug: string;
|
|
30
53
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
* Use '*' only in development!
|
|
54
|
+
* The oxy server's API base URL. Empty string when oxy serves the
|
|
55
|
+
* bundle itself (same-origin, the common case); a full URL only
|
|
56
|
+
* when the bundle is running under a dev server proxy.
|
|
35
57
|
*/
|
|
36
|
-
|
|
58
|
+
apiBaseUrl: string;
|
|
59
|
+
/** App UUID; informational. */
|
|
60
|
+
appId?: string;
|
|
37
61
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
62
|
+
* Project (workspace) UUID. Injection (`window.__OXY_APP__.projectId`)
|
|
63
|
+
* wins over the manifest's `projectId` field — the admin row is
|
|
64
|
+
* authoritative. Manifest `projectId` is a dev-time hint used only
|
|
65
|
+
* when running without a server. Used by `useQuery` to construct the
|
|
66
|
+
* `/api/projects/:id/query` URL.
|
|
40
67
|
*/
|
|
41
|
-
disableAutoAuth?: boolean;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Creates an Oxy configuration from environment variables
|
|
45
|
-
*
|
|
46
|
-
* Environment variables:
|
|
47
|
-
* - OXY_URL: Base URL of the Oxy API
|
|
48
|
-
* - OXY_API_KEY: API key for authentication
|
|
49
|
-
* - OXY_PROJECT_ID: Project ID (UUID)
|
|
50
|
-
* - OXY_BRANCH: (Optional) Branch name
|
|
51
|
-
*
|
|
52
|
-
* @param overrides - Optional configuration overrides
|
|
53
|
-
* @returns OxyConfig object
|
|
54
|
-
* @throws Error if required environment variables are missing
|
|
55
|
-
*/
|
|
56
|
-
declare function createConfig(overrides?: Partial<OxyConfig>): OxyConfig;
|
|
57
|
-
/**
|
|
58
|
-
* Creates an Oxy configuration asynchronously with support for postMessage authentication
|
|
59
|
-
*
|
|
60
|
-
* This is the recommended method for iframe scenarios where authentication
|
|
61
|
-
* needs to be obtained from the parent window via postMessage.
|
|
62
|
-
*
|
|
63
|
-
* When running in an iframe without an API key, this function will:
|
|
64
|
-
* 1. Detect the iframe context
|
|
65
|
-
* 2. Send an authentication request to the parent window
|
|
66
|
-
* 3. Wait for the parent to respond with credentials
|
|
67
|
-
* 4. Return the configured client
|
|
68
|
-
*
|
|
69
|
-
* Environment variables (fallback):
|
|
70
|
-
* - OXY_URL: Base URL of the Oxy API
|
|
71
|
-
* - OXY_API_KEY: API key for authentication
|
|
72
|
-
* - OXY_PROJECT_ID: Project ID (UUID)
|
|
73
|
-
* - OXY_BRANCH: (Optional) Branch name
|
|
74
|
-
*
|
|
75
|
-
* @param overrides - Optional configuration overrides
|
|
76
|
-
* @returns Promise resolving to OxyConfig object
|
|
77
|
-
* @throws Error if required configuration is missing
|
|
78
|
-
* @throws PostMessageAuthTimeoutError if parent doesn't respond
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```typescript
|
|
82
|
-
* // Automatic iframe detection and authentication
|
|
83
|
-
* const config = await createConfigAsync({
|
|
84
|
-
* parentOrigin: 'https://app.example.com',
|
|
85
|
-
* projectId: 'my-project-id',
|
|
86
|
-
* baseUrl: 'https://api.oxy.tech'
|
|
87
|
-
* });
|
|
88
|
-
* ```
|
|
89
|
-
*/
|
|
90
|
-
declare function createConfigAsync(overrides?: Partial<OxyConfig>): Promise<OxyConfig>;
|
|
91
|
-
//#endregion
|
|
92
|
-
//#region src/types.d.ts
|
|
93
|
-
/**
|
|
94
|
-
* Represents an app item in the project
|
|
95
|
-
*/
|
|
96
|
-
interface AppItem {
|
|
97
|
-
name: string;
|
|
98
|
-
path: string;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Reference to a data file (usually parquet)
|
|
102
|
-
*/
|
|
103
|
-
interface FileReference {
|
|
104
|
-
file_path: string;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Table data structure for in-memory tables
|
|
108
|
-
* (used when data is fetched and parsed)
|
|
109
|
-
*/
|
|
110
|
-
interface TableData {
|
|
111
|
-
columns: string[];
|
|
112
|
-
rows: unknown[][];
|
|
113
|
-
total_rows?: number;
|
|
114
|
-
}
|
|
115
|
-
type DataContainer = Record<string, FileReference>;
|
|
116
|
-
/**
|
|
117
|
-
* Response from app data endpoints
|
|
118
|
-
*/
|
|
119
|
-
interface AppDataResponse {
|
|
120
|
-
data: DataContainer | null;
|
|
121
|
-
error: string | null;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Display with potential error
|
|
125
|
-
*/
|
|
126
|
-
interface DisplayWithError {
|
|
127
|
-
display?: DisplayData;
|
|
128
|
-
error?: string;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Display data structure
|
|
132
|
-
*/
|
|
133
|
-
interface DisplayData {
|
|
134
|
-
type: string;
|
|
135
|
-
content: unknown;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Response from get displays endpoint
|
|
139
|
-
*/
|
|
140
|
-
interface GetDisplaysResponse {
|
|
141
|
-
displays: DisplayWithError[];
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* PostMessage authentication protocol types
|
|
145
|
-
*/
|
|
146
|
-
/**
|
|
147
|
-
* Request message sent from iframe to parent window
|
|
148
|
-
*/
|
|
149
|
-
interface OxyAuthRequestMessage {
|
|
150
|
-
type: "OXY_AUTH_REQUEST";
|
|
151
|
-
version: "1.0";
|
|
152
|
-
timestamp: number;
|
|
153
|
-
requestId: string;
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Response message sent from parent window to iframe
|
|
157
|
-
*/
|
|
158
|
-
interface OxyAuthResponseMessage {
|
|
159
|
-
type: "OXY_AUTH_RESPONSE";
|
|
160
|
-
version: "1.0";
|
|
161
|
-
requestId: string;
|
|
162
|
-
apiKey?: string;
|
|
163
68
|
projectId?: string;
|
|
164
|
-
baseUrl?: string;
|
|
165
69
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
/** Number of retry attempts (default: 0) */
|
|
175
|
-
retries?: number;
|
|
70
|
+
interface LoadManifestOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Override the URL the manifest is fetched from. Default:
|
|
73
|
+
* `<injected_base>/oxy-app.json` or `/oxy-app.json`.
|
|
74
|
+
* Useful for non-Next bundlers — set explicitly to wherever your
|
|
75
|
+
* bundler emits static assets.
|
|
76
|
+
*/
|
|
77
|
+
manifestUrl?: string;
|
|
176
78
|
}
|
|
177
79
|
/**
|
|
178
|
-
*
|
|
80
|
+
* Load + validate the manifest. Cached after the first call so callers
|
|
81
|
+
* can invoke this from every component without coordinating.
|
|
179
82
|
*/
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
83
|
+
declare function loadCustomerAppManifest(options?: LoadManifestOptions): Promise<ResolvedCustomerAppManifest>;
|
|
84
|
+
/** For tests: reset the cache between runs. */
|
|
85
|
+
declare function _resetCustomerAppManifestCacheForTest(): void;
|
|
86
|
+
//#endregion
|
|
87
|
+
//#region src/customer-app/debug.d.ts
|
|
88
|
+
/** Untyped at the boundary — keep it loose so server-side schema
|
|
89
|
+
* additions don't break older bundles. Stable enough for inspection
|
|
90
|
+
* but not a contract clients should depend on field-by-field. */
|
|
91
|
+
interface CustomerAppDebugSnapshot {
|
|
92
|
+
org_slug: string;
|
|
93
|
+
app_slug: string;
|
|
94
|
+
app: {
|
|
95
|
+
id: string;
|
|
96
|
+
slug: string;
|
|
97
|
+
name: string;
|
|
98
|
+
status: string;
|
|
99
|
+
source_type: string;
|
|
100
|
+
project_id: string;
|
|
101
|
+
branch: string;
|
|
102
|
+
};
|
|
103
|
+
bundle_dir: string | null;
|
|
104
|
+
bundle_dir_exists: boolean;
|
|
105
|
+
/** Raw parsed manifest from the server — kept loose so schema additions don't break older bundles. */
|
|
106
|
+
manifest: Record<string, unknown> | null;
|
|
107
|
+
manifest_error: string | null;
|
|
108
|
+
products: Array<{
|
|
109
|
+
name: string;
|
|
110
|
+
producer: string;
|
|
111
|
+
}>;
|
|
185
112
|
}
|
|
186
113
|
/**
|
|
187
|
-
*
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
*
|
|
114
|
+
* Fetch the server-side diagnostic snapshot for this bundle. Pair with
|
|
115
|
+
* `loadCustomerAppManifest()` — pass its result here. Logs the
|
|
116
|
+
* snapshot through the SDK logger so it appears in the bundle's
|
|
117
|
+
* console at info level.
|
|
191
118
|
*/
|
|
192
|
-
declare
|
|
193
|
-
|
|
119
|
+
declare function getCustomerAppDebug(resolved: ResolvedCustomerAppManifest): Promise<CustomerAppDebugSnapshot>;
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region src/customer-app/errors.d.ts
|
|
122
|
+
interface CustomerAppErrorReport {
|
|
123
|
+
title: string;
|
|
124
|
+
message: string;
|
|
125
|
+
hint: string;
|
|
126
|
+
docs?: string;
|
|
194
127
|
}
|
|
128
|
+
/** Interpret a thrown error as a structured report for UI display. */
|
|
129
|
+
declare function interpretCustomerAppError(err: unknown): CustomerAppErrorReport;
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region src/customer-app/inject.d.ts
|
|
195
132
|
/**
|
|
196
|
-
*
|
|
133
|
+
* Shape of `window.__OXY_APP__` written by oxy at serve time.
|
|
134
|
+
* Consumed by `loadCustomerAppManifest` as the authoritative identity
|
|
135
|
+
* source (overrides any hints in `oxy-app.json`).
|
|
197
136
|
*/
|
|
198
|
-
|
|
199
|
-
|
|
137
|
+
interface OxyInjectedAppConfig {
|
|
138
|
+
appId: string;
|
|
139
|
+
slug: string;
|
|
140
|
+
orgId: string;
|
|
141
|
+
orgSlug: string;
|
|
142
|
+
projectId: string;
|
|
143
|
+
branch: string;
|
|
144
|
+
/** Empty string means same-origin (the default for v2). */
|
|
145
|
+
apiBaseUrl: string;
|
|
200
146
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
constructor();
|
|
147
|
+
declare global {
|
|
148
|
+
interface Window {
|
|
149
|
+
__OXY_APP__?: OxyInjectedAppConfig;
|
|
150
|
+
}
|
|
206
151
|
}
|
|
207
152
|
/**
|
|
208
|
-
*
|
|
153
|
+
* Read the runtime app-config oxy injected at serve time. Returns
|
|
154
|
+
* `undefined` outside the browser or when the global isn't set
|
|
155
|
+
* (`pnpm dev` against a non-oxy server, etc. — manifest hints are
|
|
156
|
+
* the fallback).
|
|
209
157
|
*/
|
|
210
|
-
declare
|
|
211
|
-
|
|
158
|
+
declare function readInjectedAppConfig(): OxyInjectedAppConfig | undefined;
|
|
159
|
+
//#endregion
|
|
160
|
+
//#region src/customer-app/logger.d.ts
|
|
161
|
+
type OxyAppLogLevel = "debug" | "info" | "warn" | "error";
|
|
162
|
+
interface OxyAppLogger {
|
|
163
|
+
log(level: OxyAppLogLevel, msg: string, ctx?: Record<string, unknown>): void;
|
|
212
164
|
}
|
|
165
|
+
/** Replace the global logger. Pass `null` to silence everything. */
|
|
166
|
+
declare function setOxyAppLogger(logger: OxyAppLogger | null): void;
|
|
167
|
+
/** Used by the SDK internals; not part of the public surface. */
|
|
168
|
+
declare function getOxyAppLogger(): OxyAppLogger;
|
|
213
169
|
//#endregion
|
|
214
|
-
//#region src/
|
|
170
|
+
//#region src/customer-app/react.d.ts
|
|
215
171
|
/**
|
|
216
|
-
*
|
|
172
|
+
* Credentialed fetch wrapper stored in context so `useQuery` can share
|
|
173
|
+
* the same request mechanism without coupling it to the global `fetch`.
|
|
174
|
+
*
|
|
175
|
+
* Sends `credentials: "include"` so the session cookie rides along when
|
|
176
|
+
* the app is served by oxy (in-workspace / admin preview) — that cookie
|
|
177
|
+
* authorizes data calls. For local dev (cross-origin), the
|
|
178
|
+
* `@oxy-hq/vite-plugin` proxy attaches the developer's token. Bundles may
|
|
179
|
+
* override the fetcher for test/proxy environments.
|
|
217
180
|
*/
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
181
|
+
type AppFetcher = typeof fetch;
|
|
182
|
+
interface OxyAppProviderProps {
|
|
183
|
+
/** Optional manifest load options. Same shape as `loadCustomerAppManifest`. */
|
|
184
|
+
manifestOptions?: LoadManifestOptions;
|
|
221
185
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* This is the recommended method when using the SDK in an iframe that needs to
|
|
225
|
-
* obtain authentication from the parent window via postMessage.
|
|
226
|
-
*
|
|
227
|
-
* @param config - Optional configuration overrides
|
|
228
|
-
* @returns Promise resolving to OxyClient instance
|
|
229
|
-
* @throws Error if required configuration is missing
|
|
230
|
-
* @throws PostMessageAuthTimeoutError if parent doesn't respond
|
|
231
|
-
*
|
|
232
|
-
* @example
|
|
233
|
-
* ```typescript
|
|
234
|
-
* // In an iframe - automatic postMessage auth
|
|
235
|
-
* const client = await OxyClient.create({
|
|
236
|
-
* parentOrigin: 'https://app.example.com',
|
|
237
|
-
* projectId: 'my-project-id',
|
|
238
|
-
* baseUrl: 'https://api.oxy.tech'
|
|
239
|
-
* });
|
|
240
|
-
*
|
|
241
|
-
* // Use the client normally
|
|
242
|
-
* const apps = await client.listApps();
|
|
243
|
-
* ```
|
|
244
|
-
*/
|
|
245
|
-
static create(config?: Partial<OxyConfig>): Promise<OxyClient>;
|
|
246
|
-
/**
|
|
247
|
-
* Encodes a file path to base64 for use in API URLs.
|
|
248
|
-
* Handles Unicode characters (e.g., emojis) properly in both Node.js and browser.
|
|
249
|
-
*/
|
|
250
|
-
private encodePathBase64;
|
|
251
|
-
/**
|
|
252
|
-
* Makes an authenticated HTTP request to the Oxy API
|
|
253
|
-
*/
|
|
254
|
-
private request;
|
|
255
|
-
/**
|
|
256
|
-
* Builds query parameters including optional branch
|
|
257
|
-
*/
|
|
258
|
-
private buildQueryParams;
|
|
259
|
-
/**
|
|
260
|
-
* Lists all apps in the project
|
|
261
|
-
*
|
|
262
|
-
* @returns Array of app items
|
|
263
|
-
*
|
|
264
|
-
* @example
|
|
265
|
-
* ```typescript
|
|
266
|
-
* const apps = await client.listApps();
|
|
267
|
-
* console.log('Available apps:', apps);
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
listApps(): Promise<AppItem[]>;
|
|
271
|
-
/**
|
|
272
|
-
* Gets data for a specific app
|
|
273
|
-
*
|
|
274
|
-
* @param appPath - Relative path to the app file (e.g., 'my-app.app.yml')
|
|
275
|
-
* @returns App data response
|
|
276
|
-
*
|
|
277
|
-
* @example
|
|
278
|
-
* ```typescript
|
|
279
|
-
* const data = await client.getAppData('dashboard.app.yml');
|
|
280
|
-
* if (data.error) {
|
|
281
|
-
* console.error('Error:', data.error);
|
|
282
|
-
* } else {
|
|
283
|
-
* console.log('App data:', data.data);
|
|
284
|
-
* }
|
|
285
|
-
* ```
|
|
286
|
-
*/
|
|
287
|
-
getAppData(appPath: string): Promise<AppDataResponse>;
|
|
288
|
-
/**
|
|
289
|
-
* Runs an app and returns fresh data (bypasses cache)
|
|
290
|
-
*
|
|
291
|
-
* @param appPath - Relative path to the app file
|
|
292
|
-
* @returns App data response
|
|
293
|
-
*
|
|
294
|
-
* @example
|
|
295
|
-
* ```typescript
|
|
296
|
-
* const data = await client.runApp('dashboard.app.yml');
|
|
297
|
-
* console.log('Fresh app data:', data.data);
|
|
298
|
-
* ```
|
|
186
|
+
* Rendered while the manifest is loading. Defaults to nothing; pass a
|
|
187
|
+
* spinner if you want one.
|
|
299
188
|
*/
|
|
300
|
-
|
|
189
|
+
fallback?: React.ReactNode;
|
|
301
190
|
/**
|
|
302
|
-
*
|
|
303
|
-
*
|
|
304
|
-
*
|
|
305
|
-
* @returns Display configurations with potential errors
|
|
306
|
-
*
|
|
307
|
-
* @example
|
|
308
|
-
* ```typescript
|
|
309
|
-
* const displays = await client.getDisplays('dashboard.app.yml');
|
|
310
|
-
* displays.displays.forEach(d => {
|
|
311
|
-
* if (d.error) {
|
|
312
|
-
* console.error('Display error:', d.error);
|
|
313
|
-
* } else {
|
|
314
|
-
* console.log('Display:', d.display);
|
|
315
|
-
* }
|
|
316
|
-
* });
|
|
317
|
-
* ```
|
|
318
|
-
*/
|
|
319
|
-
getDisplays(appPath: string): Promise<GetDisplaysResponse>;
|
|
320
|
-
/**
|
|
321
|
-
* Gets a file from the app state directory (e.g., generated charts, images)
|
|
322
|
-
*
|
|
323
|
-
* This is useful for retrieving generated assets like charts, images, or other
|
|
324
|
-
* files produced by app workflows and stored in the state directory.
|
|
325
|
-
*
|
|
326
|
-
* @param filePath - Relative path to the file in state directory
|
|
327
|
-
* @returns Blob containing the file data
|
|
328
|
-
*
|
|
329
|
-
* @example
|
|
330
|
-
* ```typescript
|
|
331
|
-
* // Get a generated chart image
|
|
332
|
-
* const blob = await client.getFile('charts/sales-chart.png');
|
|
333
|
-
* const imageUrl = URL.createObjectURL(blob);
|
|
334
|
-
*
|
|
335
|
-
* // Use in an img tag
|
|
336
|
-
* document.querySelector('img').src = imageUrl;
|
|
337
|
-
* ```
|
|
338
|
-
*
|
|
339
|
-
* @example
|
|
340
|
-
* ```typescript
|
|
341
|
-
* // Download a file
|
|
342
|
-
* const blob = await client.getFile('exports/data.csv');
|
|
343
|
-
* const a = document.createElement('a');
|
|
344
|
-
* a.href = URL.createObjectURL(blob);
|
|
345
|
-
* a.download = 'data.csv';
|
|
346
|
-
* a.click();
|
|
347
|
-
* ```
|
|
348
|
-
*/
|
|
349
|
-
getFile(filePath: string): Promise<Blob>;
|
|
350
|
-
/**
|
|
351
|
-
* Gets a file URL for direct browser access
|
|
352
|
-
*
|
|
353
|
-
* This returns a URL that can be used directly in img tags, fetch calls, etc.
|
|
354
|
-
* The URL includes authentication via query parameters.
|
|
355
|
-
*
|
|
356
|
-
* @param filePath - Relative path to the file in state directory
|
|
357
|
-
* @returns Full URL to the file
|
|
358
|
-
*
|
|
359
|
-
* @example
|
|
360
|
-
* ```typescript
|
|
361
|
-
* const imageUrl = client.getFileUrl('charts/sales-chart.png');
|
|
362
|
-
*
|
|
363
|
-
* // Use directly in img tag (in environments where query-based auth is supported)
|
|
364
|
-
* document.querySelector('img').src = imageUrl;
|
|
365
|
-
* ```
|
|
191
|
+
* Rendered on manifest load failure. Receives the structured error
|
|
192
|
+
* report so the bundle can show its own branded error card. Defaults
|
|
193
|
+
* to a minimal text-only fallback (better than a blank page).
|
|
366
194
|
*/
|
|
367
|
-
|
|
195
|
+
errorFallback?: (err: CustomerAppErrorReport) => React.ReactNode;
|
|
368
196
|
/**
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
372
|
-
* @param limit - Maximum number of rows to return (default: 100)
|
|
373
|
-
* @returns TableData with columns and rows
|
|
374
|
-
*
|
|
375
|
-
* @example
|
|
376
|
-
* ```typescript
|
|
377
|
-
* const tableData = await client.getTableData('data/sales.parquet', 50);
|
|
378
|
-
* console.log(tableData.columns);
|
|
379
|
-
* console.log(tableData.rows);
|
|
380
|
-
* console.log(`Total rows: ${tableData.total_rows}`);
|
|
381
|
-
* ```
|
|
197
|
+
* Override the fetch implementation used by all hooks (`useQuery`).
|
|
198
|
+
* Useful for test environments or proxy setups. Defaults to a wrapper
|
|
199
|
+
* that sets `credentials: "include"` on every request.
|
|
382
200
|
*/
|
|
383
|
-
|
|
201
|
+
fetcher?: AppFetcher;
|
|
202
|
+
children: React.ReactNode;
|
|
384
203
|
}
|
|
385
|
-
//#endregion
|
|
386
|
-
//#region src/parquet.d.ts
|
|
387
204
|
/**
|
|
388
|
-
*
|
|
389
|
-
|
|
390
|
-
|
|
205
|
+
* Top-level provider. Loads the manifest once on mount; children only
|
|
206
|
+
* render after the manifest is ready (or the error fallback fires).
|
|
207
|
+
*/
|
|
208
|
+
declare function OxyAppProvider(props: OxyAppProviderProps): React.JSX.Element;
|
|
209
|
+
/**
|
|
210
|
+
* Error thrown by all customer-app hooks when an API call returns a
|
|
211
|
+
* non-2xx response. Carries the structured `code` + `hint` the server
|
|
212
|
+
* emits so bundle UIs can render an actionable message instead of
|
|
213
|
+
* "404: { ...json... }".
|
|
214
|
+
*
|
|
215
|
+
* The server contract is documented in
|
|
216
|
+
* `crates/app/src/server/api/projects/agent_ask.rs` and
|
|
217
|
+
* `procedure_run.rs` — both emit `{ message, code?, hint? }` as JSON.
|
|
218
|
+
* Hooks that previously wrapped the raw text in `new Error()` now
|
|
219
|
+
* throw this type instead.
|
|
220
|
+
*/
|
|
221
|
+
declare class OxyApiError extends Error {
|
|
222
|
+
readonly status: number;
|
|
223
|
+
readonly code: string | null;
|
|
224
|
+
readonly hint: string | null;
|
|
225
|
+
constructor(opts: {
|
|
226
|
+
status: number;
|
|
227
|
+
message: string;
|
|
228
|
+
code?: string | null;
|
|
229
|
+
hint?: string | null;
|
|
230
|
+
});
|
|
231
|
+
}
|
|
391
232
|
/**
|
|
392
|
-
*
|
|
233
|
+
* Read the resolved manifest from context. Throws if called outside
|
|
234
|
+
* `<OxyAppProvider>` — that's a programmer error worth surfacing
|
|
235
|
+
* loudly, not silently swallowing.
|
|
393
236
|
*/
|
|
394
|
-
|
|
237
|
+
declare function useResolvedManifest(): ResolvedCustomerAppManifest;
|
|
238
|
+
interface UseQueryInput {
|
|
239
|
+
sql: string;
|
|
240
|
+
database?: string;
|
|
241
|
+
}
|
|
242
|
+
interface UseQueryOpts {
|
|
243
|
+
params?: Record<string, string | number | boolean | null | undefined>;
|
|
244
|
+
/** Set false to skip the request (e.g., waiting on user input). */
|
|
245
|
+
enabled?: boolean;
|
|
246
|
+
}
|
|
247
|
+
interface UseQueryResult<Row = Record<string, unknown>> {
|
|
248
|
+
rows: Row[];
|
|
395
249
|
columns: string[];
|
|
396
|
-
|
|
397
|
-
|
|
250
|
+
loading: boolean;
|
|
251
|
+
error: Error | null;
|
|
252
|
+
refetch: () => void;
|
|
398
253
|
}
|
|
399
254
|
/**
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
}>): Promise<void>;
|
|
453
|
-
/**
|
|
454
|
-
* Execute a SQL query against the registered Parquet data
|
|
455
|
-
*
|
|
456
|
-
* @param sql - SQL query string
|
|
457
|
-
* @returns Query result with columns and rows
|
|
458
|
-
*
|
|
459
|
-
* @example
|
|
460
|
-
* ```typescript
|
|
461
|
-
* const result = await reader.query('SELECT * FROM sales LIMIT 10');
|
|
462
|
-
* console.log(result.columns);
|
|
463
|
-
* console.log(result.rows);
|
|
464
|
-
* ```
|
|
465
|
-
*
|
|
466
|
-
* @example
|
|
467
|
-
* ```typescript
|
|
468
|
-
* // Query multiple tables
|
|
469
|
-
* await reader.registerParquet(salesBlob, 'sales');
|
|
470
|
-
* await reader.registerParquet(customersBlob, 'customers');
|
|
471
|
-
* const result = await reader.query(`
|
|
472
|
-
* SELECT s.*, c.name
|
|
473
|
-
* FROM sales s
|
|
474
|
-
* JOIN customers c ON s.customer_id = c.id
|
|
475
|
-
* `);
|
|
476
|
-
* ```
|
|
477
|
-
*/
|
|
478
|
-
query(sql: string): Promise<QueryResult>;
|
|
479
|
-
/**
|
|
480
|
-
* Get all data from a registered table
|
|
481
|
-
*
|
|
482
|
-
* @param tableName - Name of the table to query
|
|
483
|
-
* @param limit - Maximum number of rows to return (default: all)
|
|
484
|
-
* @returns Query result
|
|
485
|
-
*
|
|
486
|
-
* @example
|
|
487
|
-
* ```typescript
|
|
488
|
-
* const allData = await reader.getAll('sales');
|
|
489
|
-
* const first100 = await reader.getAll('sales', 100);
|
|
490
|
-
* ```
|
|
491
|
-
*/
|
|
492
|
-
getAll(tableName: string, limit?: number): Promise<QueryResult>;
|
|
493
|
-
/**
|
|
494
|
-
* Get table schema information
|
|
495
|
-
*
|
|
496
|
-
* @param tableName - Name of the table to describe
|
|
497
|
-
* @returns Schema information
|
|
498
|
-
*
|
|
499
|
-
* @example
|
|
500
|
-
* ```typescript
|
|
501
|
-
* const schema = await reader.getSchema('sales');
|
|
502
|
-
* console.log(schema.columns); // ['id', 'name', 'sales']
|
|
503
|
-
* console.log(schema.rows); // [['id', 'INTEGER'], ['name', 'VARCHAR'], ...]
|
|
504
|
-
* ```
|
|
505
|
-
*/
|
|
506
|
-
getSchema(tableName: string): Promise<QueryResult>;
|
|
507
|
-
/**
|
|
508
|
-
* Get row count for a table
|
|
509
|
-
*
|
|
510
|
-
* @param tableName - Name of the table to count
|
|
511
|
-
* @returns Number of rows in the table
|
|
512
|
-
*
|
|
513
|
-
* @example
|
|
514
|
-
* ```typescript
|
|
515
|
-
* const count = await reader.count('sales');
|
|
516
|
-
* console.log(`Total rows: ${count}`);
|
|
517
|
-
* ```
|
|
518
|
-
*/
|
|
519
|
-
count(tableName: string): Promise<number>;
|
|
255
|
+
* Execute an ad-hoc SQL query against the project linked to this
|
|
256
|
+
* customer app. The query is specified inline by the caller; no
|
|
257
|
+
* manifest declaration is involved.
|
|
258
|
+
*
|
|
259
|
+
* Re-runs whenever `input` or enabled `params` change. Use the
|
|
260
|
+
* `enabled` option to defer the first fetch until required data is
|
|
261
|
+
* available (e.g. a user-supplied filter value).
|
|
262
|
+
*/
|
|
263
|
+
declare function useQuery<Row = Record<string, unknown>>(input: UseQueryInput, opts?: UseQueryOpts): UseQueryResult<Row>;
|
|
264
|
+
/** Scalar filter operators (compared against a single value). */
|
|
265
|
+
type SemanticScalarOp = "eq" | "neq" | "lt" | "lte" | "gt" | "gte";
|
|
266
|
+
/** Array filter operators (compared against a list). */
|
|
267
|
+
type SemanticArrayOp = "in" | "not_in";
|
|
268
|
+
/** Date-range filter operators. `from` / `to` accept ISO date strings. */
|
|
269
|
+
type SemanticDateRangeOp = "in_date_range" | "not_in_date_range";
|
|
270
|
+
/**
|
|
271
|
+
* One filter clause. The `field` references a dimension name within
|
|
272
|
+
* the topic; the `op` discriminator picks which other fields are
|
|
273
|
+
* meaningful. Wire shape matches `agentic_semantic::SemanticFilter`
|
|
274
|
+
* verbatim — the bundle's request body is forwarded to airlayer's
|
|
275
|
+
* compiler with no translation.
|
|
276
|
+
*/
|
|
277
|
+
type SemanticFilter = {
|
|
278
|
+
field: string;
|
|
279
|
+
op: SemanticScalarOp;
|
|
280
|
+
value: string | number | boolean | null;
|
|
281
|
+
} | {
|
|
282
|
+
field: string;
|
|
283
|
+
op: SemanticArrayOp;
|
|
284
|
+
values: Array<string | number | boolean | null>;
|
|
285
|
+
} | {
|
|
286
|
+
field: string;
|
|
287
|
+
op: SemanticDateRangeOp;
|
|
288
|
+
from: string;
|
|
289
|
+
to: string;
|
|
290
|
+
};
|
|
291
|
+
/** Time dimensions with optional granularity (e.g. "day", "month"). */
|
|
292
|
+
interface SemanticTimeDimension {
|
|
293
|
+
dimension: string;
|
|
294
|
+
granularity?: "day" | "week" | "month" | "quarter" | "year";
|
|
295
|
+
}
|
|
296
|
+
interface UseSemanticQueryInput {
|
|
297
|
+
topic: string;
|
|
298
|
+
dimensions?: string[];
|
|
299
|
+
measures?: string[];
|
|
300
|
+
time_dimensions?: SemanticTimeDimension[];
|
|
301
|
+
filters?: SemanticFilter[];
|
|
302
|
+
limit?: number;
|
|
303
|
+
}
|
|
304
|
+
interface UseSemanticQueryOpts {
|
|
305
|
+
/** Set false to skip the request (e.g., waiting on user input). */
|
|
306
|
+
enabled?: boolean;
|
|
520
307
|
/**
|
|
521
|
-
*
|
|
308
|
+
* When true, the response includes the compiled SQL string at
|
|
309
|
+
* `sql`. Off by default — production callers shouldn't bake the
|
|
310
|
+
* warehouse SQL into their UI. Bundle authors flip this on while
|
|
311
|
+
* debugging.
|
|
522
312
|
*/
|
|
523
|
-
|
|
313
|
+
debug?: boolean;
|
|
314
|
+
}
|
|
315
|
+
interface UseSemanticQueryResult<Row = Record<string, unknown>> {
|
|
316
|
+
rows: Row[];
|
|
317
|
+
columns: string[];
|
|
318
|
+
/** True when the result was capped at the server's row limit. */
|
|
319
|
+
truncated: boolean;
|
|
320
|
+
/** Compiled SQL — populated only when `opts.debug` is true. */
|
|
321
|
+
sql: string | null;
|
|
322
|
+
loading: boolean;
|
|
323
|
+
error: Error | null;
|
|
324
|
+
refetch: () => void;
|
|
524
325
|
}
|
|
525
326
|
/**
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
* @param sql - SQL query to execute (optional, defaults to SELECT * FROM tableName)
|
|
531
|
-
* @returns Query result
|
|
532
|
-
*
|
|
533
|
-
* @example
|
|
534
|
-
* ```typescript
|
|
535
|
-
* const blob = await client.getFile('data/sales.parquet');
|
|
536
|
-
* const result = await queryParquet(blob, 'sales', 'SELECT product, SUM(amount) as total FROM sales GROUP BY product');
|
|
537
|
-
* console.log(result);
|
|
538
|
-
* ```
|
|
539
|
-
*/
|
|
540
|
-
declare function queryParquet(blob: Blob, tableName?: string, sql?: string): Promise<QueryResult>;
|
|
541
|
-
/**
|
|
542
|
-
* Helper function to read Parquet file and get all data
|
|
543
|
-
*
|
|
544
|
-
* @param blob - Parquet file as Blob
|
|
545
|
-
* @param tableName - Name to use for the table (default: 'data')
|
|
546
|
-
* @param limit - Maximum number of rows (optional)
|
|
547
|
-
* @returns Query result
|
|
548
|
-
*
|
|
549
|
-
* @example
|
|
550
|
-
* ```typescript
|
|
551
|
-
* const blob = await client.getFile('data/sales.parquet');
|
|
552
|
-
* const data = await readParquet(blob, 'sales', 1000);
|
|
553
|
-
* console.log(`Loaded ${data.rowCount} rows`);
|
|
554
|
-
* ```
|
|
555
|
-
*/
|
|
556
|
-
declare function readParquet(blob: Blob, tableName?: string, limit?: number): Promise<QueryResult>;
|
|
557
|
-
//#endregion
|
|
558
|
-
//#region src/sdk.d.ts
|
|
559
|
-
/**
|
|
560
|
-
* OxySDK provides a unified interface for fetching data from Oxy and querying it with SQL.
|
|
561
|
-
* It combines OxyClient (for API calls) and ParquetReader (for SQL queries) into a single,
|
|
562
|
-
* easy-to-use interface.
|
|
563
|
-
*
|
|
564
|
-
* @example
|
|
565
|
-
* ```typescript
|
|
566
|
-
* // Create SDK instance
|
|
567
|
-
* const sdk = new OxySDK({ apiKey: 'your-key', projectId: 'your-project' });
|
|
568
|
-
*
|
|
569
|
-
* // Load a parquet file and query it
|
|
570
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
571
|
-
* const result = await sdk.query('SELECT * FROM sales WHERE amount > 1000');
|
|
572
|
-
* console.log(result.rows);
|
|
327
|
+
* Run a semantic-layer query against the project's `.view.yml` /
|
|
328
|
+
* `.topic.yml` definitions. The server compiles to SQL and executes
|
|
329
|
+
* through the same connector path as `useQuery`, so result shape
|
|
330
|
+
* matches.
|
|
573
331
|
*
|
|
574
|
-
*
|
|
575
|
-
*
|
|
576
|
-
*
|
|
332
|
+
* Re-runs whenever the input shape changes (deep-compared via JSON).
|
|
333
|
+
* Use `opts.enabled = false` to defer the first fetch until required
|
|
334
|
+
* inputs (e.g. a user-picked filter value) are available.
|
|
577
335
|
*/
|
|
578
|
-
declare
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
/**
|
|
583
|
-
* Creates an OxySDK instance asynchronously with support for postMessage authentication
|
|
584
|
-
*
|
|
585
|
-
* @param config - Optional configuration overrides
|
|
586
|
-
* @returns Promise resolving to OxySDK instance
|
|
587
|
-
*
|
|
588
|
-
* @example
|
|
589
|
-
* ```typescript
|
|
590
|
-
* // In an iframe - automatic postMessage auth
|
|
591
|
-
* const sdk = await OxySDK.create({
|
|
592
|
-
* parentOrigin: 'https://app.example.com',
|
|
593
|
-
* projectId: 'my-project-id'
|
|
594
|
-
* });
|
|
595
|
-
* ```
|
|
596
|
-
*/
|
|
597
|
-
static create(config?: Partial<OxyConfig>): Promise<OxySDK>;
|
|
598
|
-
/**
|
|
599
|
-
* Load a Parquet file from Oxy and register it for SQL queries
|
|
600
|
-
*
|
|
601
|
-
* @param filePath - Path to the parquet file in the app state directory
|
|
602
|
-
* @param tableName - Name to use for the table in SQL queries
|
|
603
|
-
*
|
|
604
|
-
* @example
|
|
605
|
-
* ```typescript
|
|
606
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
607
|
-
* await sdk.loadFile('data/customers.parquet', 'customers');
|
|
608
|
-
*
|
|
609
|
-
* const result = await sdk.query(`
|
|
610
|
-
* SELECT s.*, c.name
|
|
611
|
-
* FROM sales s
|
|
612
|
-
* JOIN customers c ON s.customer_id = c.id
|
|
613
|
-
* `);
|
|
614
|
-
* ```
|
|
615
|
-
*/
|
|
616
|
-
loadFile(filePath: string, tableName: string): Promise<void>;
|
|
617
|
-
/**
|
|
618
|
-
* Load multiple Parquet files at once
|
|
619
|
-
*
|
|
620
|
-
* @param files - Array of file paths and table names
|
|
621
|
-
*
|
|
622
|
-
* @example
|
|
623
|
-
* ```typescript
|
|
624
|
-
* await sdk.loadFiles([
|
|
625
|
-
* { filePath: 'data/sales.parquet', tableName: 'sales' },
|
|
626
|
-
* { filePath: 'data/customers.parquet', tableName: 'customers' },
|
|
627
|
-
* { filePath: 'data/products.parquet', tableName: 'products' }
|
|
628
|
-
* ]);
|
|
629
|
-
*
|
|
630
|
-
* const result = await sdk.query('SELECT * FROM sales');
|
|
631
|
-
* ```
|
|
632
|
-
*/
|
|
633
|
-
loadFiles(files: Array<{
|
|
634
|
-
filePath: string;
|
|
635
|
-
tableName: string;
|
|
636
|
-
}>): Promise<void>;
|
|
637
|
-
/**
|
|
638
|
-
* Load all data from an app's data container
|
|
639
|
-
*
|
|
640
|
-
* This fetches the app's data and registers all parquet files using their container keys as table names.
|
|
641
|
-
*
|
|
642
|
-
* @param appPath - Path to the app file
|
|
643
|
-
* @returns DataContainer with file references
|
|
644
|
-
*
|
|
645
|
-
* @example
|
|
646
|
-
* ```typescript
|
|
647
|
-
* // If app has data: { sales: { file_path: 'data/sales.parquet' } }
|
|
648
|
-
* const data = await sdk.loadAppData('dashboard.app.yml');
|
|
649
|
-
* // Now you can query the 'sales' table
|
|
650
|
-
* const result = await sdk.query('SELECT * FROM sales LIMIT 10');
|
|
651
|
-
* ```
|
|
652
|
-
*/
|
|
653
|
-
loadAppData(appPath: string): Promise<DataContainer | null>;
|
|
654
|
-
/**
|
|
655
|
-
* Execute a SQL query against loaded data
|
|
656
|
-
*
|
|
657
|
-
* @param sql - SQL query to execute
|
|
658
|
-
* @returns Query result with columns and rows
|
|
659
|
-
*
|
|
660
|
-
* @example
|
|
661
|
-
* ```typescript
|
|
662
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
663
|
-
*
|
|
664
|
-
* const result = await sdk.query('SELECT product, SUM(amount) as total FROM sales GROUP BY product');
|
|
665
|
-
* console.log(result.columns); // ['product', 'total']
|
|
666
|
-
* console.log(result.rows); // [['Product A', 1000], ['Product B', 2000]]
|
|
667
|
-
* console.log(result.rowCount); // 2
|
|
668
|
-
* ```
|
|
669
|
-
*/
|
|
670
|
-
query(sql: string): Promise<QueryResult>;
|
|
671
|
-
/**
|
|
672
|
-
* Get all data from a loaded table
|
|
673
|
-
*
|
|
674
|
-
* @param tableName - Name of the table
|
|
675
|
-
* @param limit - Maximum number of rows (optional)
|
|
676
|
-
* @returns Query result
|
|
677
|
-
*
|
|
678
|
-
* @example
|
|
679
|
-
* ```typescript
|
|
680
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
681
|
-
* const allData = await sdk.getAll('sales');
|
|
682
|
-
* const first100 = await sdk.getAll('sales', 100);
|
|
683
|
-
* ```
|
|
684
|
-
*/
|
|
685
|
-
getAll(tableName: string, limit?: number): Promise<QueryResult>;
|
|
686
|
-
/**
|
|
687
|
-
* Get schema information for a loaded table
|
|
688
|
-
*
|
|
689
|
-
* @param tableName - Name of the table
|
|
690
|
-
* @returns Schema information
|
|
691
|
-
*
|
|
692
|
-
* @example
|
|
693
|
-
* ```typescript
|
|
694
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
695
|
-
* const schema = await sdk.getSchema('sales');
|
|
696
|
-
* console.log(schema.columns); // ['column_name', 'column_type', ...]
|
|
697
|
-
* console.log(schema.rows); // [['id', 'INTEGER'], ['name', 'VARCHAR'], ...]
|
|
698
|
-
* ```
|
|
699
|
-
*/
|
|
700
|
-
getSchema(tableName: string): Promise<QueryResult>;
|
|
701
|
-
/**
|
|
702
|
-
* Get row count for a loaded table
|
|
703
|
-
*
|
|
704
|
-
* @param tableName - Name of the table
|
|
705
|
-
* @returns Number of rows
|
|
706
|
-
*
|
|
707
|
-
* @example
|
|
708
|
-
* ```typescript
|
|
709
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
710
|
-
* const count = await sdk.count('sales');
|
|
711
|
-
* console.log(`Total rows: ${count}`);
|
|
712
|
-
* ```
|
|
713
|
-
*/
|
|
714
|
-
count(tableName: string): Promise<number>;
|
|
715
|
-
/**
|
|
716
|
-
* Get direct access to the underlying OxyClient
|
|
717
|
-
*
|
|
718
|
-
* Useful for advanced operations like listing apps, getting displays, etc.
|
|
719
|
-
*
|
|
720
|
-
* @returns The OxyClient instance
|
|
721
|
-
*
|
|
722
|
-
* @example
|
|
723
|
-
* ```typescript
|
|
724
|
-
* const apps = await sdk.getClient().listApps();
|
|
725
|
-
* const displays = await sdk.getClient().getDisplays('my-app.app.yml');
|
|
726
|
-
* ```
|
|
727
|
-
*/
|
|
728
|
-
getClient(): OxyClient;
|
|
729
|
-
/**
|
|
730
|
-
* Get direct access to the underlying ParquetReader
|
|
731
|
-
*
|
|
732
|
-
* Useful for advanced operations like registering blobs directly.
|
|
733
|
-
*
|
|
734
|
-
* @returns The ParquetReader instance
|
|
735
|
-
*
|
|
736
|
-
* @example
|
|
737
|
-
* ```typescript
|
|
738
|
-
* const myBlob = new Blob([parquetData]);
|
|
739
|
-
* await sdk.getReader().registerParquet(myBlob, 'mydata');
|
|
740
|
-
* ```
|
|
741
|
-
*/
|
|
742
|
-
getReader(): ParquetReader;
|
|
743
|
-
/**
|
|
744
|
-
* Close and cleanup all resources
|
|
745
|
-
*
|
|
746
|
-
* This clears all loaded data and releases resources. Call this when you're done with the SDK.
|
|
747
|
-
*
|
|
748
|
-
* @example
|
|
749
|
-
* ```typescript
|
|
750
|
-
* const sdk = new OxySDK({ apiKey: 'key', projectId: 'project' });
|
|
751
|
-
* await sdk.loadFile('data/sales.parquet', 'sales');
|
|
752
|
-
* const result = await sdk.query('SELECT * FROM sales');
|
|
753
|
-
* await sdk.close(); // Clean up
|
|
754
|
-
* ```
|
|
755
|
-
*/
|
|
756
|
-
close(): Promise<void>;
|
|
336
|
+
declare function useSemanticQuery<Row = Record<string, unknown>>(input: UseSemanticQueryInput, opts?: UseSemanticQueryOpts): UseSemanticQueryResult<Row>;
|
|
337
|
+
type ProcedureRunState = "idle" | "running" | "done" | "failed";
|
|
338
|
+
interface UseProcedureRunInput {
|
|
339
|
+
procedureId: string;
|
|
757
340
|
}
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
341
|
+
interface UseProcedureRunOpts {
|
|
342
|
+
/** Polling cadence in ms while running. Default: 2000 (procedures
|
|
343
|
+
* are typically minutes-long; tighter cadence wastes resources). */
|
|
344
|
+
pollIntervalMs?: number;
|
|
345
|
+
pollIntervalBackoffMs?: number;
|
|
346
|
+
/** Max client-side wait in ms. Default: 1 hour. */
|
|
347
|
+
maxWaitMs?: number;
|
|
348
|
+
}
|
|
349
|
+
interface ProcedureProgress {
|
|
350
|
+
step: string;
|
|
351
|
+
percent: number;
|
|
352
|
+
}
|
|
353
|
+
interface ProcedureResult {
|
|
354
|
+
summary: string;
|
|
355
|
+
outputs: Record<string, unknown>;
|
|
356
|
+
}
|
|
357
|
+
interface UseProcedureRunResult {
|
|
358
|
+
state: ProcedureRunState;
|
|
359
|
+
run: (params?: Record<string, unknown>) => void;
|
|
360
|
+
/** Cancel the in-flight run. Idempotent. */
|
|
361
|
+
cancel: () => void;
|
|
362
|
+
progress: ProcedureProgress | null;
|
|
363
|
+
result: ProcedureResult | null;
|
|
766
364
|
error: Error | null;
|
|
767
365
|
}
|
|
768
366
|
/**
|
|
769
|
-
*
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
*/
|
|
803
|
-
|
|
367
|
+
* @beta Long-running procedure runner. The wire shape works end-to-end
|
|
368
|
+
* (start → poll → cancel; runs survive server restarts via the
|
|
369
|
+
* `customer_app_procedure_runs` table) but a few rough edges remain
|
|
370
|
+
* before this is GA-ready:
|
|
371
|
+
*
|
|
372
|
+
* - Hint surfaces for `procedure_not_found` are correct but the
|
|
373
|
+
* procedure-discovery rules (which directories the server scans,
|
|
374
|
+
* case-sensitivity, branch awareness) aren't documented yet.
|
|
375
|
+
* - Cancellation across multi-instance deployments leans on a
|
|
376
|
+
* periodic sweep — fine for now, but expect occasional latency
|
|
377
|
+
* between `cancel()` and the run actually stopping.
|
|
378
|
+
* - Progress reporting requires the procedure to emit named
|
|
379
|
+
* steps; bundles get `progress: null` until that lands.
|
|
380
|
+
*
|
|
381
|
+
* The API surface is stable; expect breaking changes only if the
|
|
382
|
+
* server-side `customer_app_procedure_runs` schema changes.
|
|
383
|
+
*/
|
|
384
|
+
declare function useProcedureRun(input: UseProcedureRunInput, opts?: UseProcedureRunOpts): UseProcedureRunResult;
|
|
385
|
+
type AgentRunState = "idle" | "running" | "needs_clarification" | "done" | "failed";
|
|
386
|
+
interface AgentRunEvent {
|
|
387
|
+
type: string;
|
|
388
|
+
data: unknown;
|
|
389
|
+
}
|
|
390
|
+
/** SQL produced and (optionally) executed by the agent. Extracted
|
|
391
|
+
* from `query_generated` / `query_executed` / `verified_sql` /
|
|
392
|
+
* `semantic_query` / `omni_query` SSE events so callers don't have
|
|
393
|
+
* to scan the raw event stream themselves. */
|
|
394
|
+
interface AgentSqlArtifact {
|
|
395
|
+
type: "sql";
|
|
396
|
+
/** Stable id derived from the SSE event id so React keys stay
|
|
397
|
+
* stable across re-renders / reconnects. */
|
|
398
|
+
id: string;
|
|
399
|
+
/** Originating UI event type — preserves the verified/semantic/etc.
|
|
400
|
+
* flavor in case the renderer wants a badge. */
|
|
401
|
+
source: string;
|
|
402
|
+
sql: string;
|
|
403
|
+
/** Present when the SQL was executed and rows came back. */
|
|
404
|
+
results?: {
|
|
405
|
+
columns: string[];
|
|
406
|
+
rows: unknown[][];
|
|
407
|
+
rowCount: number;
|
|
408
|
+
};
|
|
409
|
+
/** Present when execution failed — surface it so the bundle UI can
|
|
410
|
+
* show the failure inline next to the SQL instead of swallowing
|
|
411
|
+
* it inside the agent's final answer. */
|
|
412
|
+
error?: string;
|
|
413
|
+
}
|
|
414
|
+
type AgentArtifact = AgentSqlArtifact;
|
|
415
|
+
interface UseAgentRunInput {
|
|
416
|
+
agentId: string;
|
|
417
|
+
}
|
|
418
|
+
interface UseAgentRunResult {
|
|
419
|
+
state: AgentRunState;
|
|
420
|
+
/** Submit a question and open the SSE stream. */
|
|
421
|
+
ask: (question: string, opts?: {
|
|
422
|
+
threadId?: string;
|
|
423
|
+
}) => void;
|
|
424
|
+
/** Cancel the in-flight stream + the server-side run. Idempotent. */
|
|
425
|
+
cancel: () => void;
|
|
426
|
+
/** Accumulated raw events for advanced consumers. */
|
|
427
|
+
events: AgentRunEvent[];
|
|
428
|
+
/** SQL artifacts extracted from the event stream — convenience
|
|
429
|
+
* view over `events` so renderers don't have to know which event
|
|
430
|
+
* types carry SQL. */
|
|
431
|
+
artifacts: AgentArtifact[];
|
|
432
|
+
/** Final answer once a `done` event arrives. Markdown. */
|
|
433
|
+
answer: string | null;
|
|
434
|
+
/** Clarification text once a suspension event arrives. */
|
|
435
|
+
clarification: string | null;
|
|
436
|
+
/** Thread id used by the active run (stable across follow-ups). */
|
|
437
|
+
threadId: string | null;
|
|
438
|
+
/**
|
|
439
|
+
* @beta Relative path to the full thread view in oxy (e.g.
|
|
440
|
+
* `/threads/<id>` for local mode, or
|
|
441
|
+
* `/<org_slug>/workspaces/<ws_id>/threads/<id>` in cloud). Set
|
|
442
|
+
* once the run starts so a bundle can render a "Continue in Oxy"
|
|
443
|
+
* link without constructing the URL itself.
|
|
444
|
+
*
|
|
445
|
+
* Caveats while in beta:
|
|
446
|
+
* - The bundle's origin and the oxy app shell's origin can
|
|
447
|
+
* differ in cloud deployments. If they do, this relative URL
|
|
448
|
+
* resolves against the bundle's origin and 404s. A future
|
|
449
|
+
* release will expose the oxy app origin via the manifest;
|
|
450
|
+
* for now, prefix at the call site if you know your
|
|
451
|
+
* deployment topology, or hide the link entirely.
|
|
452
|
+
* - The thread row may not be queryable until the run produces
|
|
453
|
+
* its first event — clicking the link immediately after
|
|
454
|
+
* `ask()` can land on a "thread not found" page.
|
|
455
|
+
*/
|
|
456
|
+
threadUrl: string | null;
|
|
457
|
+
error: Error | null;
|
|
458
|
+
}
|
|
459
|
+
declare function useAgentRun(input: UseAgentRunInput): UseAgentRunResult;
|
|
460
|
+
interface OxyAnswerProps {
|
|
461
|
+
/** Markdown answer text from `useAgentRun().answer`. */
|
|
462
|
+
answer: string | null;
|
|
463
|
+
/** SQL artifacts from `useAgentRun().artifacts`. */
|
|
464
|
+
artifacts?: AgentArtifact[];
|
|
465
|
+
/** Lifecycle state — drives the placeholder, spinner, error UI. */
|
|
466
|
+
state: AgentRunState;
|
|
467
|
+
/** Clarification text when `state === "needs_clarification"`. */
|
|
468
|
+
clarification?: string | null;
|
|
469
|
+
/** Failure reason when `state === "failed"`. */
|
|
470
|
+
error?: Error | null;
|
|
471
|
+
/**
|
|
472
|
+
* @beta Relative URL to the thread view in oxy — renders a
|
|
473
|
+
* "Continue in Oxy (beta)" link when set. Pass `null` to suppress
|
|
474
|
+
* the link entirely; the link is marked beta because the resolved
|
|
475
|
+
* URL may not reach a live thread in every deployment topology
|
|
476
|
+
* (see `UseAgentRunResult.threadUrl`).
|
|
477
|
+
*/
|
|
478
|
+
threadUrl?: string | null;
|
|
479
|
+
/** Override the link label. Default: "Continue this thread in Oxy". */
|
|
480
|
+
threadLinkLabel?: string;
|
|
481
|
+
/** Maximum number of SQL result rows to render per artifact. Older
|
|
482
|
+
* rows truncated with a "+N more" note. Default: 10. */
|
|
483
|
+
maxArtifactRows?: number;
|
|
484
|
+
/** Class on the outer container — for callers using utility CSS. */
|
|
485
|
+
className?: string;
|
|
804
486
|
}
|
|
805
487
|
/**
|
|
806
|
-
*
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
* ```tsx
|
|
810
|
-
* // Synchronous initialization with config
|
|
811
|
-
* function App() {
|
|
812
|
-
* return (
|
|
813
|
-
* <OxyProvider config={{
|
|
814
|
-
* apiKey: 'your-key',
|
|
815
|
-
* projectId: 'your-project',
|
|
816
|
-
* baseUrl: 'https://api.oxy.tech'
|
|
817
|
-
* }}>
|
|
818
|
-
* <Dashboard />
|
|
819
|
-
* </OxyProvider>
|
|
820
|
-
* );
|
|
821
|
-
* }
|
|
822
|
-
* ```
|
|
823
|
-
*
|
|
824
|
-
* @example
|
|
825
|
-
* ```tsx
|
|
826
|
-
* // Async initialization (for iframe/postMessage auth)
|
|
827
|
-
* function App() {
|
|
828
|
-
* return (
|
|
829
|
-
* <OxyProvider
|
|
830
|
-
* useAsync
|
|
831
|
-
* config={{ parentOrigin: 'https://app.example.com' }}
|
|
832
|
-
* >
|
|
833
|
-
* <Dashboard />
|
|
834
|
-
* </OxyProvider>
|
|
835
|
-
* );
|
|
836
|
-
* }
|
|
837
|
-
* ```
|
|
838
|
-
*
|
|
839
|
-
* @example
|
|
840
|
-
* ```tsx
|
|
841
|
-
* // With environment variables
|
|
842
|
-
* import { createConfig } from '@oxy/sdk';
|
|
843
|
-
*
|
|
844
|
-
* function App() {
|
|
845
|
-
* return (
|
|
846
|
-
* <OxyProvider config={createConfig()}>
|
|
847
|
-
* <Dashboard />
|
|
848
|
-
* </OxyProvider>
|
|
849
|
-
* );
|
|
850
|
-
* }
|
|
851
|
-
* ```
|
|
852
|
-
*
|
|
853
|
-
* @example
|
|
854
|
-
* ```tsx
|
|
855
|
-
* // With loading and error slots
|
|
856
|
-
* function App() {
|
|
857
|
-
* return (
|
|
858
|
-
* <OxyProvider
|
|
859
|
-
* config={createConfig()}
|
|
860
|
-
* loadingFallback={<div>Loading SDK...</div>}
|
|
861
|
-
* errorFallback={(error) => <div>Error: {error.message}</div>}
|
|
862
|
-
* >
|
|
863
|
-
* <Dashboard />
|
|
864
|
-
* </OxyProvider>
|
|
865
|
-
* );
|
|
866
|
-
* }
|
|
867
|
-
* ```
|
|
868
|
-
*/
|
|
869
|
-
declare function OxyProvider({
|
|
870
|
-
children,
|
|
871
|
-
config,
|
|
872
|
-
useAsync,
|
|
873
|
-
appPath,
|
|
874
|
-
files,
|
|
875
|
-
onReady,
|
|
876
|
-
onError,
|
|
877
|
-
loadingFallback,
|
|
878
|
-
errorFallback
|
|
879
|
-
}: OxyProviderProps): React.JSX.Element;
|
|
880
|
-
/**
|
|
881
|
-
* Hook to access OxySDK from child components
|
|
882
|
-
*
|
|
883
|
-
* @throws {Error} If used outside of OxyProvider
|
|
884
|
-
* @returns {OxyContextValue} The SDK instance, loading state, and error
|
|
885
|
-
*
|
|
886
|
-
* @example
|
|
887
|
-
* ```tsx
|
|
888
|
-
* function Dashboard() {
|
|
889
|
-
* const { sdk, isLoading, error } = useOxy();
|
|
890
|
-
*
|
|
891
|
-
* useEffect(() => {
|
|
892
|
-
* if (sdk) {
|
|
893
|
-
* sdk.loadAppData('dashboard.app.yml')
|
|
894
|
-
* .then(() => sdk.query('SELECT * FROM my_table'))
|
|
895
|
-
* .then(result => console.log(result));
|
|
896
|
-
* }
|
|
897
|
-
* }, [sdk]);
|
|
898
|
-
*
|
|
899
|
-
* if (isLoading) return <div>Loading SDK...</div>;
|
|
900
|
-
* if (error) return <div>Error: {error.message}</div>;
|
|
901
|
-
* if (!sdk) return null;
|
|
902
|
-
*
|
|
903
|
-
* return <div>Dashboard</div>;
|
|
904
|
-
* }
|
|
905
|
-
* ```
|
|
906
|
-
*/
|
|
907
|
-
declare function useOxy(): OxyContextValue;
|
|
908
|
-
/**
|
|
909
|
-
* Hook to access OxySDK that throws if not ready
|
|
910
|
-
*
|
|
911
|
-
* This is a convenience hook that returns the SDK directly or throws an error if not initialized.
|
|
912
|
-
* Use this when you know the SDK should be ready.
|
|
488
|
+
* Renders an agent run's answer + artifacts + thread link as a
|
|
489
|
+
* single block. The default styling is intentionally neutral
|
|
490
|
+
* (system fonts, gray surfaces) so it blends into any bundle.
|
|
913
491
|
*
|
|
914
|
-
*
|
|
915
|
-
* @returns {OxySDK} The SDK instance
|
|
492
|
+
* Designed to be paired with `useAgentRun`:
|
|
916
493
|
*
|
|
917
|
-
* @example
|
|
918
494
|
* ```tsx
|
|
919
|
-
*
|
|
920
|
-
*
|
|
921
|
-
*
|
|
922
|
-
*
|
|
923
|
-
*
|
|
924
|
-
*
|
|
925
|
-
*
|
|
926
|
-
* .then(setData);
|
|
927
|
-
* }, [sdk]);
|
|
928
|
-
*
|
|
929
|
-
* return <table>...</table>;
|
|
930
|
-
* }
|
|
495
|
+
* const run = useAgentRun({ agentId: "analyst" });
|
|
496
|
+
* return (
|
|
497
|
+
* <>
|
|
498
|
+
* <button onClick={() => run.ask("how many users last week?")}>Ask</button>
|
|
499
|
+
* <OxyAnswer {...run} />
|
|
500
|
+
* </>
|
|
501
|
+
* );
|
|
931
502
|
* ```
|
|
932
503
|
*/
|
|
933
|
-
declare function
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
504
|
+
declare function OxyAnswer(props: OxyAnswerProps): React.JSX.Element;
|
|
505
|
+
interface OxyChatProps {
|
|
506
|
+
/** Agent id (matches `<id>.agentic.yml` in the project). */
|
|
507
|
+
agentId: string;
|
|
508
|
+
/** Placeholder for the question input. */
|
|
509
|
+
placeholder?: string;
|
|
510
|
+
/** Button label. Default: "Ask". */
|
|
511
|
+
submitLabel?: string;
|
|
512
|
+
/** Rendered when the user hasn't asked anything yet. */
|
|
513
|
+
emptyState?: React.ReactNode;
|
|
514
|
+
/** Forwarded to the inner `<OxyAnswer>`. */
|
|
515
|
+
maxArtifactRows?: number;
|
|
516
|
+
/** Class on the outer container. */
|
|
517
|
+
className?: string;
|
|
518
|
+
}
|
|
942
519
|
/**
|
|
943
|
-
*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
520
|
+
* Complete drop-in chat surface. One agent, one input, one answer
|
|
521
|
+
* view. The chat is single-turn by default — each new question
|
|
522
|
+
* cancels the previous run and clears the answer. Bundles that
|
|
523
|
+
* want a multi-turn conversation history compose their own UI
|
|
524
|
+
* using `useAgentRun` directly.
|
|
947
525
|
*
|
|
948
|
-
*
|
|
949
|
-
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
* @throws {PostMessageAuthInvalidOriginError} If response from wrong origin
|
|
953
|
-
* @throws {PostMessageAuthInvalidResponseError} If response is malformed
|
|
954
|
-
*
|
|
955
|
-
* @example
|
|
956
|
-
* ```typescript
|
|
957
|
-
* const auth = await requestAuthFromParent({
|
|
958
|
-
* parentOrigin: 'https://app.example.com',
|
|
959
|
-
* timeout: 5000
|
|
960
|
-
* });
|
|
961
|
-
* console.log('Received API key:', auth.apiKey);
|
|
962
|
-
* ```
|
|
526
|
+
* Single-turn keeps the surface dead simple: bundles use this for
|
|
527
|
+
* the "ask anything about your data" widget that sits next to
|
|
528
|
+
* structured panels. Multi-turn is rare in those contexts and
|
|
529
|
+
* better expressed by the bundle.
|
|
963
530
|
*/
|
|
964
|
-
declare function
|
|
531
|
+
declare function OxyChat(props: OxyChatProps): React.JSX.Element;
|
|
965
532
|
//#endregion
|
|
966
|
-
export { type
|
|
533
|
+
export { type AgentArtifact, type AgentRunEvent, type AgentRunState, type AgentSqlArtifact, type AppFetcher, type CustomerAppDebugSnapshot, type CustomerAppErrorReport, type LoadManifestOptions, OxyAnswer, type OxyAnswerProps, OxyApiError, type OxyAppLogLevel, type OxyAppLogger, type OxyAppManifest, OxyAppProvider, type OxyAppProviderProps, OxyChat, type OxyChatProps, type OxyInjectedAppConfig, type ProcedureProgress, type ProcedureResult, type ProcedureRunState, type ResolvedCustomerAppManifest, type SemanticArrayOp, type SemanticDateRangeOp, type SemanticFilter, type SemanticScalarOp, type SemanticTimeDimension, type UseAgentRunInput, type UseAgentRunResult, type UseProcedureRunInput, type UseProcedureRunOpts, type UseProcedureRunResult, type UseQueryInput, type UseQueryOpts, type UseQueryResult, type UseSemanticQueryInput, type UseSemanticQueryOpts, type UseSemanticQueryResult, _resetCustomerAppManifestCacheForTest, getCustomerAppDebug, getOxyAppLogger, interpretCustomerAppError, loadCustomerAppManifest, readInjectedAppConfig, setOxyAppLogger, useAgentRun, useProcedureRun, useQuery, useResolvedManifest, useSemanticQuery };
|
|
967
534
|
//# sourceMappingURL=index.d.cts.map
|