@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.
Files changed (2) hide show
  1. package/README.md +972 -0
  2. 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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dremio/js-sdk",
3
- "version": "0.40.1",
3
+ "version": "0.41.0",
4
4
  "description": "JavaScript library for the Dremio API",
5
5
  "keywords": [
6
6
  "dremio",