slates 0.0.2 → 1.0.0-rc.1

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 (34) hide show
  1. package/example/google-sheets/auth.ts +317 -0
  2. package/example/google-sheets/config.ts +9 -0
  3. package/example/google-sheets/docs/abc.md +1 -0
  4. package/example/google-sheets/docs/readme.md +1 -0
  5. package/example/google-sheets/index.ts +42 -0
  6. package/example/google-sheets/lib/client.ts +717 -0
  7. package/example/google-sheets/lib/types.ts +1674 -0
  8. package/example/google-sheets/readme.md +1 -0
  9. package/example/google-sheets/slate.json +4 -0
  10. package/example/google-sheets/spec.ts +13 -0
  11. package/example/google-sheets/tools/append-values.ts +74 -0
  12. package/example/google-sheets/tools/clear-values.ts +45 -0
  13. package/example/google-sheets/tools/copy-paste.ts +99 -0
  14. package/example/google-sheets/tools/create-spreadsheet.ts +72 -0
  15. package/example/google-sheets/tools/find-replace.ts +68 -0
  16. package/example/google-sheets/tools/format-cells.ts +137 -0
  17. package/example/google-sheets/tools/get-spreadsheet.ts +108 -0
  18. package/example/google-sheets/tools/index.ts +15 -0
  19. package/example/google-sheets/tools/manage-rows-columns.ts +160 -0
  20. package/example/google-sheets/tools/manage-sheets.ts +183 -0
  21. package/example/google-sheets/tools/merge-cells.ts +76 -0
  22. package/example/google-sheets/tools/named-ranges.ts +82 -0
  23. package/example/google-sheets/tools/protect-range.ts +100 -0
  24. package/example/google-sheets/tools/read-values.ts +94 -0
  25. package/example/google-sheets/tools/sort-range.ts +78 -0
  26. package/example/google-sheets/tools/write-values.ts +91 -0
  27. package/example/google-sheets/triggers/index.ts +1 -0
  28. package/example/google-sheets/triggers/spreadsheet-changed.ts +108 -0
  29. package/example/out.zip.b64 +1 -0
  30. package/package.json +30 -20
  31. package/src/index.ts +1 -0
  32. package/tsconfig.json +8 -0
  33. package/bin/slates.js +0 -8
  34. package/readme.md +0 -9
@@ -0,0 +1,717 @@
1
+ import { createAxios } from 'slates';
2
+ import type {
3
+ AppendValuesResponse,
4
+ BatchGetValuesResponse,
5
+ BatchUpdateSpreadsheetRequest,
6
+ BatchUpdateSpreadsheetResponse,
7
+ BatchUpdateValuesResponse,
8
+ CellFormat,
9
+ ClearValuesResponse,
10
+ ConditionalFormatRule,
11
+ DateTimeRenderOption,
12
+ GridRange,
13
+ InsertDataOption,
14
+ Request,
15
+ SheetProperties,
16
+ Spreadsheet,
17
+ SpreadsheetProperties,
18
+ UpdateValuesResponse,
19
+ ValueInputOption,
20
+ ValueRange,
21
+ ValueRenderOption
22
+ } from './types';
23
+
24
+ export interface ClientConfig {
25
+ token: string;
26
+ isApiKey?: boolean;
27
+ }
28
+
29
+ export class SheetsClient {
30
+ private axios;
31
+ private isApiKey: boolean;
32
+
33
+ constructor(config: ClientConfig) {
34
+ this.isApiKey = config.isApiKey || false;
35
+
36
+ this.axios = createAxios({
37
+ baseURL: 'https://sheets.googleapis.com/v4'
38
+ });
39
+
40
+ if (this.isApiKey) {
41
+ this.axios.defaults.params = { key: config.token };
42
+ } else {
43
+ this.axios.defaults.headers.common['Authorization'] = `Bearer ${config.token}`;
44
+ }
45
+ }
46
+
47
+ // Spreadsheet operations
48
+
49
+ async createSpreadsheet(properties: SpreadsheetProperties): Promise<Spreadsheet> {
50
+ let response = await this.axios.post('/spreadsheets', {
51
+ properties
52
+ });
53
+ return response.data;
54
+ }
55
+
56
+ async getSpreadsheet(
57
+ spreadsheetId: string,
58
+ options?: {
59
+ ranges?: string[];
60
+ includeGridData?: boolean;
61
+ }
62
+ ): Promise<Spreadsheet> {
63
+ let params: Record<string, unknown> = {};
64
+ if (options?.ranges) {
65
+ params.ranges = options.ranges;
66
+ }
67
+ if (options?.includeGridData !== undefined) {
68
+ params.includeGridData = options.includeGridData;
69
+ }
70
+
71
+ let response = await this.axios.get(`/spreadsheets/${spreadsheetId}`, { params });
72
+ return response.data;
73
+ }
74
+
75
+ async batchUpdate(
76
+ spreadsheetId: string,
77
+ requests: Request[],
78
+ options?: {
79
+ includeSpreadsheetInResponse?: boolean;
80
+ responseRanges?: string[];
81
+ responseIncludeGridData?: boolean;
82
+ }
83
+ ): Promise<BatchUpdateSpreadsheetResponse> {
84
+ let body: BatchUpdateSpreadsheetRequest = {
85
+ requests,
86
+ ...options
87
+ };
88
+
89
+ let response = await this.axios.post(`/spreadsheets/${spreadsheetId}:batchUpdate`, body);
90
+ return response.data;
91
+ }
92
+
93
+ // Sheet management
94
+
95
+ async addSheet(
96
+ spreadsheetId: string,
97
+ properties: Partial<SheetProperties>
98
+ ): Promise<SheetProperties | undefined> {
99
+ let result = await this.batchUpdate(spreadsheetId, [
100
+ {
101
+ addSheet: { properties: properties as SheetProperties }
102
+ }
103
+ ]);
104
+ return result.replies?.[0]?.addSheet?.properties;
105
+ }
106
+
107
+ async deleteSheet(spreadsheetId: string, sheetId: number): Promise<void> {
108
+ await this.batchUpdate(spreadsheetId, [
109
+ {
110
+ deleteSheet: { sheetId }
111
+ }
112
+ ]);
113
+ }
114
+
115
+ async duplicateSheet(
116
+ spreadsheetId: string,
117
+ sourceSheetId: number,
118
+ options?: {
119
+ insertSheetIndex?: number;
120
+ newSheetId?: number;
121
+ newSheetName?: string;
122
+ }
123
+ ): Promise<SheetProperties | undefined> {
124
+ let result = await this.batchUpdate(spreadsheetId, [
125
+ {
126
+ duplicateSheet: {
127
+ sourceSheetId,
128
+ ...options
129
+ }
130
+ }
131
+ ]);
132
+ return result.replies?.[0]?.duplicateSheet?.properties;
133
+ }
134
+
135
+ async updateSheetProperties(
136
+ spreadsheetId: string,
137
+ properties: SheetProperties,
138
+ fields: string
139
+ ): Promise<void> {
140
+ await this.batchUpdate(spreadsheetId, [
141
+ {
142
+ updateSheetProperties: { properties, fields }
143
+ }
144
+ ]);
145
+ }
146
+
147
+ // Values operations
148
+
149
+ async getValues(
150
+ spreadsheetId: string,
151
+ range: string,
152
+ options?: {
153
+ majorDimension?: 'ROWS' | 'COLUMNS';
154
+ valueRenderOption?: ValueRenderOption;
155
+ dateTimeRenderOption?: DateTimeRenderOption;
156
+ }
157
+ ): Promise<ValueRange> {
158
+ let response = await this.axios.get(
159
+ `/spreadsheets/${spreadsheetId}/values/${encodeURIComponent(range)}`,
160
+ { params: options }
161
+ );
162
+ return response.data;
163
+ }
164
+
165
+ async batchGetValues(
166
+ spreadsheetId: string,
167
+ ranges: string[],
168
+ options?: {
169
+ majorDimension?: 'ROWS' | 'COLUMNS';
170
+ valueRenderOption?: ValueRenderOption;
171
+ dateTimeRenderOption?: DateTimeRenderOption;
172
+ }
173
+ ): Promise<BatchGetValuesResponse> {
174
+ let response = await this.axios.get(`/spreadsheets/${spreadsheetId}/values:batchGet`, {
175
+ params: {
176
+ ranges,
177
+ ...options
178
+ }
179
+ });
180
+ return response.data;
181
+ }
182
+
183
+ async updateValues(
184
+ spreadsheetId: string,
185
+ range: string,
186
+ values: (string | number | boolean | null)[][],
187
+ options?: {
188
+ valueInputOption?: ValueInputOption;
189
+ includeValuesInResponse?: boolean;
190
+ responseValueRenderOption?: ValueRenderOption;
191
+ responseDateTimeRenderOption?: DateTimeRenderOption;
192
+ }
193
+ ): Promise<UpdateValuesResponse> {
194
+ let params = {
195
+ valueInputOption: options?.valueInputOption || 'USER_ENTERED',
196
+ includeValuesInResponse: options?.includeValuesInResponse,
197
+ responseValueRenderOption: options?.responseValueRenderOption,
198
+ responseDateTimeRenderOption: options?.responseDateTimeRenderOption
199
+ };
200
+
201
+ let response = await this.axios.put(
202
+ `/spreadsheets/${spreadsheetId}/values/${encodeURIComponent(range)}`,
203
+ { range, values },
204
+ { params }
205
+ );
206
+ return response.data;
207
+ }
208
+
209
+ async batchUpdateValues(
210
+ spreadsheetId: string,
211
+ data: { range: string; values: (string | number | boolean | null)[][] }[],
212
+ options?: {
213
+ valueInputOption?: ValueInputOption;
214
+ includeValuesInResponse?: boolean;
215
+ responseValueRenderOption?: ValueRenderOption;
216
+ responseDateTimeRenderOption?: DateTimeRenderOption;
217
+ }
218
+ ): Promise<BatchUpdateValuesResponse> {
219
+ let response = await this.axios.post(`/spreadsheets/${spreadsheetId}/values:batchUpdate`, {
220
+ data,
221
+ valueInputOption: options?.valueInputOption || 'USER_ENTERED',
222
+ includeValuesInResponse: options?.includeValuesInResponse,
223
+ responseValueRenderOption: options?.responseValueRenderOption,
224
+ responseDateTimeRenderOption: options?.responseDateTimeRenderOption
225
+ });
226
+ return response.data;
227
+ }
228
+
229
+ async appendValues(
230
+ spreadsheetId: string,
231
+ range: string,
232
+ values: (string | number | boolean | null)[][],
233
+ options?: {
234
+ valueInputOption?: ValueInputOption;
235
+ insertDataOption?: InsertDataOption;
236
+ includeValuesInResponse?: boolean;
237
+ responseValueRenderOption?: ValueRenderOption;
238
+ responseDateTimeRenderOption?: DateTimeRenderOption;
239
+ }
240
+ ): Promise<AppendValuesResponse> {
241
+ let params = {
242
+ valueInputOption: options?.valueInputOption || 'USER_ENTERED',
243
+ insertDataOption: options?.insertDataOption,
244
+ includeValuesInResponse: options?.includeValuesInResponse,
245
+ responseValueRenderOption: options?.responseValueRenderOption,
246
+ responseDateTimeRenderOption: options?.responseDateTimeRenderOption
247
+ };
248
+
249
+ let response = await this.axios.post(
250
+ `/spreadsheets/${spreadsheetId}/values/${encodeURIComponent(range)}:append`,
251
+ { range, values },
252
+ { params }
253
+ );
254
+ return response.data;
255
+ }
256
+
257
+ async clearValues(spreadsheetId: string, range: string): Promise<ClearValuesResponse> {
258
+ let response = await this.axios.post(
259
+ `/spreadsheets/${spreadsheetId}/values/${encodeURIComponent(range)}:clear`,
260
+ {}
261
+ );
262
+ return response.data;
263
+ }
264
+
265
+ async batchClearValues(
266
+ spreadsheetId: string,
267
+ ranges: string[]
268
+ ): Promise<{ spreadsheetId?: string; clearedRanges?: string[] }> {
269
+ let response = await this.axios.post(`/spreadsheets/${spreadsheetId}/values:batchClear`, {
270
+ ranges
271
+ });
272
+ return response.data;
273
+ }
274
+
275
+ // Formatting operations
276
+
277
+ async formatCells(
278
+ spreadsheetId: string,
279
+ range: GridRange,
280
+ format: CellFormat
281
+ ): Promise<void> {
282
+ await this.batchUpdate(spreadsheetId, [
283
+ {
284
+ repeatCell: {
285
+ range,
286
+ cell: {
287
+ userEnteredFormat: format
288
+ },
289
+ fields: 'userEnteredFormat'
290
+ }
291
+ }
292
+ ]);
293
+ }
294
+
295
+ async mergeCells(
296
+ spreadsheetId: string,
297
+ range: GridRange,
298
+ mergeType: 'MERGE_ALL' | 'MERGE_COLUMNS' | 'MERGE_ROWS' = 'MERGE_ALL'
299
+ ): Promise<void> {
300
+ await this.batchUpdate(spreadsheetId, [
301
+ {
302
+ mergeCells: { range, mergeType }
303
+ }
304
+ ]);
305
+ }
306
+
307
+ async unmergeCells(spreadsheetId: string, range: GridRange): Promise<void> {
308
+ await this.batchUpdate(spreadsheetId, [
309
+ {
310
+ unmergeCells: { range }
311
+ }
312
+ ]);
313
+ }
314
+
315
+ async updateBorders(
316
+ spreadsheetId: string,
317
+ range: GridRange,
318
+ borders: {
319
+ top?: {
320
+ style?:
321
+ | 'NONE'
322
+ | 'DOTTED'
323
+ | 'DASHED'
324
+ | 'SOLID'
325
+ | 'SOLID_MEDIUM'
326
+ | 'SOLID_THICK'
327
+ | 'DOUBLE';
328
+ width?: number;
329
+ color?: { red?: number; green?: number; blue?: number; alpha?: number };
330
+ };
331
+ bottom?: {
332
+ style?:
333
+ | 'NONE'
334
+ | 'DOTTED'
335
+ | 'DASHED'
336
+ | 'SOLID'
337
+ | 'SOLID_MEDIUM'
338
+ | 'SOLID_THICK'
339
+ | 'DOUBLE';
340
+ width?: number;
341
+ color?: { red?: number; green?: number; blue?: number; alpha?: number };
342
+ };
343
+ left?: {
344
+ style?:
345
+ | 'NONE'
346
+ | 'DOTTED'
347
+ | 'DASHED'
348
+ | 'SOLID'
349
+ | 'SOLID_MEDIUM'
350
+ | 'SOLID_THICK'
351
+ | 'DOUBLE';
352
+ width?: number;
353
+ color?: { red?: number; green?: number; blue?: number; alpha?: number };
354
+ };
355
+ right?: {
356
+ style?:
357
+ | 'NONE'
358
+ | 'DOTTED'
359
+ | 'DASHED'
360
+ | 'SOLID'
361
+ | 'SOLID_MEDIUM'
362
+ | 'SOLID_THICK'
363
+ | 'DOUBLE';
364
+ width?: number;
365
+ color?: { red?: number; green?: number; blue?: number; alpha?: number };
366
+ };
367
+ innerHorizontal?: {
368
+ style?:
369
+ | 'NONE'
370
+ | 'DOTTED'
371
+ | 'DASHED'
372
+ | 'SOLID'
373
+ | 'SOLID_MEDIUM'
374
+ | 'SOLID_THICK'
375
+ | 'DOUBLE';
376
+ width?: number;
377
+ color?: { red?: number; green?: number; blue?: number; alpha?: number };
378
+ };
379
+ innerVertical?: {
380
+ style?:
381
+ | 'NONE'
382
+ | 'DOTTED'
383
+ | 'DASHED'
384
+ | 'SOLID'
385
+ | 'SOLID_MEDIUM'
386
+ | 'SOLID_THICK'
387
+ | 'DOUBLE';
388
+ width?: number;
389
+ color?: { red?: number; green?: number; blue?: number; alpha?: number };
390
+ };
391
+ }
392
+ ): Promise<void> {
393
+ await this.batchUpdate(spreadsheetId, [
394
+ {
395
+ updateBorders: { range, ...borders }
396
+ }
397
+ ]);
398
+ }
399
+
400
+ // Conditional formatting
401
+
402
+ async addConditionalFormatRule(
403
+ spreadsheetId: string,
404
+ rule: ConditionalFormatRule,
405
+ index?: number
406
+ ): Promise<void> {
407
+ await this.batchUpdate(spreadsheetId, [
408
+ {
409
+ addConditionalFormatRule: { rule, index }
410
+ }
411
+ ]);
412
+ }
413
+
414
+ async deleteConditionalFormatRule(
415
+ spreadsheetId: string,
416
+ sheetId: number,
417
+ index: number
418
+ ): Promise<void> {
419
+ await this.batchUpdate(spreadsheetId, [
420
+ {
421
+ deleteConditionalFormatRule: { sheetId, index }
422
+ }
423
+ ]);
424
+ }
425
+
426
+ // Row/Column operations
427
+
428
+ async insertDimension(
429
+ spreadsheetId: string,
430
+ sheetId: number,
431
+ dimension: 'ROWS' | 'COLUMNS',
432
+ startIndex: number,
433
+ endIndex: number,
434
+ inheritFromBefore?: boolean
435
+ ): Promise<void> {
436
+ await this.batchUpdate(spreadsheetId, [
437
+ {
438
+ insertDimension: {
439
+ range: { sheetId, dimension, startIndex, endIndex },
440
+ inheritFromBefore
441
+ }
442
+ }
443
+ ]);
444
+ }
445
+
446
+ async deleteDimension(
447
+ spreadsheetId: string,
448
+ sheetId: number,
449
+ dimension: 'ROWS' | 'COLUMNS',
450
+ startIndex: number,
451
+ endIndex: number
452
+ ): Promise<void> {
453
+ await this.batchUpdate(spreadsheetId, [
454
+ {
455
+ deleteDimension: {
456
+ range: { sheetId, dimension, startIndex, endIndex }
457
+ }
458
+ }
459
+ ]);
460
+ }
461
+
462
+ async appendDimension(
463
+ spreadsheetId: string,
464
+ sheetId: number,
465
+ dimension: 'ROWS' | 'COLUMNS',
466
+ length: number
467
+ ): Promise<void> {
468
+ await this.batchUpdate(spreadsheetId, [
469
+ {
470
+ appendDimension: { sheetId, dimension, length }
471
+ }
472
+ ]);
473
+ }
474
+
475
+ async autoResizeDimensions(
476
+ spreadsheetId: string,
477
+ sheetId: number,
478
+ dimension: 'ROWS' | 'COLUMNS',
479
+ startIndex?: number,
480
+ endIndex?: number
481
+ ): Promise<void> {
482
+ await this.batchUpdate(spreadsheetId, [
483
+ {
484
+ autoResizeDimensions: {
485
+ dimensions: { sheetId, dimension, startIndex, endIndex }
486
+ }
487
+ }
488
+ ]);
489
+ }
490
+
491
+ // Find and replace
492
+
493
+ async findReplace(
494
+ spreadsheetId: string,
495
+ find: string,
496
+ replacement: string,
497
+ options?: {
498
+ matchCase?: boolean;
499
+ matchEntireCell?: boolean;
500
+ searchByRegex?: boolean;
501
+ includeFormulas?: boolean;
502
+ range?: GridRange;
503
+ sheetId?: number;
504
+ allSheets?: boolean;
505
+ }
506
+ ): Promise<{
507
+ valuesChanged?: number;
508
+ formulasChanged?: number;
509
+ rowsChanged?: number;
510
+ sheetsChanged?: number;
511
+ occurrencesChanged?: number;
512
+ }> {
513
+ let result = await this.batchUpdate(spreadsheetId, [
514
+ {
515
+ findReplace: {
516
+ find,
517
+ replacement,
518
+ ...options
519
+ }
520
+ }
521
+ ]);
522
+ return result.replies?.[0]?.findReplace || {};
523
+ }
524
+
525
+ // Sort operations
526
+
527
+ async sortRange(
528
+ spreadsheetId: string,
529
+ range: GridRange,
530
+ sortSpecs: {
531
+ dimensionIndex?: number;
532
+ sortOrder?: 'ASCENDING' | 'DESCENDING';
533
+ }[]
534
+ ): Promise<void> {
535
+ await this.batchUpdate(spreadsheetId, [
536
+ {
537
+ sortRange: { range, sortSpecs }
538
+ }
539
+ ]);
540
+ }
541
+
542
+ // Protected ranges
543
+
544
+ async addProtectedRange(
545
+ spreadsheetId: string,
546
+ range: GridRange,
547
+ options?: {
548
+ description?: string;
549
+ warningOnly?: boolean;
550
+ editors?: {
551
+ users?: string[];
552
+ groups?: string[];
553
+ domainUsersCanEdit?: boolean;
554
+ };
555
+ }
556
+ ): Promise<number | undefined> {
557
+ let result = await this.batchUpdate(spreadsheetId, [
558
+ {
559
+ addProtectedRange: {
560
+ protectedRange: {
561
+ range,
562
+ ...options
563
+ }
564
+ }
565
+ }
566
+ ]);
567
+ return result.replies?.[0]?.addProtectedRange?.protectedRange?.protectedRangeId;
568
+ }
569
+
570
+ async deleteProtectedRange(spreadsheetId: string, protectedRangeId: number): Promise<void> {
571
+ await this.batchUpdate(spreadsheetId, [
572
+ {
573
+ deleteProtectedRange: { protectedRangeId }
574
+ }
575
+ ]);
576
+ }
577
+
578
+ // Named ranges
579
+
580
+ async addNamedRange(
581
+ spreadsheetId: string,
582
+ name: string,
583
+ range: GridRange
584
+ ): Promise<string | undefined> {
585
+ let result = await this.batchUpdate(spreadsheetId, [
586
+ {
587
+ addNamedRange: {
588
+ namedRange: { name, range }
589
+ }
590
+ }
591
+ ]);
592
+ return result.replies?.[0]?.addNamedRange?.namedRange?.namedRangeId;
593
+ }
594
+
595
+ async deleteNamedRange(spreadsheetId: string, namedRangeId: string): Promise<void> {
596
+ await this.batchUpdate(spreadsheetId, [
597
+ {
598
+ deleteNamedRange: { namedRangeId }
599
+ }
600
+ ]);
601
+ }
602
+
603
+ // Data validation
604
+
605
+ async setDataValidation(
606
+ spreadsheetId: string,
607
+ range: GridRange,
608
+ rule: {
609
+ condition: {
610
+ type: string;
611
+ values?: { userEnteredValue?: string }[];
612
+ };
613
+ inputMessage?: string;
614
+ strict?: boolean;
615
+ showCustomUi?: boolean;
616
+ }
617
+ ): Promise<void> {
618
+ await this.batchUpdate(spreadsheetId, [
619
+ {
620
+ setDataValidation: { range, rule }
621
+ }
622
+ ]);
623
+ }
624
+
625
+ // Copy/Cut paste
626
+
627
+ async copyPaste(
628
+ spreadsheetId: string,
629
+ source: GridRange,
630
+ destination: GridRange,
631
+ pasteType?:
632
+ | 'PASTE_NORMAL'
633
+ | 'PASTE_VALUES'
634
+ | 'PASTE_FORMAT'
635
+ | 'PASTE_NO_BORDERS'
636
+ | 'PASTE_FORMULA'
637
+ | 'PASTE_DATA_VALIDATION'
638
+ | 'PASTE_CONDITIONAL_FORMATTING',
639
+ pasteOrientation?: 'NORMAL' | 'TRANSPOSE'
640
+ ): Promise<void> {
641
+ await this.batchUpdate(spreadsheetId, [
642
+ {
643
+ copyPaste: { source, destination, pasteType, pasteOrientation }
644
+ }
645
+ ]);
646
+ }
647
+
648
+ // Update spreadsheet properties
649
+
650
+ async updateSpreadsheetProperties(
651
+ spreadsheetId: string,
652
+ properties: Partial<SpreadsheetProperties>,
653
+ fields: string
654
+ ): Promise<void> {
655
+ await this.batchUpdate(spreadsheetId, [
656
+ {
657
+ updateSpreadsheetProperties: {
658
+ properties: properties as SpreadsheetProperties,
659
+ fields
660
+ }
661
+ }
662
+ ]);
663
+ }
664
+ }
665
+
666
+ // Drive client for watching file changes
667
+ export class DriveClient {
668
+ private axios;
669
+
670
+ constructor(token: string) {
671
+ this.axios = createAxios({
672
+ baseURL: 'https://www.googleapis.com/drive/v3'
673
+ });
674
+ this.axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
675
+ }
676
+
677
+ async watchFile(
678
+ fileId: string,
679
+ webhookUrl: string,
680
+ channelId: string
681
+ ): Promise<{
682
+ resourceId?: string;
683
+ resourceUri?: string;
684
+ expiration?: string;
685
+ }> {
686
+ let response = await this.axios.post(`/files/${fileId}/watch`, {
687
+ id: channelId,
688
+ type: 'web_hook',
689
+ address: webhookUrl,
690
+ expiration: Date.now() + 24 * 60 * 60 * 1000 // 24 hours max
691
+ });
692
+ return response.data;
693
+ }
694
+
695
+ async stopChannel(channelId: string, resourceId: string): Promise<void> {
696
+ await this.axios.post('/channels/stop', {
697
+ id: channelId,
698
+ resourceId
699
+ });
700
+ }
701
+
702
+ async getFile(fileId: string): Promise<{
703
+ id?: string;
704
+ name?: string;
705
+ mimeType?: string;
706
+ modifiedTime?: string;
707
+ createdTime?: string;
708
+ owners?: { emailAddress?: string; displayName?: string }[];
709
+ }> {
710
+ let response = await this.axios.get(`/files/${fileId}`, {
711
+ params: {
712
+ fields: 'id,name,mimeType,modifiedTime,createdTime,owners(emailAddress,displayName)'
713
+ }
714
+ });
715
+ return response.data;
716
+ }
717
+ }