@dremio/js-sdk 0.40.1 → 0.42.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 ADDED
@@ -0,0 +1,1043 @@
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
+ ### Deno
46
+
47
+ ```typescript
48
+ import { Dremio, fromPat } from "npm:@dremio/js-sdk@latest/cloud";
49
+
50
+ const dremio = new Dremio({
51
+ origin: "https://api.dremio.cloud",
52
+ credentials: fromPat("PERSONAL_ACCESS_TOKEN"),
53
+ });
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```typescript
59
+ import { Dremio, fromAccessToken } from "@dremio/js-sdk/cloud";
60
+
61
+ const dremio = new Dremio({
62
+ origin: "https://api.dremio.cloud",
63
+ credentials: fromAccessToken("ACCESS_TOKEN"),
64
+ });
65
+
66
+ // Create a `Job` from a SQL query
67
+ const job = await dremio
68
+ .jobs("PROJECT_ID")
69
+ .createAndRetrieve({ sql: "SELECT * FROM my_table LIMIT 100" })
70
+ .then((result) => result.unwrap());
71
+
72
+ // Retrieve `Job` results as an array
73
+ // Waits for job completion before attempting to fetch results
74
+ const results = await job.results.slice().then((result) => result.unwrap());
75
+
76
+ // Observe job status in real-time
77
+ const subscription = dremio
78
+ .jobs("PROJECT_ID")
79
+ .observe("JOB_ID")
80
+ .subscribe((result) => {
81
+ const job = result.unwrap();
82
+ console.log("Job state:", job.state);
83
+ });
84
+ ```
85
+
86
+ ## Features
87
+
88
+ ### Async Generators
89
+
90
+ Pagination is handled automatically through the usage of async generators:
91
+
92
+ ```typescript
93
+ // Iterate through pages automatically
94
+ for await (const project of dremio.projects.list().data()) {
95
+ // Process project
96
+ }
97
+
98
+ // Or collect all pages at once
99
+ const projects = await Array.fromAsync(dremio.projects.list().data());
100
+ ```
101
+
102
+ ### Request Coalescing
103
+
104
+ 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:
105
+
106
+ ```typescript
107
+ // Results in only one bulk HTTP API call
108
+ for (const script of await Array.fromAsync(
109
+ dremio.scripts("PROJECT_ID").list().data(),
110
+ )) {
111
+ if (script.owner.id === "USER_ID") {
112
+ await script.delete();
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### Typed Error Handling
118
+
119
+ 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.
120
+
121
+ ### Native Data Types
122
+
123
+ API responses are automatically converted to native JavaScript/TypeScript types:
124
+
125
+ - ISO 8601 date strings → `Date` objects
126
+ - Timestamps → `Temporal.Instant`
127
+ - Durations → `Temporal.Duration`
128
+ - Large integers → `bigint`
129
+ - Arrays → `Set` or `Map` where appropriate
130
+
131
+ ## Table of Contents
132
+
133
+ - [Configuration](#configuration)
134
+ - [Authentication](#authentication)
135
+ - [Catalog](#catalog)
136
+ - [Engine Rules](#engine-rules)
137
+ - [Engines](#engines)
138
+ - [Jobs](#jobs)
139
+ - [OAuth Applications](#oauth-applications)
140
+ - [Organizations](#organizations)
141
+ - [Projects](#projects)
142
+ - [Roles](#roles)
143
+ - [Scripts](#scripts)
144
+ - [Users](#users)
145
+
146
+ ## Configuration
147
+
148
+ The `Dremio` class accepts a configuration object with the following properties:
149
+
150
+ ```typescript
151
+ interface DremioConfig {
152
+ origin: string;
153
+ credentials: CredentialProvider;
154
+ logger?: Logger;
155
+ fetch?: typeof fetch;
156
+ }
157
+ ```
158
+
159
+ ### `origin`
160
+
161
+ The base API URL of your Dremio instance:
162
+
163
+ **Dremio Cloud:**
164
+
165
+ - `"https://api.dremio.cloud"` - US region
166
+ - `"https://api.eu.dremio.cloud"` - EU region
167
+
168
+ **Dremio Self-Hosted:**
169
+
170
+ - Your self-hosted Dremio URL (e.g., `"https://dremio.example.com"`)
171
+
172
+ ### `credentials`
173
+
174
+ A credential provider function that returns authentication headers. See the [Authentication](#authentication) section for available options:
175
+
176
+ - `fromAccessToken()` - OAuth access token
177
+ - `fromRefreshToken()` - OAuth refresh token (auto-refreshes)
178
+ - `fromPat()` - Personal access token
179
+
180
+ ### `logger` (optional)
181
+
182
+ A custom logger implementation. Must implement:
183
+
184
+ ```typescript
185
+ interface Logger {
186
+ debug(message: string, ...args: any[]): void;
187
+ info(message: string, ...args: any[]): void;
188
+ warn(message: string, ...args: any[]): void;
189
+ error(message: string, ...args: any[]): void;
190
+ }
191
+ ```
192
+
193
+ See [Custom Logger](#custom-logger) for examples.
194
+
195
+ ### `fetch` (optional)
196
+
197
+ A custom fetch implementation. Useful for:
198
+
199
+ - Adding custom middleware
200
+ - Using a specific fetch polyfill
201
+ - Intercepting requests for testing
202
+
203
+ Defaults to the global `fetch` function.
204
+
205
+ ## Authentication
206
+
207
+ ### Access Token
208
+
209
+ ```typescript
210
+ import { Dremio, fromAccessToken } from "@dremio/js-sdk/cloud";
211
+
212
+ const dremio = new Dremio({
213
+ origin: "https://api.dremio.cloud",
214
+ credentials: fromAccessToken("your-access-token"),
215
+ });
216
+ ```
217
+
218
+ ### Refresh Token
219
+
220
+ ```typescript
221
+ import { Dremio, fromRefreshToken } from "@dremio/js-sdk/cloud";
222
+
223
+ const credentials = fromRefreshToken({
224
+ client_id: "your-client-id",
225
+ redirect_uri: "your-redirect-uri",
226
+ })("your-refresh-token");
227
+
228
+ const dremio = new Dremio({
229
+ origin: "https://api.dremio.cloud",
230
+ credentials,
231
+ });
232
+ ```
233
+
234
+ ### Personal Access Token (PAT)
235
+
236
+ ```typescript
237
+ import { Dremio, fromPat } from "@dremio/js-sdk/cloud";
238
+
239
+ const dremio = new Dremio({
240
+ origin: "https://api.dremio.cloud",
241
+ credentials: fromPat("your-personal-access-token"),
242
+ });
243
+ ```
244
+
245
+ ## Catalog
246
+
247
+ ### `CatalogReference` Interface
248
+
249
+ ```typescript
250
+ interface CatalogReference {
251
+ readonly id: string;
252
+ readonly path: string[];
253
+ readonly name: string;
254
+ readonly type:
255
+ | "DATASET_DIRECT"
256
+ | "DATASET_PROMOTED"
257
+ | "DATASET_VIRTUAL"
258
+ | "FILE"
259
+ | "FOLDER"
260
+ | "FUNCTION"
261
+ | "HOME"
262
+ | "SOURCE"
263
+ | "SPACE";
264
+ pathString(separator?: string): string;
265
+ catalogObject(): Promise<Result<CatalogObject, unknown>>;
266
+ }
267
+ ```
268
+
269
+ ### List Catalog Root
270
+
271
+ ```typescript
272
+ for await (const item of dremio.catalog("PROJECT_ID").list().data()) {
273
+ console.log(item.path, item.type);
274
+ }
275
+ ```
276
+
277
+ ### Retrieve by ID
278
+
279
+ ```typescript
280
+ const catalogObject = await dremio
281
+ .catalog("PROJECT_ID")
282
+ .retrieve("CATALOG_ID")
283
+ .then((result) => result.unwrap());
284
+ ```
285
+
286
+ **Options:**
287
+
288
+ - `signal`: Optional AbortSignal for request cancellation
289
+
290
+ ### Retrieve by Path
291
+
292
+ ```typescript
293
+ const catalogObject = await dremio
294
+ .catalog("PROJECT_ID")
295
+ .retrieveByPath(["SOURCE_NAME", "folder", "table"])
296
+ .then((result) => result.unwrap());
297
+ ```
298
+
299
+ ### Search Catalog
300
+
301
+ ```typescript
302
+ for await (const result of dremio
303
+ .catalog("PROJECT_ID")
304
+ .search({
305
+ query: "sales",
306
+ filter: 'type=="DATASET"',
307
+ limit: 50,
308
+ })
309
+ .data()) {
310
+ console.log(result.path, result.type);
311
+ }
312
+ ```
313
+
314
+ **Search Options:**
315
+
316
+ - `query`: Search query string
317
+ - `filter`: Optional filter expression
318
+ - `limit`: Maximum results per page (default: 25)
319
+ - `signal`: Optional AbortSignal
320
+
321
+ ### Upload Files to Catalog
322
+
323
+ ```typescript
324
+ const uploadLocation = await dremio
325
+ .catalog("PROJECT_ID")
326
+ .copyFromObjectStore({
327
+ sourceName: "SOURCE_NAME",
328
+ path: ["folder", "dataset.parquet"],
329
+ extension: "parquet",
330
+ })
331
+ .then((result) => result.unwrap());
332
+ ```
333
+
334
+ ### Upload and Ingest File (Node.js)
335
+
336
+ ```typescript
337
+ import { Readable } from "node:stream";
338
+ import { createReadStream } from "node:fs";
339
+
340
+ const job = await dremio
341
+ .catalog("PROJECT_ID")
342
+ .upload(Readable.toWeb(createReadStream("./data.csv")), "csv")
343
+ .andThen((fileUpload) => {
344
+ const fileFormat = {
345
+ type: "CSV",
346
+ comment: "#",
347
+ escape: '"',
348
+ extractHeader: true,
349
+ fieldDelimiter: ",",
350
+ lineDelimiter: "\r\n",
351
+ quote: '"',
352
+ skipLines: 0,
353
+ emptyAsNull: true,
354
+ trimSpace: true,
355
+ } as const;
356
+ return fileUpload
357
+ .preview({ fileFormat })
358
+ .map(({ schema }) => ({ fileFormat, fileUpload, schema }));
359
+ })
360
+ .andThen(({ fileFormat, fileUpload, schema }) =>
361
+ fileUpload.ingest({
362
+ extension: "csv",
363
+ fileFormat,
364
+ schemaFields: schema,
365
+ namespace: ["@username"],
366
+ tableName: "my_table",
367
+ }),
368
+ )
369
+ .andThen((jobId) => dremio.jobs("PROJECT_ID").retrieve(jobId))
370
+ .map((job) => job.retrieveSettled())
371
+ .then((result) => result.unwrap());
372
+ ```
373
+
374
+ ### Upload File with Progress (Browser)
375
+
376
+ ```typescript
377
+ const FILE_FORMAT = {
378
+ type: "CSV",
379
+ extractHeader: true,
380
+ fieldDelimiter: ",",
381
+ lineDelimiter: "\n",
382
+ quote: '"',
383
+ escape: "\\",
384
+ comment: "#",
385
+ skipLines: 0,
386
+ emptyAsNull: true,
387
+ trimSpace: true,
388
+ } as const;
389
+
390
+ const fileUpload = await dremio
391
+ .catalog("PROJECT_ID")
392
+ .uploadXHR(fileObject, "csv", {
393
+ onProgress: (e) => {
394
+ console.log(`Upload progress: ${e.loaded}/${e.total}`);
395
+ },
396
+ })
397
+ .then((result) => result.unwrap());
398
+
399
+ // Preview and ingest
400
+ const job = await fileUpload
401
+ .preview({ fileFormat: FILE_FORMAT })
402
+ .andThen(({ schema }) =>
403
+ fileUpload.ingest({
404
+ extension: "csv",
405
+ fileFormat: FILE_FORMAT,
406
+ namespace: ["@username"],
407
+ tableName: "my_table",
408
+ schemaFields: schema,
409
+ }),
410
+ )
411
+ .andThen((jobId) => dremio.jobs("PROJECT_ID").retrieve(jobId))
412
+ .map((job) => job.retrieveSettled())
413
+ .then((result) => result.unwrap());
414
+ ```
415
+
416
+ ## Engine Rules
417
+
418
+ ### List Engine Rules
419
+
420
+ ```typescript
421
+ const { rules, defaultRule, tag } = await dremio
422
+ .engineRules("PROJECT_ID")
423
+ .list()
424
+ .then((result) => result.unwrap());
425
+
426
+ rules.forEach((rule) => {
427
+ console.log(rule.id, rule.name, rule.engines);
428
+ });
429
+ ```
430
+
431
+ **Options:**
432
+
433
+ - `signal`: Optional AbortSignal for request cancellation
434
+
435
+ ## Engines
436
+
437
+ ### `Engine` Interface
438
+
439
+ ```typescript
440
+ import { Temporal } from "temporal-polyfill";
441
+
442
+ type EngineSize =
443
+ | "XX_SMALL_V1"
444
+ | "X_SMALL_V1"
445
+ | "SMALL_V1"
446
+ | "MEDIUM_V1"
447
+ | "LARGE_V1"
448
+ | "X_LARGE_V1"
449
+ | "XX_LARGE_V1"
450
+ | "XXX_LARGE_V1";
451
+
452
+ interface EngineConfiguration {
453
+ readonly autoStopDelay: Temporal.Duration;
454
+ readonly cloudTags: Array<{ key: string; value: string }>;
455
+ readonly description: string | null;
456
+ readonly drainTimeLimit: Temporal.Duration;
457
+ readonly maxConcurrency: number;
458
+ readonly maxReplicas: number;
459
+ readonly minReplicas: number;
460
+ readonly queueTimeLimit: Temporal.Duration;
461
+ readonly runTimeLimit: Temporal.Duration;
462
+ readonly size: EngineSize;
463
+ }
464
+
465
+ interface Engine {
466
+ readonly id: string;
467
+ readonly name: string;
468
+ readonly state:
469
+ | "DELETING"
470
+ | "DISABLED"
471
+ | "DISABLING"
472
+ | "ENABLED"
473
+ | "ENABLING"
474
+ | "INVALID";
475
+ readonly activeReplicas: number;
476
+ readonly configuration: EngineConfiguration;
477
+ readonly statusChangedAt: Date;
478
+ readonly queriedAt: Date | null;
479
+ update(properties: Partial<EngineConfiguration>): Promise<Engine>;
480
+ }
481
+ ```
482
+
483
+ ### List All Engines
484
+
485
+ ```typescript
486
+ for await (const engine of dremio.engines("PROJECT_ID").list().data()) {
487
+ console.log(engine.id, engine.name, engine.state);
488
+ console.log("Size:", engine.configuration.size);
489
+ console.log("Min replicas:", engine.configuration.minReplicas);
490
+ console.log("Max replicas:", engine.configuration.maxReplicas);
491
+ console.log("Active replicas:", engine.activeReplicas);
492
+ }
493
+ ```
494
+
495
+ **Options:**
496
+
497
+ - `signal`: Optional AbortSignal for request cancellation
498
+
499
+ ### Retrieve a Specific Engine
500
+
501
+ ```typescript
502
+ const engine = await dremio
503
+ .engines("PROJECT_ID")
504
+ .retrieve("ENGINE_ID")
505
+ .then((result) => result.unwrap());
506
+ ```
507
+
508
+ ### Update Engine Configuration
509
+
510
+ ```typescript
511
+ const engine = await dremio
512
+ .engines("PROJECT_ID")
513
+ .retrieve("ENGINE_ID")
514
+ .then((result) => result.unwrap());
515
+
516
+ const updatedEngine = await engine.update({
517
+ size: "LARGE_V1", // Engine size
518
+ minReplicas: 1,
519
+ maxReplicas: 5,
520
+ maxConcurrency: 100,
521
+ autoStopDelay: Temporal.Duration.from({ minutes: 15 }),
522
+ description: "Production query engine",
523
+ cloudTags: [{ key: "environment", value: "production" }],
524
+ });
525
+ ```
526
+
527
+ ## Jobs
528
+
529
+ The `jobs` resource is available for project-level job queries:
530
+
531
+ ```typescript
532
+ // Retrieve job by ID
533
+ const job = await dremio
534
+ .jobs("PROJECT_ID")
535
+ .retrieve("JOB_ID")
536
+ .then((result) => result.unwrap());
537
+ ```
538
+
539
+ ### `Job` Interface
540
+
541
+ ```typescript
542
+ interface Job {
543
+ readonly id: string;
544
+ readonly state:
545
+ | "NOT_SUBMITTED"
546
+ | "STARTING"
547
+ | "RUNNING"
548
+ | "COMPLETED"
549
+ | "CANCELED"
550
+ | "FAILED"
551
+ | "CANCELLATION_REQUESTED"
552
+ | "PLANNING"
553
+ | "PENDING"
554
+ | "METADATA_RETRIEVAL"
555
+ | "QUEUED"
556
+ | "ENGINE_START"
557
+ | "EXECUTION_PLANNING"
558
+ | "INVALID_STATE";
559
+ readonly queryType:
560
+ | "UI_RUN"
561
+ | "UI_PREVIEW"
562
+ | "ODBC"
563
+ | "JDBC"
564
+ | "REST"
565
+ | "ACCELERATOR_CREATE"
566
+ | "ACCELERATOR_DROP"
567
+ | "UNKNOWN";
568
+ readonly startedAt: Date | null;
569
+ readonly endedAt: Date | null;
570
+ readonly rowCount: number | null;
571
+ readonly errorMessage?: string;
572
+ readonly settled: boolean;
573
+ readonly results: {
574
+ slice: (start?: number, end?: number) => Promise<Result<any[], unknown>>;
575
+ metadata: () => Promise<
576
+ Result<{ schema: any; totalRows: number }, unknown>
577
+ >;
578
+ jsonBatches: () => AsyncGenerator<any, void, unknown>;
579
+ };
580
+ retrieveSettled(): Promise<Job>;
581
+ cancel(): Promise<Result<void, unknown>>;
582
+ }
583
+ ```
584
+
585
+ For detailed job management methods, refer to the Enterprise/OSS documentation.
586
+
587
+ ## OAuth Applications
588
+
589
+ ### `OAuthApplication` Interface
590
+
591
+ ```typescript
592
+ interface OAuthApplication {
593
+ readonly id: string;
594
+ readonly name: string;
595
+ readonly state: "ENABLED" | "DISABLED";
596
+ delete(): Promise<Result<void, unknown>>;
597
+ }
598
+
599
+ interface OAuthApplicationDetails extends OAuthApplication {
600
+ readonly clientId: string;
601
+ readonly redirectUris: Set<string>;
602
+ readonly type: "NATIVE" | "REGULAR_WEB" | "SPA";
603
+ }
604
+ ```
605
+
606
+ ### List OAuth Applications
607
+
608
+ ```typescript
609
+ for await (const app of dremio.oauthApplications.list().data()) {
610
+ // Process app
611
+ }
612
+ ```
613
+
614
+ **Options:**
615
+
616
+ - `signal`: Optional AbortSignal for request cancellation
617
+
618
+ ### Retrieve an OAuth Application
619
+
620
+ ```typescript
621
+ const app = await dremio.oauthApplications
622
+ .retrieve("APP_ID")
623
+ .then((result) => result.unwrap());
624
+ ```
625
+
626
+ **Options:**
627
+
628
+ - `signal`: Optional AbortSignal for request cancellation
629
+
630
+ ### Create an OAuth Application
631
+
632
+ ```typescript
633
+ const appId = await dremio.oauthApplications
634
+ .create({
635
+ name: "My Application",
636
+ type: "confidential",
637
+ redirectUris: ["https://myapp.com/callback"],
638
+ })
639
+ .then((result) => result.unwrap());
640
+ ```
641
+
642
+ ### Delete an OAuth Application
643
+
644
+ ```typescript
645
+ const app = await dremio.oauthApplications
646
+ .retrieve("APP_ID")
647
+ .then((result) => result.unwrap());
648
+
649
+ await app.delete();
650
+ ```
651
+
652
+ ## Organizations
653
+
654
+ ### `Organization` Interface
655
+
656
+ ```typescript
657
+ interface Organization {
658
+ readonly id: string;
659
+ readonly name: string;
660
+ readonly state:
661
+ | "ACTIVE"
662
+ | "FAILED"
663
+ | "DELETED"
664
+ | "INVALID"
665
+ | "CFT_STARTED"
666
+ | "CFT_COMPLETE"
667
+ | "COMMISSIONING";
668
+ readonly createdAt: Temporal.Instant;
669
+ readonly createdBy: string;
670
+ readonly modifiedAt: Temporal.Instant;
671
+ readonly modifiedBy: string;
672
+ readonly defaultProjectId: string;
673
+ readonly cloudTags: Array<{ key: string; value: string }>;
674
+ readonly settled: boolean;
675
+ update(fields: {
676
+ name?: string;
677
+ defaultProjectId?: string;
678
+ }): Promise<Result<Organization, unknown>>;
679
+ }
680
+ ```
681
+
682
+ ### Retrieve Current Organization
683
+
684
+ ```typescript
685
+ const organization = await dremio.organizations
686
+ .retrieve()
687
+ .then((result) => result.unwrap());
688
+ ```
689
+
690
+ **Options:**
691
+
692
+ - `signal`: Optional AbortSignal for request cancellation
693
+
694
+ ## Projects
695
+
696
+ ### `Project` Interface
697
+
698
+ ```typescript
699
+ interface Project {
700
+ readonly id: string;
701
+ readonly name: string;
702
+ readonly state:
703
+ | "ACTIVATING"
704
+ | "ACTIVE"
705
+ | "ARCHIVED"
706
+ | "ARCHIVING"
707
+ | "CREATING"
708
+ | "DEACTIVATING"
709
+ | "INACTIVE"
710
+ | "RESTORING";
711
+ readonly cloudId: string;
712
+ readonly cloudType: "AWS" | "AZURE";
713
+ readonly createdAt: Date;
714
+ readonly createdBy: string;
715
+ readonly modifiedAt: Date;
716
+ readonly modifiedBy: string;
717
+ readonly numberOfEngines: number;
718
+ readonly type: "QUERY_ENGINE";
719
+ readonly settled: boolean;
720
+ delete(): Promise<Result<undefined, unknown>>;
721
+ update(properties: { name?: string }): Promise<Result<Project, unknown>>;
722
+ grants(): Promise<
723
+ Result<{ grants: Grant[]; availablePrivileges: string[] }, unknown>
724
+ >;
725
+ }
726
+ ```
727
+
728
+ ### List All Projects
729
+
730
+ ```typescript
731
+ for await (const project of dremio.projects.list().data()) {
732
+ console.log(project.id, project.name, project.state);
733
+ }
734
+ ```
735
+
736
+ **Options:**
737
+
738
+ - `signal`: Optional AbortSignal for request cancellation
739
+
740
+ ### Retrieve a Specific Project
741
+
742
+ ```typescript
743
+ const project = await dremio.projects
744
+ .retrieve("PROJECT_ID")
745
+ .then((result) => result.unwrap());
746
+ ```
747
+
748
+ **Options:**
749
+
750
+ - `signal`: Optional AbortSignal for request cancellation
751
+
752
+ ### Observe Project Changes
753
+
754
+ ```typescript
755
+ import { Subscription } from "rxjs";
756
+
757
+ const subscription: Subscription = dremio.projects
758
+ .observe("PROJECT_ID")
759
+ .subscribe({
760
+ next: (project) => {
761
+ console.log("Project state:", project.state);
762
+ },
763
+ error: (error) => {
764
+ console.error("Error observing project:", error);
765
+ },
766
+ });
767
+
768
+ // Unsubscribe when done
769
+ subscription.unsubscribe();
770
+ ```
771
+
772
+ ### Activate a Project
773
+
774
+ ```typescript
775
+ await dremio.projects.activate("PROJECT_ID");
776
+ ```
777
+
778
+ ### Delete a Project
779
+
780
+ ```typescript
781
+ await dremio.projects.delete("PROJECT_ID");
782
+ ```
783
+
784
+ ### Update a Project
785
+
786
+ ```typescript
787
+ const project = await dremio.projects
788
+ .retrieve("PROJECT_ID")
789
+ .then((result) => result.unwrap());
790
+
791
+ const updatedProject = await project
792
+ .update({
793
+ name: "New Project Name",
794
+ })
795
+ .then((result) => result.unwrap());
796
+ ```
797
+
798
+ ### Project Grants Management
799
+
800
+ ```typescript
801
+ const project = await dremio.projects
802
+ .retrieve("PROJECT_ID")
803
+ .then((result) => result.unwrap());
804
+
805
+ // Retrieve grants
806
+ const { grants, availablePrivileges } = await project
807
+ .grants()
808
+ .then((result) => result.unwrap());
809
+
810
+ grants.forEach((grant) => {
811
+ console.log(grant.grantee, grant.privileges);
812
+ });
813
+ ```
814
+
815
+ ## Roles
816
+
817
+ ### `Role` Interface
818
+
819
+ ```typescript
820
+ interface RoleReference {
821
+ readonly id: string;
822
+ readonly name: string;
823
+ readonly type: "INTERNAL" | "EXTERNAL" | "SYSTEM";
824
+ delete(): Promise<Result<void, unknown>>;
825
+ }
826
+
827
+ interface Role {
828
+ readonly roleReference: RoleReference;
829
+ readonly description: string | null;
830
+ readonly memberCount: number;
831
+ readonly roles: RoleReference[];
832
+ update(properties: {
833
+ name?: string;
834
+ roles?: RoleReference[];
835
+ description?: string;
836
+ }): Promise<Result<Role, unknown>>;
837
+ }
838
+ ```
839
+
840
+ ### List Roles
841
+
842
+ ```typescript
843
+ // List all roles
844
+ for await (const role of dremio.roles("PROJECT_ID").list().data()) {
845
+ console.log(role.roleReference.id, role.roleReference.name);
846
+ }
847
+
848
+ // Retrieve a role
849
+ const role = await dremio
850
+ .roles("PROJECT_ID")
851
+ .retrieve("ROLE_ID")
852
+ .then((result) => result.unwrap());
853
+ ```
854
+
855
+ For detailed role management methods, refer to the Enterprise documentation.
856
+
857
+ ## Scripts
858
+
859
+ ### `Script` Interface
860
+
861
+ ```typescript
862
+ import { Query } from "@dremio/js-sdk/common";
863
+ import { Temporal } from "temporal-polyfill";
864
+
865
+ interface Script {
866
+ readonly id: string;
867
+ readonly name: string;
868
+ readonly query: Query;
869
+ readonly createdAt: Temporal.Instant;
870
+ readonly createdBy: string;
871
+ readonly modifiedAt: Temporal.Instant;
872
+ readonly modifiedBy: string;
873
+ delete(): Promise<Result<void, unknown>>;
874
+ save(properties: {
875
+ name?: string;
876
+ query?: Query;
877
+ }): Promise<Result<Script, unknown>>;
878
+ }
879
+ ```
880
+
881
+ ### List Scripts
882
+
883
+ ```typescript
884
+ for await (const script of dremio.scripts("PROJECT_ID").list().data()) {
885
+ console.log(script.id, script.name);
886
+ }
887
+ ```
888
+
889
+ **Options:**
890
+
891
+ - `signal`: Optional AbortSignal for request cancellation
892
+
893
+ ### Retrieve a Script
894
+
895
+ ```typescript
896
+ const script = await dremio
897
+ .scripts("PROJECT_ID")
898
+ .retrieve("SCRIPT_ID")
899
+ .then((result) => result.unwrap());
900
+ ```
901
+
902
+ **Options:**
903
+
904
+ - `signal`: Optional AbortSignal for request cancellation
905
+
906
+ ### Create a Script
907
+
908
+ ```typescript
909
+ import { Query } from "@dremio/js-sdk/common";
910
+
911
+ const script = await dremio
912
+ .scripts("PROJECT_ID")
913
+ .store({
914
+ name: "My Query",
915
+ query: new Query("SELECT * FROM my_table", ["@username"]),
916
+ })
917
+ .then((result) => result.unwrap());
918
+ ```
919
+
920
+ ### Update a Script
921
+
922
+ ```typescript
923
+ const script = await dremio
924
+ .scripts("PROJECT_ID")
925
+ .retrieve("SCRIPT_ID")
926
+ .then((result) => result.unwrap());
927
+
928
+ const updatedScript = await script
929
+ .save({
930
+ name: "Updated Query Name",
931
+ query: new Query("SELECT * FROM my_table WHERE id > 100", ["@username"]),
932
+ })
933
+ .then((result) => result.unwrap());
934
+ ```
935
+
936
+ ### Delete a Script
937
+
938
+ ```typescript
939
+ const script = await dremio
940
+ .scripts("PROJECT_ID")
941
+ .retrieve("SCRIPT_ID")
942
+ .then((result) => result.unwrap());
943
+
944
+ await script.delete();
945
+ ```
946
+
947
+ ## Error Handling
948
+
949
+ 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:
950
+
951
+ ```typescript
952
+ import { Result } from "ts-results-es";
953
+
954
+ const result = await dremio.projects.retrieve("PROJECT_ID");
955
+
956
+ if (result.isOk()) {
957
+ const project = result.value;
958
+ console.log(project.name);
959
+ } else {
960
+ const error = result.error;
961
+ console.error("Error:", error);
962
+ }
963
+
964
+ // Or use unwrap() and catch errors
965
+ try {
966
+ const project = await dremio.projects
967
+ .retrieve("PROJECT_ID")
968
+ .then((result) => result.unwrap());
969
+ } catch (error) {
970
+ console.error("Error:", error);
971
+ }
972
+ ```
973
+
974
+ ## Request Cancellation
975
+
976
+ Methods that do not change state in Dremio support cancellation via AbortSignal:
977
+
978
+ ```typescript
979
+ const abortController = new AbortController();
980
+
981
+ // Pass the signal to the request
982
+ const project = await dremio.projects
983
+ .retrieve("PROJECT_ID", {
984
+ signal: abortController.signal,
985
+ })
986
+ .then((result) => result.unwrap());
987
+
988
+ // Cancel the request if needed
989
+ abortController.abort();
990
+ ```
991
+
992
+ ## Observable Pattern
993
+
994
+ Some methods return RxJS Observables for real-time updates:
995
+
996
+ ```typescript
997
+ import { Subscription } from "rxjs";
998
+
999
+ const subscription = dremio.projects.observe("PROJECT_ID").subscribe({
1000
+ next: (project) => console.log("Project updated:", project.state),
1001
+ error: (error) => console.error("Error:", error),
1002
+ complete: () => console.log("Observation complete"),
1003
+ });
1004
+
1005
+ // Unsubscribe when done
1006
+ subscription.unsubscribe();
1007
+ ```
1008
+
1009
+ ## Advanced Configuration
1010
+
1011
+ ### Custom Logger
1012
+
1013
+ You can provide a custom logger implementation or use a library like [pino](https://getpino.io):
1014
+
1015
+ ```typescript
1016
+ import pino from "pino";
1017
+
1018
+ const logger = pino();
1019
+
1020
+ const dremio = new Dremio({
1021
+ origin: "https://api.dremio.cloud",
1022
+ credentials: fromAccessToken("your-token"),
1023
+ logger,
1024
+ });
1025
+ ```
1026
+
1027
+ ### Custom Fetch Implementation
1028
+
1029
+ ```typescript
1030
+ const dremio = new Dremio({
1031
+ origin: "https://api.dremio.cloud",
1032
+ credentials: fromAccessToken("your-token"),
1033
+ fetch: customFetchImplementation,
1034
+ });
1035
+ ```
1036
+
1037
+ ## API Reference
1038
+
1039
+ For complete HTTP API documentation (which this SDK wraps), see the [Dremio Cloud API Reference](https://docs.dremio.com/dremio-cloud/api/).
1040
+
1041
+ ## License
1042
+
1043
+ Apache-2.0
@@ -1430,7 +1430,7 @@ var DremioCloud = (() => {
1430
1430
  // dist/cloud/Dremio.js
1431
1431
  var import_moize2 = __toESM(require_moize(), 1);
1432
1432
 
1433
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/utils.js
1433
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/utils.js
1434
1434
  function toString(val) {
1435
1435
  var value = String(val);
1436
1436
  if (value === "[object Object]") {
@@ -1442,7 +1442,7 @@ var DremioCloud = (() => {
1442
1442
  return value;
1443
1443
  }
1444
1444
 
1445
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/option.js
1445
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/option.js
1446
1446
  var NoneImpl = (
1447
1447
  /** @class */
1448
1448
  (function() {
@@ -1611,7 +1611,7 @@ var DremioCloud = (() => {
1611
1611
  Option2.isOption = isOption;
1612
1612
  })(Option || (Option = {}));
1613
1613
 
1614
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/result.js
1614
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/result.js
1615
1615
  var __spreadArray = function(to2, from2, pack) {
1616
1616
  if (pack || arguments.length === 2) for (var i2 = 0, l2 = from2.length, ar2; i2 < l2; i2++) {
1617
1617
  if (ar2 || !(i2 in from2)) {
@@ -1849,7 +1849,7 @@ var DremioCloud = (() => {
1849
1849
  Result2.isResult = isResult;
1850
1850
  })(Result || (Result = {}));
1851
1851
 
1852
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/asyncresult.js
1852
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/asyncresult.js
1853
1853
  var __awaiter = function(thisArg, _arguments, P2, generator) {
1854
1854
  function adopt(value) {
1855
1855
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -2032,6 +2032,9 @@ var DremioCloud = (() => {
2032
2032
  return result.toOption();
2033
2033
  }));
2034
2034
  };
2035
+ AsyncResult2.prototype.then = function(onfulfilled, onrejected) {
2036
+ return this.promise.then(onfulfilled, onrejected);
2037
+ };
2035
2038
  AsyncResult2.prototype.thenInternal = function(mapper) {
2036
2039
  return new AsyncResult2(this.promise.then(mapper));
2037
2040
  };
@@ -2039,7 +2042,7 @@ var DremioCloud = (() => {
2039
2042
  })()
2040
2043
  );
2041
2044
 
2042
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/asyncoption.js
2045
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/asyncoption.js
2043
2046
  var __awaiter2 = function(thisArg, _arguments, P2, generator) {
2044
2047
  function adopt(value) {
2045
2048
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -2202,6 +2205,9 @@ var DremioCloud = (() => {
2202
2205
  return option.toResult(error);
2203
2206
  }));
2204
2207
  };
2208
+ AsyncOption2.prototype.then = function(onfulfilled, onrejected) {
2209
+ return this.promise.then(onfulfilled, onrejected);
2210
+ };
2205
2211
  AsyncOption2.prototype.thenInternal = function(mapper) {
2206
2212
  return new AsyncOption2(this.promise.then(mapper));
2207
2213
  };
@@ -3486,7 +3486,7 @@ var DremioCommunity = (() => {
3486
3486
  }
3487
3487
  };
3488
3488
 
3489
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/utils.js
3489
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/utils.js
3490
3490
  function toString(val) {
3491
3491
  var value = String(val);
3492
3492
  if (value === "[object Object]") {
@@ -3498,7 +3498,7 @@ var DremioCommunity = (() => {
3498
3498
  return value;
3499
3499
  }
3500
3500
 
3501
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/option.js
3501
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/option.js
3502
3502
  var NoneImpl = (
3503
3503
  /** @class */
3504
3504
  (function() {
@@ -3667,7 +3667,7 @@ var DremioCommunity = (() => {
3667
3667
  Option2.isOption = isOption;
3668
3668
  })(Option || (Option = {}));
3669
3669
 
3670
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/result.js
3670
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/result.js
3671
3671
  var __spreadArray = function(to2, from2, pack) {
3672
3672
  if (pack || arguments.length === 2) for (var i2 = 0, l2 = from2.length, ar2; i2 < l2; i2++) {
3673
3673
  if (ar2 || !(i2 in from2)) {
@@ -3905,7 +3905,7 @@ var DremioCommunity = (() => {
3905
3905
  Result2.isResult = isResult;
3906
3906
  })(Result || (Result = {}));
3907
3907
 
3908
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/asyncresult.js
3908
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/asyncresult.js
3909
3909
  var __awaiter = function(thisArg, _arguments, P2, generator) {
3910
3910
  function adopt(value) {
3911
3911
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -4088,6 +4088,9 @@ var DremioCommunity = (() => {
4088
4088
  return result.toOption();
4089
4089
  }));
4090
4090
  };
4091
+ AsyncResult2.prototype.then = function(onfulfilled, onrejected) {
4092
+ return this.promise.then(onfulfilled, onrejected);
4093
+ };
4091
4094
  AsyncResult2.prototype.thenInternal = function(mapper) {
4092
4095
  return new AsyncResult2(this.promise.then(mapper));
4093
4096
  };
@@ -4095,7 +4098,7 @@ var DremioCommunity = (() => {
4095
4098
  })()
4096
4099
  );
4097
4100
 
4098
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/asyncoption.js
4101
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/asyncoption.js
4099
4102
  var __awaiter2 = function(thisArg, _arguments, P2, generator) {
4100
4103
  function adopt(value) {
4101
4104
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -4258,6 +4261,9 @@ var DremioCommunity = (() => {
4258
4261
  return option.toResult(error);
4259
4262
  }));
4260
4263
  };
4264
+ AsyncOption2.prototype.then = function(onfulfilled, onrejected) {
4265
+ return this.promise.then(onfulfilled, onrejected);
4266
+ };
4261
4267
  AsyncOption2.prototype.thenInternal = function(mapper) {
4262
4268
  return new AsyncOption2(this.promise.then(mapper));
4263
4269
  };
@@ -3540,7 +3540,7 @@ var DremioEnterprise = (() => {
3540
3540
  var EnterpriseFileCatalogReference = class extends FileCatalogReference {
3541
3541
  };
3542
3542
 
3543
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/utils.js
3543
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/utils.js
3544
3544
  function toString(val) {
3545
3545
  var value = String(val);
3546
3546
  if (value === "[object Object]") {
@@ -3552,7 +3552,7 @@ var DremioEnterprise = (() => {
3552
3552
  return value;
3553
3553
  }
3554
3554
 
3555
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/option.js
3555
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/option.js
3556
3556
  var NoneImpl = (
3557
3557
  /** @class */
3558
3558
  (function() {
@@ -3721,7 +3721,7 @@ var DremioEnterprise = (() => {
3721
3721
  Option2.isOption = isOption;
3722
3722
  })(Option || (Option = {}));
3723
3723
 
3724
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/result.js
3724
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/result.js
3725
3725
  var __spreadArray = function(to2, from2, pack) {
3726
3726
  if (pack || arguments.length === 2) for (var i2 = 0, l2 = from2.length, ar2; i2 < l2; i2++) {
3727
3727
  if (ar2 || !(i2 in from2)) {
@@ -3959,7 +3959,7 @@ var DremioEnterprise = (() => {
3959
3959
  Result2.isResult = isResult;
3960
3960
  })(Result || (Result = {}));
3961
3961
 
3962
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/asyncresult.js
3962
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/asyncresult.js
3963
3963
  var __awaiter = function(thisArg, _arguments, P2, generator) {
3964
3964
  function adopt(value) {
3965
3965
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -4142,6 +4142,9 @@ var DremioEnterprise = (() => {
4142
4142
  return result.toOption();
4143
4143
  }));
4144
4144
  };
4145
+ AsyncResult2.prototype.then = function(onfulfilled, onrejected) {
4146
+ return this.promise.then(onfulfilled, onrejected);
4147
+ };
4145
4148
  AsyncResult2.prototype.thenInternal = function(mapper) {
4146
4149
  return new AsyncResult2(this.promise.then(mapper));
4147
4150
  };
@@ -4149,7 +4152,7 @@ var DremioEnterprise = (() => {
4149
4152
  })()
4150
4153
  );
4151
4154
 
4152
- // node_modules/.pnpm/ts-results-es@5.0.1/node_modules/ts-results-es/dist/esm/asyncoption.js
4155
+ // node_modules/.pnpm/ts-results-es@6.0.0/node_modules/ts-results-es/dist/esm/asyncoption.js
4153
4156
  var __awaiter2 = function(thisArg, _arguments, P2, generator) {
4154
4157
  function adopt(value) {
4155
4158
  return value instanceof P2 ? value : new P2(function(resolve) {
@@ -4312,6 +4315,9 @@ var DremioEnterprise = (() => {
4312
4315
  return option.toResult(error);
4313
4316
  }));
4314
4317
  };
4318
+ AsyncOption2.prototype.then = function(onfulfilled, onrejected) {
4319
+ return this.promise.then(onfulfilled, onrejected);
4320
+ };
4315
4321
  AsyncOption2.prototype.thenInternal = function(mapper) {
4316
4322
  return new AsyncOption2(this.promise.then(mapper));
4317
4323
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dremio/js-sdk",
3
- "version": "0.40.1",
3
+ "version": "0.42.0",
4
4
  "description": "JavaScript library for the Dremio API",
5
5
  "keywords": [
6
6
  "dremio",
@@ -54,7 +54,7 @@
54
54
  "rxjs": "^7",
55
55
  "semver": "^7",
56
56
  "temporal-polyfill": "^0.3.0",
57
- "ts-results-es": "^5.0.1",
57
+ "ts-results-es": "^6.0.0",
58
58
  "zod": "^4.1.0"
59
59
  },
60
60
  "devDependencies": {