@dremio/js-sdk 0.40.1 → 0.41.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 +972 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,972 @@
|
|
|
1
|
+
# Dremio JavaScript SDK
|
|
2
|
+
|
|
3
|
+
A JavaScript/TypeScript SDK for interacting with Dremio HTTP APIs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @dremio/js-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm install @dremio/js-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bun install @dremio/js-sdk
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Browser (IIFE)
|
|
20
|
+
|
|
21
|
+
**jsDelivr:**
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<script src="https://cdn.jsdelivr.net/npm/@dremio/js-sdk@latest/dist-iife/cloud.js"></script>
|
|
25
|
+
<script>
|
|
26
|
+
const { Dremio, fromAccessToken } = window.DremioCloud;
|
|
27
|
+
|
|
28
|
+
const dremio = new Dremio({
|
|
29
|
+
origin: "https://api.dremio.cloud",
|
|
30
|
+
credentials: fromAccessToken("ACCESS_TOKEN"),
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**unpkg:**
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<script src="https://unpkg.com/@dremio/js-sdk@latest/dist-iife/cloud.js"></script>
|
|
39
|
+
<script>
|
|
40
|
+
const { Dremio, fromAccessToken } = window.DremioCloud;
|
|
41
|
+
// ... same usage as above
|
|
42
|
+
</script>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
import { Dremio, fromAccessToken } from "@dremio/js-sdk/cloud";
|
|
49
|
+
|
|
50
|
+
const dremio = new Dremio({
|
|
51
|
+
origin: "https://api.dremio.cloud",
|
|
52
|
+
credentials: fromAccessToken("ACCESS_TOKEN"),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Create a `Job` from a SQL query
|
|
56
|
+
const job = await dremio
|
|
57
|
+
.jobs("PROJECT_ID")
|
|
58
|
+
.createAndRetrieve({ sql: "SELECT * FROM my_table LIMIT 100" })
|
|
59
|
+
.then((result) => result.unwrap());
|
|
60
|
+
|
|
61
|
+
// Retrieve `Job` results as an array
|
|
62
|
+
// Waits for job completion before attempting to fetch results
|
|
63
|
+
const results = await job.results.slice().then((result) => result.unwrap());
|
|
64
|
+
|
|
65
|
+
// Observe job status in real-time
|
|
66
|
+
const subscription = dremio
|
|
67
|
+
.jobs("PROJECT_ID")
|
|
68
|
+
.observe("JOB_ID")
|
|
69
|
+
.subscribe((result) => {
|
|
70
|
+
const job = result.unwrap();
|
|
71
|
+
console.log("Job state:", job.state);
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Features
|
|
76
|
+
|
|
77
|
+
### Async Generators
|
|
78
|
+
|
|
79
|
+
Pagination is handled automatically through the usage of async generators:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Iterate through pages automatically
|
|
83
|
+
for await (const project of dremio.projects.list().data()) {
|
|
84
|
+
// Process project
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Or collect all pages at once
|
|
88
|
+
const projects = await Array.fromAsync(dremio.projects.list().data());
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Request Coalescing
|
|
92
|
+
|
|
93
|
+
When multiple delete or update requests are made synchronously within the same event loop tick, the SDK automatically coalesces them into a single batch API call when available:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// Results in only one bulk HTTP API call
|
|
97
|
+
for (const script of await Array.fromAsync(
|
|
98
|
+
dremio.scripts("PROJECT_ID").list().data(),
|
|
99
|
+
)) {
|
|
100
|
+
if (script.owner.id === "USER_ID") {
|
|
101
|
+
await script.delete();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Typed Error Handling
|
|
107
|
+
|
|
108
|
+
Errors are represented as `Result<T, E>` (see [ts-results-es](https://github.com/vultix/ts-results-es)) to allow type-safe handling of runtime errors. See [Error Handling](#error-handling) for more details.
|
|
109
|
+
|
|
110
|
+
### Native Data Types
|
|
111
|
+
|
|
112
|
+
API responses are automatically converted to native JavaScript/TypeScript types:
|
|
113
|
+
|
|
114
|
+
- ISO 8601 date strings → `Date` objects
|
|
115
|
+
- Timestamps → `Temporal.Instant`
|
|
116
|
+
- Durations → `Temporal.Duration`
|
|
117
|
+
- Large integers → `bigint`
|
|
118
|
+
- Arrays → `Set` or `Map` where appropriate
|
|
119
|
+
|
|
120
|
+
## Table of Contents
|
|
121
|
+
|
|
122
|
+
- [Authentication](#authentication)
|
|
123
|
+
- [Catalog](#catalog)
|
|
124
|
+
- [Engine Rules](#engine-rules)
|
|
125
|
+
- [Engines](#engines)
|
|
126
|
+
- [Jobs](#jobs)
|
|
127
|
+
- [OAuth Applications](#oauth-applications)
|
|
128
|
+
- [Organizations](#organizations)
|
|
129
|
+
- [Projects](#projects)
|
|
130
|
+
- [Roles](#roles)
|
|
131
|
+
- [Scripts](#scripts)
|
|
132
|
+
- [Users](#users)
|
|
133
|
+
|
|
134
|
+
## Authentication
|
|
135
|
+
|
|
136
|
+
### Access Token
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { Dremio, fromAccessToken } from "@dremio/js-sdk/cloud";
|
|
140
|
+
|
|
141
|
+
const dremio = new Dremio({
|
|
142
|
+
origin: "https://api.dremio.cloud",
|
|
143
|
+
credentials: fromAccessToken("your-access-token"),
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Refresh Token
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { Dremio, fromRefreshToken } from "@dremio/js-sdk/cloud";
|
|
151
|
+
|
|
152
|
+
const credentials = fromRefreshToken({
|
|
153
|
+
client_id: "your-client-id",
|
|
154
|
+
redirect_uri: "your-redirect-uri",
|
|
155
|
+
})("your-refresh-token");
|
|
156
|
+
|
|
157
|
+
const dremio = new Dremio({
|
|
158
|
+
origin: "https://api.dremio.cloud",
|
|
159
|
+
credentials,
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Personal Access Token (PAT)
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
import { Dremio, fromPat } from "@dremio/js-sdk/cloud";
|
|
167
|
+
|
|
168
|
+
const dremio = new Dremio({
|
|
169
|
+
origin: "https://api.dremio.cloud",
|
|
170
|
+
credentials: fromPat("your-personal-access-token"),
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Catalog
|
|
175
|
+
|
|
176
|
+
### `CatalogReference` Interface
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
interface CatalogReference {
|
|
180
|
+
readonly id: string;
|
|
181
|
+
readonly path: string[];
|
|
182
|
+
readonly name: string;
|
|
183
|
+
readonly type:
|
|
184
|
+
| "DATASET_DIRECT"
|
|
185
|
+
| "DATASET_PROMOTED"
|
|
186
|
+
| "DATASET_VIRTUAL"
|
|
187
|
+
| "FILE"
|
|
188
|
+
| "FOLDER"
|
|
189
|
+
| "FUNCTION"
|
|
190
|
+
| "HOME"
|
|
191
|
+
| "SOURCE"
|
|
192
|
+
| "SPACE";
|
|
193
|
+
pathString(separator?: string): string;
|
|
194
|
+
catalogObject(): Promise<Result<CatalogObject, unknown>>;
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### List Catalog Root
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
for await (const item of dremio.catalog("PROJECT_ID").list().data()) {
|
|
202
|
+
console.log(item.path, item.type);
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Retrieve by ID
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const catalogObject = await dremio
|
|
210
|
+
.catalog("PROJECT_ID")
|
|
211
|
+
.retrieve("CATALOG_ID")
|
|
212
|
+
.then((result) => result.unwrap());
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Options:**
|
|
216
|
+
|
|
217
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
218
|
+
|
|
219
|
+
### Retrieve by Path
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
const catalogObject = await dremio
|
|
223
|
+
.catalog("PROJECT_ID")
|
|
224
|
+
.retrieveByPath(["SOURCE_NAME", "folder", "table"])
|
|
225
|
+
.then((result) => result.unwrap());
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Search Catalog
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
for await (const result of dremio
|
|
232
|
+
.catalog("PROJECT_ID")
|
|
233
|
+
.search({
|
|
234
|
+
query: "sales",
|
|
235
|
+
filter: 'type=="DATASET"',
|
|
236
|
+
limit: 50,
|
|
237
|
+
})
|
|
238
|
+
.data()) {
|
|
239
|
+
console.log(result.path, result.type);
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Search Options:**
|
|
244
|
+
|
|
245
|
+
- `query`: Search query string
|
|
246
|
+
- `filter`: Optional filter expression
|
|
247
|
+
- `limit`: Maximum results per page (default: 25)
|
|
248
|
+
- `signal`: Optional AbortSignal
|
|
249
|
+
|
|
250
|
+
### Upload Files to Catalog
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
const uploadLocation = await dremio
|
|
254
|
+
.catalog("PROJECT_ID")
|
|
255
|
+
.copyFromObjectStore({
|
|
256
|
+
sourceName: "SOURCE_NAME",
|
|
257
|
+
path: ["folder", "dataset.parquet"],
|
|
258
|
+
extension: "parquet",
|
|
259
|
+
})
|
|
260
|
+
.then((result) => result.unwrap());
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Upload and Ingest File (Node.js)
|
|
264
|
+
|
|
265
|
+
```typescript
|
|
266
|
+
import { Readable } from "node:stream";
|
|
267
|
+
import { createReadStream } from "node:fs";
|
|
268
|
+
|
|
269
|
+
const job = await dremio
|
|
270
|
+
.catalog("PROJECT_ID")
|
|
271
|
+
.upload(Readable.toWeb(createReadStream("./data.csv")), "csv")
|
|
272
|
+
.andThen((fileUpload) => {
|
|
273
|
+
const fileFormat = {
|
|
274
|
+
type: "CSV",
|
|
275
|
+
comment: "#",
|
|
276
|
+
escape: '"',
|
|
277
|
+
extractHeader: true,
|
|
278
|
+
fieldDelimiter: ",",
|
|
279
|
+
lineDelimiter: "\r\n",
|
|
280
|
+
quote: '"',
|
|
281
|
+
skipLines: 0,
|
|
282
|
+
emptyAsNull: true,
|
|
283
|
+
trimSpace: true,
|
|
284
|
+
} as const;
|
|
285
|
+
return fileUpload
|
|
286
|
+
.preview({ fileFormat })
|
|
287
|
+
.map(({ schema }) => ({ fileFormat, fileUpload, schema }));
|
|
288
|
+
})
|
|
289
|
+
.andThen(({ fileFormat, fileUpload, schema }) =>
|
|
290
|
+
fileUpload.ingest({
|
|
291
|
+
extension: "csv",
|
|
292
|
+
fileFormat,
|
|
293
|
+
schemaFields: schema,
|
|
294
|
+
namespace: ["@username"],
|
|
295
|
+
tableName: "my_table",
|
|
296
|
+
}),
|
|
297
|
+
)
|
|
298
|
+
.andThen((jobId) => dremio.jobs("PROJECT_ID").retrieve(jobId))
|
|
299
|
+
.map((job) => job.retrieveSettled())
|
|
300
|
+
.then((result) => result.unwrap());
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Upload File with Progress (Browser)
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
const FILE_FORMAT = {
|
|
307
|
+
type: "CSV",
|
|
308
|
+
extractHeader: true,
|
|
309
|
+
fieldDelimiter: ",",
|
|
310
|
+
lineDelimiter: "\n",
|
|
311
|
+
quote: '"',
|
|
312
|
+
escape: "\\",
|
|
313
|
+
comment: "#",
|
|
314
|
+
skipLines: 0,
|
|
315
|
+
emptyAsNull: true,
|
|
316
|
+
trimSpace: true,
|
|
317
|
+
} as const;
|
|
318
|
+
|
|
319
|
+
const fileUpload = await dremio
|
|
320
|
+
.catalog("PROJECT_ID")
|
|
321
|
+
.uploadXHR(fileObject, "csv", {
|
|
322
|
+
onProgress: (e) => {
|
|
323
|
+
console.log(`Upload progress: ${e.loaded}/${e.total}`);
|
|
324
|
+
},
|
|
325
|
+
})
|
|
326
|
+
.then((result) => result.unwrap());
|
|
327
|
+
|
|
328
|
+
// Preview and ingest
|
|
329
|
+
const job = await fileUpload
|
|
330
|
+
.preview({ fileFormat: FILE_FORMAT })
|
|
331
|
+
.andThen(({ schema }) =>
|
|
332
|
+
fileUpload.ingest({
|
|
333
|
+
extension: "csv",
|
|
334
|
+
fileFormat: FILE_FORMAT,
|
|
335
|
+
namespace: ["@username"],
|
|
336
|
+
tableName: "my_table",
|
|
337
|
+
schemaFields: schema,
|
|
338
|
+
}),
|
|
339
|
+
)
|
|
340
|
+
.andThen((jobId) => dremio.jobs("PROJECT_ID").retrieve(jobId))
|
|
341
|
+
.map((job) => job.retrieveSettled())
|
|
342
|
+
.then((result) => result.unwrap());
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Engine Rules
|
|
346
|
+
|
|
347
|
+
### List Engine Rules
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const { rules, defaultRule, tag } = await dremio
|
|
351
|
+
.engineRules("PROJECT_ID")
|
|
352
|
+
.list()
|
|
353
|
+
.then((result) => result.unwrap());
|
|
354
|
+
|
|
355
|
+
rules.forEach((rule) => {
|
|
356
|
+
console.log(rule.id, rule.name, rule.engines);
|
|
357
|
+
});
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
**Options:**
|
|
361
|
+
|
|
362
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
363
|
+
|
|
364
|
+
## Engines
|
|
365
|
+
|
|
366
|
+
### `Engine` Interface
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { Temporal } from "temporal-polyfill";
|
|
370
|
+
|
|
371
|
+
type EngineSize =
|
|
372
|
+
| "XX_SMALL_V1"
|
|
373
|
+
| "X_SMALL_V1"
|
|
374
|
+
| "SMALL_V1"
|
|
375
|
+
| "MEDIUM_V1"
|
|
376
|
+
| "LARGE_V1"
|
|
377
|
+
| "X_LARGE_V1"
|
|
378
|
+
| "XX_LARGE_V1"
|
|
379
|
+
| "XXX_LARGE_V1";
|
|
380
|
+
|
|
381
|
+
interface EngineConfiguration {
|
|
382
|
+
readonly autoStopDelay: Temporal.Duration;
|
|
383
|
+
readonly cloudTags: Array<{ key: string; value: string }>;
|
|
384
|
+
readonly description: string | null;
|
|
385
|
+
readonly drainTimeLimit: Temporal.Duration;
|
|
386
|
+
readonly maxConcurrency: number;
|
|
387
|
+
readonly maxReplicas: number;
|
|
388
|
+
readonly minReplicas: number;
|
|
389
|
+
readonly queueTimeLimit: Temporal.Duration;
|
|
390
|
+
readonly runTimeLimit: Temporal.Duration;
|
|
391
|
+
readonly size: EngineSize;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
interface Engine {
|
|
395
|
+
readonly id: string;
|
|
396
|
+
readonly name: string;
|
|
397
|
+
readonly state:
|
|
398
|
+
| "DELETING"
|
|
399
|
+
| "DISABLED"
|
|
400
|
+
| "DISABLING"
|
|
401
|
+
| "ENABLED"
|
|
402
|
+
| "ENABLING"
|
|
403
|
+
| "INVALID";
|
|
404
|
+
readonly activeReplicas: number;
|
|
405
|
+
readonly configuration: EngineConfiguration;
|
|
406
|
+
readonly statusChangedAt: Date;
|
|
407
|
+
readonly queriedAt: Date | null;
|
|
408
|
+
update(properties: Partial<EngineConfiguration>): Promise<Engine>;
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
### List All Engines
|
|
413
|
+
|
|
414
|
+
```typescript
|
|
415
|
+
for await (const engine of dremio.engines("PROJECT_ID").list().data()) {
|
|
416
|
+
console.log(engine.id, engine.name, engine.state);
|
|
417
|
+
console.log("Size:", engine.configuration.size);
|
|
418
|
+
console.log("Min replicas:", engine.configuration.minReplicas);
|
|
419
|
+
console.log("Max replicas:", engine.configuration.maxReplicas);
|
|
420
|
+
console.log("Active replicas:", engine.activeReplicas);
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
**Options:**
|
|
425
|
+
|
|
426
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
427
|
+
|
|
428
|
+
### Retrieve a Specific Engine
|
|
429
|
+
|
|
430
|
+
```typescript
|
|
431
|
+
const engine = await dremio
|
|
432
|
+
.engines("PROJECT_ID")
|
|
433
|
+
.retrieve("ENGINE_ID")
|
|
434
|
+
.then((result) => result.unwrap());
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Update Engine Configuration
|
|
438
|
+
|
|
439
|
+
```typescript
|
|
440
|
+
const engine = await dremio
|
|
441
|
+
.engines("PROJECT_ID")
|
|
442
|
+
.retrieve("ENGINE_ID")
|
|
443
|
+
.then((result) => result.unwrap());
|
|
444
|
+
|
|
445
|
+
const updatedEngine = await engine.update({
|
|
446
|
+
size: "LARGE_V1", // Engine size
|
|
447
|
+
minReplicas: 1,
|
|
448
|
+
maxReplicas: 5,
|
|
449
|
+
maxConcurrency: 100,
|
|
450
|
+
autoStopDelay: Temporal.Duration.from({ minutes: 15 }),
|
|
451
|
+
description: "Production query engine",
|
|
452
|
+
cloudTags: [{ key: "environment", value: "production" }],
|
|
453
|
+
});
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
## Jobs
|
|
457
|
+
|
|
458
|
+
The `jobs` resource is available for project-level job queries:
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
// Retrieve job by ID
|
|
462
|
+
const job = await dremio
|
|
463
|
+
.jobs("PROJECT_ID")
|
|
464
|
+
.retrieve("JOB_ID")
|
|
465
|
+
.then((result) => result.unwrap());
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
### `Job` Interface
|
|
469
|
+
|
|
470
|
+
```typescript
|
|
471
|
+
interface Job {
|
|
472
|
+
readonly id: string;
|
|
473
|
+
readonly state:
|
|
474
|
+
| "NOT_SUBMITTED"
|
|
475
|
+
| "STARTING"
|
|
476
|
+
| "RUNNING"
|
|
477
|
+
| "COMPLETED"
|
|
478
|
+
| "CANCELED"
|
|
479
|
+
| "FAILED"
|
|
480
|
+
| "CANCELLATION_REQUESTED"
|
|
481
|
+
| "PLANNING"
|
|
482
|
+
| "PENDING"
|
|
483
|
+
| "METADATA_RETRIEVAL"
|
|
484
|
+
| "QUEUED"
|
|
485
|
+
| "ENGINE_START"
|
|
486
|
+
| "EXECUTION_PLANNING"
|
|
487
|
+
| "INVALID_STATE";
|
|
488
|
+
readonly queryType:
|
|
489
|
+
| "UI_RUN"
|
|
490
|
+
| "UI_PREVIEW"
|
|
491
|
+
| "ODBC"
|
|
492
|
+
| "JDBC"
|
|
493
|
+
| "REST"
|
|
494
|
+
| "ACCELERATOR_CREATE"
|
|
495
|
+
| "ACCELERATOR_DROP"
|
|
496
|
+
| "UNKNOWN";
|
|
497
|
+
readonly startedAt: Date | null;
|
|
498
|
+
readonly endedAt: Date | null;
|
|
499
|
+
readonly rowCount: number | null;
|
|
500
|
+
readonly errorMessage?: string;
|
|
501
|
+
readonly settled: boolean;
|
|
502
|
+
readonly results: {
|
|
503
|
+
slice: (start?: number, end?: number) => Promise<Result<any[], unknown>>;
|
|
504
|
+
metadata: () => Promise<
|
|
505
|
+
Result<{ schema: any; totalRows: number }, unknown>
|
|
506
|
+
>;
|
|
507
|
+
jsonBatches: () => AsyncGenerator<any, void, unknown>;
|
|
508
|
+
};
|
|
509
|
+
retrieveSettled(): Promise<Job>;
|
|
510
|
+
cancel(): Promise<Result<void, unknown>>;
|
|
511
|
+
}
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
For detailed job management methods, refer to the Enterprise/OSS documentation.
|
|
515
|
+
|
|
516
|
+
## OAuth Applications
|
|
517
|
+
|
|
518
|
+
### `OAuthApplication` Interface
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
interface OAuthApplication {
|
|
522
|
+
readonly id: string;
|
|
523
|
+
readonly name: string;
|
|
524
|
+
readonly state: "ENABLED" | "DISABLED";
|
|
525
|
+
delete(): Promise<Result<void, unknown>>;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
interface OAuthApplicationDetails extends OAuthApplication {
|
|
529
|
+
readonly clientId: string;
|
|
530
|
+
readonly redirectUris: Set<string>;
|
|
531
|
+
readonly type: "NATIVE" | "REGULAR_WEB" | "SPA";
|
|
532
|
+
}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
### List OAuth Applications
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
for await (const app of dremio.oauthApplications.list().data()) {
|
|
539
|
+
// Process app
|
|
540
|
+
}
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
**Options:**
|
|
544
|
+
|
|
545
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
546
|
+
|
|
547
|
+
### Retrieve an OAuth Application
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
const app = await dremio.oauthApplications
|
|
551
|
+
.retrieve("APP_ID")
|
|
552
|
+
.then((result) => result.unwrap());
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
**Options:**
|
|
556
|
+
|
|
557
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
558
|
+
|
|
559
|
+
### Create an OAuth Application
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
const appId = await dremio.oauthApplications
|
|
563
|
+
.create({
|
|
564
|
+
name: "My Application",
|
|
565
|
+
type: "confidential",
|
|
566
|
+
redirectUris: ["https://myapp.com/callback"],
|
|
567
|
+
})
|
|
568
|
+
.then((result) => result.unwrap());
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Delete an OAuth Application
|
|
572
|
+
|
|
573
|
+
```typescript
|
|
574
|
+
const app = await dremio.oauthApplications
|
|
575
|
+
.retrieve("APP_ID")
|
|
576
|
+
.then((result) => result.unwrap());
|
|
577
|
+
|
|
578
|
+
await app.delete();
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
## Organizations
|
|
582
|
+
|
|
583
|
+
### `Organization` Interface
|
|
584
|
+
|
|
585
|
+
```typescript
|
|
586
|
+
interface Organization {
|
|
587
|
+
readonly id: string;
|
|
588
|
+
readonly name: string;
|
|
589
|
+
readonly state:
|
|
590
|
+
| "ACTIVE"
|
|
591
|
+
| "FAILED"
|
|
592
|
+
| "DELETED"
|
|
593
|
+
| "INVALID"
|
|
594
|
+
| "CFT_STARTED"
|
|
595
|
+
| "CFT_COMPLETE"
|
|
596
|
+
| "COMMISSIONING";
|
|
597
|
+
readonly createdAt: Temporal.Instant;
|
|
598
|
+
readonly createdBy: string;
|
|
599
|
+
readonly modifiedAt: Temporal.Instant;
|
|
600
|
+
readonly modifiedBy: string;
|
|
601
|
+
readonly defaultProjectId: string;
|
|
602
|
+
readonly cloudTags: Array<{ key: string; value: string }>;
|
|
603
|
+
readonly settled: boolean;
|
|
604
|
+
update(fields: {
|
|
605
|
+
name?: string;
|
|
606
|
+
defaultProjectId?: string;
|
|
607
|
+
}): Promise<Result<Organization, unknown>>;
|
|
608
|
+
}
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
### Retrieve Current Organization
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
const organization = await dremio.organizations
|
|
615
|
+
.retrieve()
|
|
616
|
+
.then((result) => result.unwrap());
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
**Options:**
|
|
620
|
+
|
|
621
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
622
|
+
|
|
623
|
+
## Projects
|
|
624
|
+
|
|
625
|
+
### `Project` Interface
|
|
626
|
+
|
|
627
|
+
```typescript
|
|
628
|
+
interface Project {
|
|
629
|
+
readonly id: string;
|
|
630
|
+
readonly name: string;
|
|
631
|
+
readonly state:
|
|
632
|
+
| "ACTIVATING"
|
|
633
|
+
| "ACTIVE"
|
|
634
|
+
| "ARCHIVED"
|
|
635
|
+
| "ARCHIVING"
|
|
636
|
+
| "CREATING"
|
|
637
|
+
| "DEACTIVATING"
|
|
638
|
+
| "INACTIVE"
|
|
639
|
+
| "RESTORING";
|
|
640
|
+
readonly cloudId: string;
|
|
641
|
+
readonly cloudType: "AWS" | "AZURE";
|
|
642
|
+
readonly createdAt: Date;
|
|
643
|
+
readonly createdBy: string;
|
|
644
|
+
readonly modifiedAt: Date;
|
|
645
|
+
readonly modifiedBy: string;
|
|
646
|
+
readonly numberOfEngines: number;
|
|
647
|
+
readonly type: "QUERY_ENGINE";
|
|
648
|
+
readonly settled: boolean;
|
|
649
|
+
delete(): Promise<Result<undefined, unknown>>;
|
|
650
|
+
update(properties: { name?: string }): Promise<Result<Project, unknown>>;
|
|
651
|
+
grants(): Promise<
|
|
652
|
+
Result<{ grants: Grant[]; availablePrivileges: string[] }, unknown>
|
|
653
|
+
>;
|
|
654
|
+
}
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### List All Projects
|
|
658
|
+
|
|
659
|
+
```typescript
|
|
660
|
+
for await (const project of dremio.projects.list().data()) {
|
|
661
|
+
console.log(project.id, project.name, project.state);
|
|
662
|
+
}
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
**Options:**
|
|
666
|
+
|
|
667
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
668
|
+
|
|
669
|
+
### Retrieve a Specific Project
|
|
670
|
+
|
|
671
|
+
```typescript
|
|
672
|
+
const project = await dremio.projects
|
|
673
|
+
.retrieve("PROJECT_ID")
|
|
674
|
+
.then((result) => result.unwrap());
|
|
675
|
+
```
|
|
676
|
+
|
|
677
|
+
**Options:**
|
|
678
|
+
|
|
679
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
680
|
+
|
|
681
|
+
### Observe Project Changes
|
|
682
|
+
|
|
683
|
+
```typescript
|
|
684
|
+
import { Subscription } from "rxjs";
|
|
685
|
+
|
|
686
|
+
const subscription: Subscription = dremio.projects
|
|
687
|
+
.observe("PROJECT_ID")
|
|
688
|
+
.subscribe({
|
|
689
|
+
next: (project) => {
|
|
690
|
+
console.log("Project state:", project.state);
|
|
691
|
+
},
|
|
692
|
+
error: (error) => {
|
|
693
|
+
console.error("Error observing project:", error);
|
|
694
|
+
},
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
// Unsubscribe when done
|
|
698
|
+
subscription.unsubscribe();
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Activate a Project
|
|
702
|
+
|
|
703
|
+
```typescript
|
|
704
|
+
await dremio.projects.activate("PROJECT_ID");
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### Delete a Project
|
|
708
|
+
|
|
709
|
+
```typescript
|
|
710
|
+
await dremio.projects.delete("PROJECT_ID");
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
### Update a Project
|
|
714
|
+
|
|
715
|
+
```typescript
|
|
716
|
+
const project = await dremio.projects
|
|
717
|
+
.retrieve("PROJECT_ID")
|
|
718
|
+
.then((result) => result.unwrap());
|
|
719
|
+
|
|
720
|
+
const updatedProject = await project
|
|
721
|
+
.update({
|
|
722
|
+
name: "New Project Name",
|
|
723
|
+
})
|
|
724
|
+
.then((result) => result.unwrap());
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
### Project Grants Management
|
|
728
|
+
|
|
729
|
+
```typescript
|
|
730
|
+
const project = await dremio.projects
|
|
731
|
+
.retrieve("PROJECT_ID")
|
|
732
|
+
.then((result) => result.unwrap());
|
|
733
|
+
|
|
734
|
+
// Retrieve grants
|
|
735
|
+
const { grants, availablePrivileges } = await project
|
|
736
|
+
.grants()
|
|
737
|
+
.then((result) => result.unwrap());
|
|
738
|
+
|
|
739
|
+
grants.forEach((grant) => {
|
|
740
|
+
console.log(grant.grantee, grant.privileges);
|
|
741
|
+
});
|
|
742
|
+
```
|
|
743
|
+
|
|
744
|
+
## Roles
|
|
745
|
+
|
|
746
|
+
### `Role` Interface
|
|
747
|
+
|
|
748
|
+
```typescript
|
|
749
|
+
interface RoleReference {
|
|
750
|
+
readonly id: string;
|
|
751
|
+
readonly name: string;
|
|
752
|
+
readonly type: "INTERNAL" | "EXTERNAL" | "SYSTEM";
|
|
753
|
+
delete(): Promise<Result<void, unknown>>;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
interface Role {
|
|
757
|
+
readonly roleReference: RoleReference;
|
|
758
|
+
readonly description: string | null;
|
|
759
|
+
readonly memberCount: number;
|
|
760
|
+
readonly roles: RoleReference[];
|
|
761
|
+
update(properties: {
|
|
762
|
+
name?: string;
|
|
763
|
+
roles?: RoleReference[];
|
|
764
|
+
description?: string;
|
|
765
|
+
}): Promise<Result<Role, unknown>>;
|
|
766
|
+
}
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
### List Roles
|
|
770
|
+
|
|
771
|
+
```typescript
|
|
772
|
+
// List all roles
|
|
773
|
+
for await (const role of dremio.roles("PROJECT_ID").list().data()) {
|
|
774
|
+
console.log(role.roleReference.id, role.roleReference.name);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Retrieve a role
|
|
778
|
+
const role = await dremio
|
|
779
|
+
.roles("PROJECT_ID")
|
|
780
|
+
.retrieve("ROLE_ID")
|
|
781
|
+
.then((result) => result.unwrap());
|
|
782
|
+
```
|
|
783
|
+
|
|
784
|
+
For detailed role management methods, refer to the Enterprise documentation.
|
|
785
|
+
|
|
786
|
+
## Scripts
|
|
787
|
+
|
|
788
|
+
### `Script` Interface
|
|
789
|
+
|
|
790
|
+
```typescript
|
|
791
|
+
import { Query } from "@dremio/js-sdk/common";
|
|
792
|
+
import { Temporal } from "temporal-polyfill";
|
|
793
|
+
|
|
794
|
+
interface Script {
|
|
795
|
+
readonly id: string;
|
|
796
|
+
readonly name: string;
|
|
797
|
+
readonly query: Query;
|
|
798
|
+
readonly createdAt: Temporal.Instant;
|
|
799
|
+
readonly createdBy: string;
|
|
800
|
+
readonly modifiedAt: Temporal.Instant;
|
|
801
|
+
readonly modifiedBy: string;
|
|
802
|
+
delete(): Promise<Result<void, unknown>>;
|
|
803
|
+
save(properties: {
|
|
804
|
+
name?: string;
|
|
805
|
+
query?: Query;
|
|
806
|
+
}): Promise<Result<Script, unknown>>;
|
|
807
|
+
}
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
### List Scripts
|
|
811
|
+
|
|
812
|
+
```typescript
|
|
813
|
+
for await (const script of dremio.scripts("PROJECT_ID").list().data()) {
|
|
814
|
+
console.log(script.id, script.name);
|
|
815
|
+
}
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
**Options:**
|
|
819
|
+
|
|
820
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
821
|
+
|
|
822
|
+
### Retrieve a Script
|
|
823
|
+
|
|
824
|
+
```typescript
|
|
825
|
+
const script = await dremio
|
|
826
|
+
.scripts("PROJECT_ID")
|
|
827
|
+
.retrieve("SCRIPT_ID")
|
|
828
|
+
.then((result) => result.unwrap());
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
**Options:**
|
|
832
|
+
|
|
833
|
+
- `signal`: Optional AbortSignal for request cancellation
|
|
834
|
+
|
|
835
|
+
### Create a Script
|
|
836
|
+
|
|
837
|
+
```typescript
|
|
838
|
+
import { Query } from "@dremio/js-sdk/common";
|
|
839
|
+
|
|
840
|
+
const script = await dremio
|
|
841
|
+
.scripts("PROJECT_ID")
|
|
842
|
+
.store({
|
|
843
|
+
name: "My Query",
|
|
844
|
+
query: new Query("SELECT * FROM my_table", ["@username"]),
|
|
845
|
+
})
|
|
846
|
+
.then((result) => result.unwrap());
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
### Update a Script
|
|
850
|
+
|
|
851
|
+
```typescript
|
|
852
|
+
const script = await dremio
|
|
853
|
+
.scripts("PROJECT_ID")
|
|
854
|
+
.retrieve("SCRIPT_ID")
|
|
855
|
+
.then((result) => result.unwrap());
|
|
856
|
+
|
|
857
|
+
const updatedScript = await script
|
|
858
|
+
.save({
|
|
859
|
+
name: "Updated Query Name",
|
|
860
|
+
query: new Query("SELECT * FROM my_table WHERE id > 100", ["@username"]),
|
|
861
|
+
})
|
|
862
|
+
.then((result) => result.unwrap());
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
### Delete a Script
|
|
866
|
+
|
|
867
|
+
```typescript
|
|
868
|
+
const script = await dremio
|
|
869
|
+
.scripts("PROJECT_ID")
|
|
870
|
+
.retrieve("SCRIPT_ID")
|
|
871
|
+
.then((result) => result.unwrap());
|
|
872
|
+
|
|
873
|
+
await script.delete();
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
## Error Handling
|
|
877
|
+
|
|
878
|
+
The SDK uses the [`ts-results-es`](https://github.com/lune-climate/ts-results-es) library for error handling. All methods that can fail return a `Result` or `AsyncResult` type:
|
|
879
|
+
|
|
880
|
+
```typescript
|
|
881
|
+
import { Result } from "ts-results-es";
|
|
882
|
+
|
|
883
|
+
const result = await dremio.projects.retrieve("PROJECT_ID");
|
|
884
|
+
|
|
885
|
+
if (result.isOk()) {
|
|
886
|
+
const project = result.unwrap();
|
|
887
|
+
console.log(project.name);
|
|
888
|
+
} else {
|
|
889
|
+
const error = result.unwrapErr();
|
|
890
|
+
console.error("Error:", error);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// Or use unwrap() and catch errors
|
|
894
|
+
try {
|
|
895
|
+
const project = await dremio.projects
|
|
896
|
+
.retrieve("PROJECT_ID")
|
|
897
|
+
.then((result) => result.unwrap());
|
|
898
|
+
} catch (error) {
|
|
899
|
+
console.error("Error:", error);
|
|
900
|
+
}
|
|
901
|
+
```
|
|
902
|
+
|
|
903
|
+
## Request Cancellation
|
|
904
|
+
|
|
905
|
+
Methods that do not change state in Dremio support cancellation via AbortSignal:
|
|
906
|
+
|
|
907
|
+
```typescript
|
|
908
|
+
const abortController = new AbortController();
|
|
909
|
+
|
|
910
|
+
// Pass the signal to the request
|
|
911
|
+
const project = await dremio.projects
|
|
912
|
+
.retrieve("PROJECT_ID", {
|
|
913
|
+
signal: abortController.signal,
|
|
914
|
+
})
|
|
915
|
+
.then((result) => result.unwrap());
|
|
916
|
+
|
|
917
|
+
// Cancel the request if needed
|
|
918
|
+
abortController.abort();
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
## Observable Pattern
|
|
922
|
+
|
|
923
|
+
Some methods return RxJS Observables for real-time updates:
|
|
924
|
+
|
|
925
|
+
```typescript
|
|
926
|
+
import { Subscription } from "rxjs";
|
|
927
|
+
|
|
928
|
+
const subscription = dremio.projects.observe("PROJECT_ID").subscribe({
|
|
929
|
+
next: (project) => console.log("Project updated:", project.state),
|
|
930
|
+
error: (error) => console.error("Error:", error),
|
|
931
|
+
complete: () => console.log("Observation complete"),
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
// Unsubscribe when done
|
|
935
|
+
subscription.unsubscribe();
|
|
936
|
+
```
|
|
937
|
+
|
|
938
|
+
## Advanced Configuration
|
|
939
|
+
|
|
940
|
+
### Custom Logger
|
|
941
|
+
|
|
942
|
+
You can provide a custom logger implementation or use a library like [pino](https://getpino.io):
|
|
943
|
+
|
|
944
|
+
```typescript
|
|
945
|
+
import pino from "pino";
|
|
946
|
+
|
|
947
|
+
const logger = pino();
|
|
948
|
+
|
|
949
|
+
const dremio = new Dremio({
|
|
950
|
+
origin: "https://api.dremio.cloud",
|
|
951
|
+
credentials: fromAccessToken("your-token"),
|
|
952
|
+
logger,
|
|
953
|
+
});
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
### Custom Fetch Implementation
|
|
957
|
+
|
|
958
|
+
```typescript
|
|
959
|
+
const dremio = new Dremio({
|
|
960
|
+
origin: "https://api.dremio.cloud",
|
|
961
|
+
credentials: fromAccessToken("your-token"),
|
|
962
|
+
fetch: customFetchImplementation,
|
|
963
|
+
});
|
|
964
|
+
```
|
|
965
|
+
|
|
966
|
+
## API Reference
|
|
967
|
+
|
|
968
|
+
For complete HTTP API documentation (which this SDK wraps), see the [Dremio Cloud API Reference](https://docs.dremio.com/dremio-cloud/api/).
|
|
969
|
+
|
|
970
|
+
## License
|
|
971
|
+
|
|
972
|
+
Apache-2.0
|