@oxy-hq/sdk 0.1.6 → 0.2.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 +281 -171
- package/dist/index.cjs +523 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +416 -33
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +416 -33
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +519 -58
- package/dist/index.mjs.map +1 -1
- package/dist/postMessage-B1J0jDRN.cjs.map +1 -1
- package/dist/postMessage-BxdgtX8j.mjs.map +1 -1
- package/package.json +11 -6
package/README.md
CHANGED
|
@@ -28,281 +28,397 @@ npm install @duckdb/duckdb-wasm
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
-
###
|
|
31
|
+
### Basic Usage
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
```typescript
|
|
34
|
+
import { OxySDK } from "@oxy/sdk";
|
|
35
|
+
|
|
36
|
+
// Create SDK instance
|
|
37
|
+
const sdk = new OxySDK({
|
|
38
|
+
apiKey: "your-api-key",
|
|
39
|
+
projectId: "your-project-id",
|
|
40
|
+
baseUrl: "https://api.oxy.tech"
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Load parquet files and query them
|
|
44
|
+
await sdk.loadFile('data/sales.parquet', 'sales');
|
|
45
|
+
await sdk.loadFile('data/customers.parquet', 'customers');
|
|
46
|
+
|
|
47
|
+
// Query with SQL - supports joins across multiple tables
|
|
48
|
+
const result = await sdk.query(`
|
|
49
|
+
SELECT s.product, s.amount, c.name as customer_name
|
|
50
|
+
FROM sales s
|
|
51
|
+
JOIN customers c ON s.customer_id = c.id
|
|
52
|
+
WHERE s.amount > 1000
|
|
53
|
+
ORDER BY s.amount DESC
|
|
54
|
+
`);
|
|
55
|
+
|
|
56
|
+
console.log(result.rows);
|
|
57
|
+
await sdk.close();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Load App Data Automatically
|
|
34
61
|
|
|
35
62
|
```typescript
|
|
36
|
-
import {
|
|
63
|
+
import { OxySDK, createConfig } from "@oxy/sdk";
|
|
64
|
+
|
|
65
|
+
const sdk = new OxySDK(createConfig());
|
|
66
|
+
|
|
67
|
+
// Loads all data from the app and registers tables
|
|
68
|
+
await sdk.loadAppData('dashboard.app.yml');
|
|
69
|
+
|
|
70
|
+
// Query the loaded tables
|
|
71
|
+
const result = await sdk.query('SELECT * FROM my_table LIMIT 10');
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Iframe Usage (PostMessage Authentication)
|
|
75
|
+
|
|
76
|
+
For embedding in iframes (e.g., v0.dev, sandboxed environments):
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
import { OxySDK } from "@oxy/sdk";
|
|
37
80
|
|
|
38
81
|
// SDK automatically requests API key from parent window
|
|
39
|
-
const
|
|
40
|
-
parentOrigin: "https://app.example.com",
|
|
41
|
-
projectId: "your-project-uuid"
|
|
42
|
-
baseUrl: "https://api.oxy.tech",
|
|
82
|
+
const sdk = await OxySDK.create({
|
|
83
|
+
parentOrigin: "https://app.example.com",
|
|
84
|
+
projectId: "your-project-uuid"
|
|
43
85
|
});
|
|
44
86
|
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
console.log("Available apps:", apps);
|
|
87
|
+
await sdk.loadAppData('dashboard.app.yml');
|
|
88
|
+
const result = await sdk.query('SELECT * FROM my_table LIMIT 10');
|
|
48
89
|
```
|
|
49
90
|
|
|
50
|
-
**Parent window setup
|
|
91
|
+
**Parent window setup:**
|
|
51
92
|
|
|
52
93
|
```typescript
|
|
53
|
-
// In parent window that hosts the iframe
|
|
54
94
|
window.addEventListener("message", (event) => {
|
|
55
95
|
if (event.data.type !== "OXY_AUTH_REQUEST") return;
|
|
56
|
-
|
|
57
|
-
// Validate iframe origin
|
|
58
96
|
if (event.origin !== "https://your-iframe-app.com") return;
|
|
59
97
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
baseUrl: "https://api.oxy.tech",
|
|
69
|
-
},
|
|
70
|
-
event.origin,
|
|
71
|
-
);
|
|
98
|
+
event.source.postMessage({
|
|
99
|
+
type: "OXY_AUTH_RESPONSE",
|
|
100
|
+
version: "1.0",
|
|
101
|
+
requestId: event.data.requestId,
|
|
102
|
+
apiKey: getUserApiKey(),
|
|
103
|
+
projectId: "your-project-uuid",
|
|
104
|
+
baseUrl: "https://api.oxy.tech"
|
|
105
|
+
}, event.origin);
|
|
72
106
|
});
|
|
73
107
|
```
|
|
74
108
|
|
|
75
|
-
###
|
|
76
|
-
|
|
77
|
-
Set up environment variables:
|
|
109
|
+
### Environment Variables
|
|
78
110
|
|
|
79
111
|
```bash
|
|
80
|
-
export OXY_URL="https://api.oxy.tech"
|
|
112
|
+
export OXY_URL="https://api.oxy.tech"
|
|
81
113
|
export OXY_API_KEY="your-api-key"
|
|
82
114
|
export OXY_PROJECT_ID="your-project-uuid"
|
|
83
115
|
export OXY_BRANCH="main" # optional
|
|
84
116
|
```
|
|
85
117
|
|
|
86
|
-
|
|
118
|
+
Use `createConfig()` to load from environment:
|
|
87
119
|
|
|
88
120
|
```typescript
|
|
89
|
-
import {
|
|
90
|
-
|
|
91
|
-
// Create configuration from environment variables
|
|
92
|
-
const config = createConfig();
|
|
93
|
-
|
|
94
|
-
// Initialize the client
|
|
95
|
-
const client = new OxyClient(config);
|
|
121
|
+
import { OxySDK, createConfig } from "@oxy/sdk";
|
|
96
122
|
|
|
97
|
-
|
|
98
|
-
const apps = await client.listApps();
|
|
99
|
-
console.log("Available apps:", apps);
|
|
100
|
-
|
|
101
|
-
// Get app data
|
|
102
|
-
const data = await client.getAppData("dashboard.app.yml");
|
|
103
|
-
if (!data.error) {
|
|
104
|
-
console.log("App data:", data.data);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Fetch a file (e.g., chart image)
|
|
108
|
-
const blob = await client.getFile("charts/sales-chart.png");
|
|
109
|
-
const url = URL.createObjectURL(blob);
|
|
110
|
-
// Use the URL in an <img> tag
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### Reading Parquet Files
|
|
114
|
-
|
|
115
|
-
```typescript
|
|
116
|
-
import { OxyClient, createConfig, readParquet, ParquetReader } from "@oxy/sdk";
|
|
117
|
-
|
|
118
|
-
const config = createConfig();
|
|
119
|
-
const client = new OxyClient(config);
|
|
120
|
-
|
|
121
|
-
// Quick read - get all data
|
|
122
|
-
const blob = await client.getFile("data/sales.parquet");
|
|
123
|
-
const data = await readParquet(blob, 1000); // Read first 1000 rows
|
|
124
|
-
console.log(data.columns);
|
|
125
|
-
console.log(data.rows);
|
|
126
|
-
|
|
127
|
-
// Advanced - query with SQL
|
|
128
|
-
const reader = new ParquetReader("sales");
|
|
129
|
-
await reader.registerParquet(blob);
|
|
130
|
-
|
|
131
|
-
const result = await reader.query(`
|
|
132
|
-
SELECT product, SUM(amount) as total_sales
|
|
133
|
-
FROM sales
|
|
134
|
-
GROUP BY product
|
|
135
|
-
ORDER BY total_sales DESC
|
|
136
|
-
LIMIT 10
|
|
137
|
-
`);
|
|
138
|
-
|
|
139
|
-
console.log("Top 10 products:", result.rows);
|
|
140
|
-
await reader.close();
|
|
123
|
+
const sdk = new OxySDK(createConfig());
|
|
141
124
|
```
|
|
142
125
|
|
|
143
126
|
## React Integration
|
|
144
127
|
|
|
145
|
-
###
|
|
128
|
+
### Using React Context (Recommended)
|
|
146
129
|
|
|
147
|
-
|
|
148
|
-
|
|
130
|
+
The SDK provides `OxyProvider` and `useOxy` hooks for easy integration:
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { OxyProvider, useOxy, createConfig } from '@oxy/sdk';
|
|
149
134
|
import { useEffect, useState } from 'react';
|
|
150
135
|
|
|
151
|
-
|
|
136
|
+
// Wrap your app with OxyProvider
|
|
137
|
+
function App() {
|
|
138
|
+
return (
|
|
139
|
+
<OxyProvider config={createConfig()}>
|
|
140
|
+
<Dashboard />
|
|
141
|
+
</OxyProvider>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
152
144
|
|
|
145
|
+
// Access SDK in child components
|
|
153
146
|
function Dashboard() {
|
|
147
|
+
const { sdk, isLoading, error } = useOxy();
|
|
154
148
|
const [data, setData] = useState(null);
|
|
155
149
|
|
|
156
150
|
useEffect(() => {
|
|
157
|
-
|
|
158
|
-
.
|
|
159
|
-
|
|
160
|
-
|
|
151
|
+
if (sdk) {
|
|
152
|
+
sdk.loadAppData('dashboard.app.yml')
|
|
153
|
+
.then(() => sdk.query('SELECT * FROM my_table LIMIT 100'))
|
|
154
|
+
.then(setData);
|
|
155
|
+
}
|
|
156
|
+
}, [sdk]);
|
|
161
157
|
|
|
162
|
-
if (
|
|
158
|
+
if (isLoading) return <div>Initializing SDK...</div>;
|
|
159
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
160
|
+
if (!data) return <div>Loading data...</div>;
|
|
163
161
|
|
|
164
162
|
return (
|
|
165
163
|
<div>
|
|
166
164
|
<h1>Dashboard</h1>
|
|
167
|
-
|
|
165
|
+
<table>
|
|
166
|
+
<thead>
|
|
167
|
+
<tr>
|
|
168
|
+
{data.columns.map(col => <th key={col}>{col}</th>)}
|
|
169
|
+
</tr>
|
|
170
|
+
</thead>
|
|
171
|
+
<tbody>
|
|
172
|
+
{data.rows.map((row, i) => (
|
|
173
|
+
<tr key={i}>
|
|
174
|
+
{row.map((cell, j) => <td key={j}>{String(cell)}</td>)}
|
|
175
|
+
</tr>
|
|
176
|
+
))}
|
|
177
|
+
</tbody>
|
|
178
|
+
</table>
|
|
168
179
|
</div>
|
|
169
180
|
);
|
|
170
181
|
}
|
|
171
182
|
```
|
|
172
183
|
|
|
173
|
-
###
|
|
184
|
+
### Iframe with PostMessage Auth
|
|
174
185
|
|
|
175
|
-
```
|
|
176
|
-
import {
|
|
186
|
+
```tsx
|
|
187
|
+
import { OxyProvider, useOxySDK } from '@oxy/sdk';
|
|
177
188
|
|
|
178
|
-
function
|
|
189
|
+
function App() {
|
|
190
|
+
return (
|
|
191
|
+
<OxyProvider
|
|
192
|
+
useAsync
|
|
193
|
+
config={{ parentOrigin: 'https://app.example.com' }}
|
|
194
|
+
>
|
|
195
|
+
<Dashboard />
|
|
196
|
+
</OxyProvider>
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function Dashboard() {
|
|
201
|
+
const sdk = useOxySDK(); // Throws if not ready
|
|
179
202
|
const [data, setData] = useState(null);
|
|
180
203
|
|
|
181
204
|
useEffect(() => {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const result = await reader.getAll(100);
|
|
187
|
-
setData(result);
|
|
188
|
-
await reader.close();
|
|
189
|
-
}
|
|
190
|
-
loadData();
|
|
191
|
-
}, [filePath]);
|
|
205
|
+
sdk.loadFile('data/sales.parquet', 'sales')
|
|
206
|
+
.then(() => sdk.query('SELECT * FROM sales LIMIT 100'))
|
|
207
|
+
.then(setData);
|
|
208
|
+
}, [sdk]);
|
|
192
209
|
|
|
193
|
-
|
|
210
|
+
return <div>{/* render data */}</div>;
|
|
194
211
|
}
|
|
195
212
|
```
|
|
196
213
|
|
|
197
|
-
|
|
214
|
+
### Without Context (Alternative)
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { OxySDK, createConfig } from '@oxy/sdk';
|
|
218
|
+
import { useEffect, useState } from 'react';
|
|
219
|
+
|
|
220
|
+
const sdk = new OxySDK(createConfig());
|
|
221
|
+
|
|
222
|
+
function Dashboard() {
|
|
223
|
+
const [data, setData] = useState(null);
|
|
224
|
+
|
|
225
|
+
useEffect(() => {
|
|
226
|
+
sdk.loadAppData('dashboard.app.yml')
|
|
227
|
+
.then(() => sdk.query('SELECT * FROM my_table LIMIT 100'))
|
|
228
|
+
.then(setData);
|
|
229
|
+
}, []);
|
|
198
230
|
|
|
199
|
-
|
|
231
|
+
return <div>{/* render data */}</div>;
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Use with v0 and Sandbox Services
|
|
200
236
|
|
|
201
|
-
**For AI Assistants (v0.dev, Cursor, etc.):** See [.v0/rules.md](.v0/rules.md) and [.cursorrules](.cursorrules) for
|
|
237
|
+
**For AI Assistants (v0.dev, Cursor, etc.):** See [.v0/rules.md](.v0/rules.md) and [.cursorrules](.cursorrules) for integration guidelines.
|
|
202
238
|
|
|
203
239
|
```typescript
|
|
204
|
-
|
|
205
|
-
import { OxyClient, createConfig, readParquet } from "@oxy/sdk";
|
|
240
|
+
import { OxySDK, createConfig } from "@oxy/sdk";
|
|
206
241
|
|
|
207
|
-
|
|
208
|
-
const client = new OxyClient(createConfig());
|
|
242
|
+
const sdk = new OxySDK(createConfig());
|
|
209
243
|
|
|
210
|
-
export async function
|
|
211
|
-
|
|
212
|
-
client.getAppData("apps/sales.app.yml"),
|
|
213
|
-
client.getAppData("apps/customers.app.yml"),
|
|
214
|
-
]);
|
|
244
|
+
export async function getDashboardData() {
|
|
245
|
+
await sdk.loadAppData("dashboard.app.yml");
|
|
215
246
|
|
|
216
|
-
return
|
|
247
|
+
return await sdk.query(`
|
|
248
|
+
SELECT s.*, c.name as customer_name
|
|
249
|
+
FROM sales s
|
|
250
|
+
LEFT JOIN customers c ON s.customer_id = c.id
|
|
251
|
+
ORDER BY s.date DESC
|
|
252
|
+
LIMIT 100
|
|
253
|
+
`);
|
|
217
254
|
}
|
|
218
255
|
|
|
219
|
-
export function
|
|
220
|
-
return
|
|
256
|
+
export function getChartUrl() {
|
|
257
|
+
return sdk.getClient().getFileUrl("charts/sales-overview.png");
|
|
221
258
|
}
|
|
222
259
|
```
|
|
223
260
|
|
|
224
|
-
|
|
261
|
+
## API Reference
|
|
262
|
+
|
|
263
|
+
### OxySDK (Unified Interface)
|
|
264
|
+
|
|
265
|
+
The `OxySDK` class combines `OxyClient` and `ParquetReader` into a single, easy-to-use interface.
|
|
266
|
+
|
|
267
|
+
#### `constructor(config: OxyConfig)`
|
|
225
268
|
|
|
226
|
-
|
|
269
|
+
Creates a new SDK instance.
|
|
227
270
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
271
|
+
#### `static async create(config?: Partial<OxyConfig>): Promise<OxySDK>`
|
|
272
|
+
|
|
273
|
+
Creates an SDK instance with async configuration (supports postMessage auth).
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
const sdk = await OxySDK.create({
|
|
277
|
+
parentOrigin: 'https://app.example.com',
|
|
278
|
+
projectId: 'your-project-id'
|
|
279
|
+
});
|
|
233
280
|
```
|
|
234
281
|
|
|
235
|
-
|
|
282
|
+
#### `async loadFile(filePath: string, tableName: string): Promise<void>`
|
|
236
283
|
|
|
237
|
-
|
|
284
|
+
Loads a Parquet file from Oxy and registers it for SQL queries.
|
|
238
285
|
|
|
239
|
-
|
|
286
|
+
```typescript
|
|
287
|
+
await sdk.loadFile('data/sales.parquet', 'sales');
|
|
288
|
+
```
|
|
240
289
|
|
|
241
|
-
|
|
290
|
+
#### `async loadFiles(files: Array<{filePath: string, tableName: string}>): Promise<void>`
|
|
242
291
|
|
|
243
|
-
|
|
292
|
+
Loads multiple Parquet files at once.
|
|
244
293
|
|
|
245
|
-
|
|
294
|
+
```typescript
|
|
295
|
+
await sdk.loadFiles([
|
|
296
|
+
{ filePath: 'data/sales.parquet', tableName: 'sales' },
|
|
297
|
+
{ filePath: 'data/customers.parquet', tableName: 'customers' }
|
|
298
|
+
]);
|
|
299
|
+
```
|
|
246
300
|
|
|
247
|
-
#### `
|
|
301
|
+
#### `async loadAppData(appPath: string): Promise<DataContainer | null>`
|
|
248
302
|
|
|
249
|
-
|
|
303
|
+
Loads all data from an app's data container. Uses container keys as table names.
|
|
250
304
|
|
|
251
|
-
|
|
305
|
+
```typescript
|
|
306
|
+
const data = await sdk.loadAppData('dashboard.app.yml');
|
|
307
|
+
// Now query the tables using their container keys
|
|
308
|
+
const result = await sdk.query('SELECT * FROM my_table');
|
|
309
|
+
```
|
|
252
310
|
|
|
253
|
-
|
|
311
|
+
#### `async query(sql: string): Promise<QueryResult>`
|
|
254
312
|
|
|
255
|
-
|
|
313
|
+
Executes a SQL query against loaded data.
|
|
256
314
|
|
|
257
|
-
|
|
315
|
+
```typescript
|
|
316
|
+
const result = await sdk.query('SELECT * FROM sales WHERE amount > 1000');
|
|
317
|
+
```
|
|
258
318
|
|
|
259
|
-
#### `
|
|
319
|
+
#### `async getAll(tableName: string, limit?: number): Promise<QueryResult>`
|
|
260
320
|
|
|
261
|
-
|
|
321
|
+
Gets all data from a loaded table.
|
|
262
322
|
|
|
263
|
-
|
|
323
|
+
```typescript
|
|
324
|
+
const data = await sdk.getAll('sales', 100);
|
|
325
|
+
```
|
|
264
326
|
|
|
265
|
-
|
|
327
|
+
#### `async getSchema(tableName: string): Promise<QueryResult>`
|
|
266
328
|
|
|
267
|
-
|
|
329
|
+
Gets schema information for a loaded table.
|
|
268
330
|
|
|
269
|
-
#### `
|
|
331
|
+
#### `async count(tableName: string): Promise<number>`
|
|
270
332
|
|
|
271
|
-
|
|
333
|
+
Gets row count for a loaded table.
|
|
272
334
|
|
|
273
|
-
#### `
|
|
335
|
+
#### `getClient(): OxyClient`
|
|
274
336
|
|
|
275
|
-
|
|
337
|
+
Returns the underlying `OxyClient` for advanced operations.
|
|
276
338
|
|
|
277
|
-
|
|
339
|
+
```typescript
|
|
340
|
+
const apps = await sdk.getClient().listApps();
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
#### `getReader(): ParquetReader`
|
|
344
|
+
|
|
345
|
+
Returns the underlying `ParquetReader` for advanced operations.
|
|
346
|
+
|
|
347
|
+
#### `async close(): Promise<void>`
|
|
348
|
+
|
|
349
|
+
Closes and cleans up all resources.
|
|
350
|
+
|
|
351
|
+
### React Hooks
|
|
352
|
+
|
|
353
|
+
#### `OxyProvider`
|
|
354
|
+
|
|
355
|
+
Provider component that initializes and provides OxySDK to child components.
|
|
356
|
+
|
|
357
|
+
**Props:**
|
|
358
|
+
- `config?: Partial<OxyConfig>` - SDK configuration
|
|
359
|
+
- `useAsync?: boolean` - If true, uses async initialization (supports postMessage auth)
|
|
360
|
+
- `onReady?: (sdk: OxySDK) => void` - Called when SDK is initialized
|
|
361
|
+
- `onError?: (error: Error) => void` - Called on initialization error
|
|
362
|
+
|
|
363
|
+
```tsx
|
|
364
|
+
<OxyProvider config={createConfig()}>
|
|
365
|
+
<YourApp />
|
|
366
|
+
</OxyProvider>
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### `useOxy()`
|
|
278
370
|
|
|
279
|
-
|
|
371
|
+
Hook to access SDK, loading state, and errors.
|
|
280
372
|
|
|
281
|
-
|
|
373
|
+
```tsx
|
|
374
|
+
const { sdk, isLoading, error } = useOxy();
|
|
375
|
+
```
|
|
282
376
|
|
|
283
|
-
|
|
377
|
+
Returns:
|
|
378
|
+
- `sdk: OxySDK | null` - The SDK instance (null if not ready)
|
|
379
|
+
- `isLoading: boolean` - True while initializing
|
|
380
|
+
- `error: Error | null` - Initialization error if any
|
|
284
381
|
|
|
285
|
-
#### `
|
|
382
|
+
#### `useOxySDK()`
|
|
286
383
|
|
|
287
|
-
|
|
384
|
+
Hook that returns SDK directly or throws if not ready. Useful when you know SDK should be initialized.
|
|
288
385
|
|
|
289
|
-
|
|
386
|
+
```tsx
|
|
387
|
+
const sdk = useOxySDK(); // Throws if not ready
|
|
388
|
+
```
|
|
290
389
|
|
|
291
|
-
|
|
390
|
+
### Advanced: OxyClient
|
|
292
391
|
|
|
293
|
-
|
|
392
|
+
For advanced use cases, access the underlying client via `sdk.getClient()`:
|
|
294
393
|
|
|
295
|
-
|
|
394
|
+
```typescript
|
|
395
|
+
const client = sdk.getClient();
|
|
396
|
+
await client.listApps();
|
|
397
|
+
await client.getDisplays('my-app.app.yml');
|
|
398
|
+
const blob = await client.getFile('path/to/file.parquet');
|
|
399
|
+
```
|
|
296
400
|
|
|
297
|
-
|
|
401
|
+
### Advanced: ParquetReader
|
|
298
402
|
|
|
299
|
-
|
|
403
|
+
For advanced use cases, access the underlying reader via `sdk.getReader()`:
|
|
300
404
|
|
|
301
|
-
|
|
405
|
+
```typescript
|
|
406
|
+
const reader = sdk.getReader();
|
|
407
|
+
await reader.registerParquet(customBlob, 'custom_table');
|
|
408
|
+
```
|
|
302
409
|
|
|
303
|
-
|
|
410
|
+
Or use standalone:
|
|
304
411
|
|
|
305
|
-
|
|
412
|
+
```typescript
|
|
413
|
+
import { ParquetReader } from "@oxy/sdk";
|
|
414
|
+
|
|
415
|
+
const reader = new ParquetReader();
|
|
416
|
+
await reader.registerParquet(blob1, 'table1');
|
|
417
|
+
await reader.registerParquet(blob2, 'table2');
|
|
418
|
+
|
|
419
|
+
const result = await reader.query('SELECT * FROM table1 JOIN table2 ON ...');
|
|
420
|
+
await reader.close();
|
|
421
|
+
```
|
|
306
422
|
|
|
307
423
|
## Environment Variables
|
|
308
424
|
|
|
@@ -315,12 +431,6 @@ Quick helper to read all data from a Parquet blob.
|
|
|
315
431
|
|
|
316
432
|
See the [examples](./examples) directory for more detailed examples:
|
|
317
433
|
|
|
318
|
-
- [basic-usage.ts](./examples/basic-usage.ts) - Basic SDK usage
|
|
319
|
-
- [parquet-usage.ts](./examples/parquet-usage.ts) - Parquet file reading
|
|
320
|
-
- [react-example.tsx](./examples/react-example.tsx) - React integration
|
|
321
|
-
- [react-parquet.tsx](./examples/react-parquet.tsx) - React with Parquet
|
|
322
|
-
- [v0-integration.ts](./examples/v0-integration.ts) - v0 sandbox integration
|
|
323
|
-
|
|
324
434
|
## Building and Publishing
|
|
325
435
|
|
|
326
436
|
```bash
|