@hasna/connectors 0.3.6 → 0.3.7

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/bin/index.js CHANGED
@@ -6701,7 +6701,7 @@ var PRESETS = {
6701
6701
  commerce: { description: "Commerce and finance", connectors: ["stripe", "shopify", "revolut", "mercury", "pandadoc"] }
6702
6702
  };
6703
6703
  var program2 = new Command;
6704
- program2.name("connectors").description("Install API connectors for your project").version("0.3.6");
6704
+ program2.name("connectors").description("Install API connectors for your project").version("0.3.7");
6705
6705
  program2.command("interactive", { isDefault: true }).alias("i").description("Interactive connector browser").action(() => {
6706
6706
  if (!isTTY) {
6707
6707
  console.log(`Non-interactive environment detected. Use a subcommand:
package/bin/mcp.js CHANGED
@@ -20309,7 +20309,7 @@ async function getConnectorCommandHelp(name, command) {
20309
20309
  loadConnectorVersions();
20310
20310
  var server = new McpServer({
20311
20311
  name: "connectors",
20312
- version: "0.3.6"
20312
+ version: "0.3.7"
20313
20313
  });
20314
20314
  server.registerTool("search_connectors", {
20315
20315
  title: "Search Connectors",
@@ -75,7 +75,11 @@ function getFormat(cmd: Command): OutputFormat {
75
75
 
76
76
  // Helper to check authentication
77
77
  function requireAuth(): Gmail {
78
- if (!isAuthenticated()) {
78
+ // isAuthenticated() checks for both accessToken and refreshToken.
79
+ // If accessToken is missing/expired but refreshToken exists, the client's
80
+ // getValidAccessToken() will handle the refresh automatically.
81
+ const tokens = loadTokens();
82
+ if (!tokens || (!tokens.accessToken && !tokens.refreshToken)) {
79
83
  error('Not authenticated. Run "connect-gmail auth login" first.');
80
84
  process.exit(1);
81
85
  }
@@ -5,6 +5,8 @@ import { Google } from '../api';
5
5
  import {
6
6
  getAccessToken,
7
7
  setAccessToken,
8
+ getRefreshToken,
9
+ getValidAccessToken,
8
10
  clearConfig,
9
11
  getConfigDir,
10
12
  setProfileOverride,
@@ -55,12 +57,26 @@ function getFormat(cmd: Command): OutputFormat {
55
57
  }
56
58
 
57
59
  // Helper to get authenticated client
58
- function getClient(): Google {
59
- const accessToken = getAccessToken();
60
+ async function getClient(): Promise<Google> {
61
+ let accessToken = getAccessToken();
62
+
63
+ // If no access token, try to refresh using refresh token
60
64
  if (!accessToken) {
61
- error(`No access token configured. Run "${CONNECTOR_NAME} config set-token <token>" or set GOOGLE_ACCESS_TOKEN environment variable.`);
62
- process.exit(1);
65
+ const refreshToken = getRefreshToken();
66
+ if (refreshToken) {
67
+ try {
68
+ accessToken = await getValidAccessToken();
69
+ } catch {
70
+ // Fall through to error below
71
+ }
72
+ }
73
+
74
+ if (!accessToken) {
75
+ error(`No access token configured. Run "${CONNECTOR_NAME} config set-token <token>" or set GOOGLE_ACCESS_TOKEN environment variable.`);
76
+ process.exit(1);
77
+ }
63
78
  }
79
+
64
80
  return new Google({ accessToken });
65
81
  }
66
82
 
@@ -208,7 +224,7 @@ gmailMessagesCmd
208
224
  .option('--labels <labels>', 'Label IDs (comma-separated)')
209
225
  .action(async (opts) => {
210
226
  try {
211
- const client = getClient();
227
+ const client = await getClient();
212
228
  const result = await client.gmail.listMessages({
213
229
  maxResults: parseInt(opts.max),
214
230
  q: opts.query,
@@ -227,7 +243,7 @@ gmailMessagesCmd
227
243
  .option('--format <format>', 'Message format (minimal, full, raw, metadata)', 'full')
228
244
  .action(async (id: string, opts) => {
229
245
  try {
230
- const client = getClient();
246
+ const client = await getClient();
231
247
  const result = await client.gmail.getMessage(id, { format: opts.format });
232
248
  print(result, getFormat(gmailMessagesCmd));
233
249
  } catch (err) {
@@ -247,7 +263,7 @@ gmailMessagesCmd
247
263
  .option('--html', 'Send as HTML email')
248
264
  .action(async (opts) => {
249
265
  try {
250
- const client = getClient();
266
+ const client = await getClient();
251
267
  const result = await client.gmail.sendMessage({
252
268
  to: opts.to,
253
269
  subject: opts.subject,
@@ -269,7 +285,7 @@ gmailMessagesCmd
269
285
  .description('Delete a message permanently')
270
286
  .action(async (id: string) => {
271
287
  try {
272
- const client = getClient();
288
+ const client = await getClient();
273
289
  await client.gmail.deleteMessage(id);
274
290
  success(`Message ${id} deleted`);
275
291
  } catch (err) {
@@ -283,7 +299,7 @@ gmailMessagesCmd
283
299
  .description('Move a message to trash')
284
300
  .action(async (id: string) => {
285
301
  try {
286
- const client = getClient();
302
+ const client = await getClient();
287
303
  await client.gmail.trashMessage(id);
288
304
  success(`Message ${id} moved to trash`);
289
305
  } catch (err) {
@@ -297,7 +313,7 @@ gmailMessagesCmd
297
313
  .description('Remove a message from trash')
298
314
  .action(async (id: string) => {
299
315
  try {
300
- const client = getClient();
316
+ const client = await getClient();
301
317
  await client.gmail.untrashMessage(id);
302
318
  success(`Message ${id} removed from trash`);
303
319
  } catch (err) {
@@ -316,7 +332,7 @@ gmailLabelsCmd
316
332
  .description('List all labels')
317
333
  .action(async () => {
318
334
  try {
319
- const client = getClient();
335
+ const client = await getClient();
320
336
  const result = await client.gmail.listLabels();
321
337
  print(result, getFormat(gmailLabelsCmd));
322
338
  } catch (err) {
@@ -330,7 +346,7 @@ gmailLabelsCmd
330
346
  .description('Get a label by ID')
331
347
  .action(async (id: string) => {
332
348
  try {
333
- const client = getClient();
349
+ const client = await getClient();
334
350
  const result = await client.gmail.getLabel(id);
335
351
  print(result, getFormat(gmailLabelsCmd));
336
352
  } catch (err) {
@@ -344,7 +360,7 @@ gmailLabelsCmd
344
360
  .description('Create a new label')
345
361
  .action(async (name: string) => {
346
362
  try {
347
- const client = getClient();
363
+ const client = await getClient();
348
364
  const result = await client.gmail.createLabel(name);
349
365
  success('Label created!');
350
366
  print(result, getFormat(gmailLabelsCmd));
@@ -359,7 +375,7 @@ gmailLabelsCmd
359
375
  .description('Delete a label')
360
376
  .action(async (id: string) => {
361
377
  try {
362
- const client = getClient();
378
+ const client = await getClient();
363
379
  await client.gmail.deleteLabel(id);
364
380
  success(`Label ${id} deleted`);
365
381
  } catch (err) {
@@ -379,7 +395,7 @@ gmailDraftsCmd
379
395
  .option('-n, --max <number>', 'Maximum results', '10')
380
396
  .action(async (opts) => {
381
397
  try {
382
- const client = getClient();
398
+ const client = await getClient();
383
399
  const result = await client.gmail.listDrafts({
384
400
  maxResults: parseInt(opts.max),
385
401
  });
@@ -395,7 +411,7 @@ gmailDraftsCmd
395
411
  .description('Get a draft by ID')
396
412
  .action(async (id: string) => {
397
413
  try {
398
- const client = getClient();
414
+ const client = await getClient();
399
415
  const result = await client.gmail.getDraft(id);
400
416
  print(result, getFormat(gmailDraftsCmd));
401
417
  } catch (err) {
@@ -412,7 +428,7 @@ gmailDraftsCmd
412
428
  .requiredOption('--body <body>', 'Email body')
413
429
  .action(async (opts) => {
414
430
  try {
415
- const client = getClient();
431
+ const client = await getClient();
416
432
  const result = await client.gmail.createDraft({
417
433
  to: opts.to,
418
434
  subject: opts.subject,
@@ -431,7 +447,7 @@ gmailDraftsCmd
431
447
  .description('Delete a draft')
432
448
  .action(async (id: string) => {
433
449
  try {
434
- const client = getClient();
450
+ const client = await getClient();
435
451
  await client.gmail.deleteDraft(id);
436
452
  success(`Draft ${id} deleted`);
437
453
  } catch (err) {
@@ -445,7 +461,7 @@ gmailDraftsCmd
445
461
  .description('Send a draft')
446
462
  .action(async (id: string) => {
447
463
  try {
448
- const client = getClient();
464
+ const client = await getClient();
449
465
  const result = await client.gmail.sendDraft(id);
450
466
  success('Draft sent!');
451
467
  print(result, getFormat(gmailDraftsCmd));
@@ -475,7 +491,7 @@ driveFilesCmd
475
491
  .option('--folder <id>', 'List files in folder')
476
492
  .action(async (opts) => {
477
493
  try {
478
- const client = getClient();
494
+ const client = await getClient();
479
495
  let result;
480
496
  if (opts.folder) {
481
497
  result = await client.drive.listFilesInFolder(opts.folder, {
@@ -499,7 +515,7 @@ driveFilesCmd
499
515
  .description('Get file metadata')
500
516
  .action(async (id: string) => {
501
517
  try {
502
- const client = getClient();
518
+ const client = await getClient();
503
519
  const result = await client.drive.getFile(id);
504
520
  print(result, getFormat(driveFilesCmd));
505
521
  } catch (err) {
@@ -517,7 +533,7 @@ driveFilesCmd
517
533
  .option('--content <content>', 'File content')
518
534
  .action(async (opts) => {
519
535
  try {
520
- const client = getClient();
536
+ const client = await getClient();
521
537
  const result = await client.drive.createFile({
522
538
  name: opts.name,
523
539
  parents: opts.parent ? [opts.parent] : undefined,
@@ -538,7 +554,7 @@ driveFilesCmd
538
554
  .option('--parent <id>', 'Parent folder ID')
539
555
  .action(async (name: string, opts) => {
540
556
  try {
541
- const client = getClient();
557
+ const client = await getClient();
542
558
  const result = await client.drive.createFolder(name, {
543
559
  parents: opts.parent ? [opts.parent] : undefined,
544
560
  });
@@ -558,7 +574,7 @@ driveFilesCmd
558
574
  .option('--starred', 'Star the file')
559
575
  .action(async (id: string, opts) => {
560
576
  try {
561
- const client = getClient();
577
+ const client = await getClient();
562
578
  const result = await client.drive.updateFile(id, {
563
579
  name: opts.name,
564
580
  description: opts.description,
@@ -577,7 +593,7 @@ driveFilesCmd
577
593
  .description('Delete a file permanently')
578
594
  .action(async (id: string) => {
579
595
  try {
580
- const client = getClient();
596
+ const client = await getClient();
581
597
  await client.drive.deleteFile(id);
582
598
  success(`File ${id} deleted`);
583
599
  } catch (err) {
@@ -591,7 +607,7 @@ driveFilesCmd
591
607
  .description('Move a file to trash')
592
608
  .action(async (id: string) => {
593
609
  try {
594
- const client = getClient();
610
+ const client = await getClient();
595
611
  await client.drive.trashFile(id);
596
612
  success(`File ${id} moved to trash`);
597
613
  } catch (err) {
@@ -606,7 +622,7 @@ driveFilesCmd
606
622
  .option('--name <name>', 'New name for the copy')
607
623
  .action(async (id: string, opts) => {
608
624
  try {
609
- const client = getClient();
625
+ const client = await getClient();
610
626
  const result = await client.drive.copyFile(id, { name: opts.name });
611
627
  success('File copied!');
612
628
  print(result, getFormat(driveFilesCmd));
@@ -626,7 +642,7 @@ drivePermissionsCmd
626
642
  .description('List permissions for a file')
627
643
  .action(async (fileId: string) => {
628
644
  try {
629
- const client = getClient();
645
+ const client = await getClient();
630
646
  const result = await client.drive.listPermissions(fileId);
631
647
  print(result, getFormat(drivePermissionsCmd));
632
648
  } catch (err) {
@@ -645,7 +661,7 @@ drivePermissionsCmd
645
661
  .option('--notify', 'Send notification email')
646
662
  .action(async (fileId: string, opts) => {
647
663
  try {
648
- const client = getClient();
664
+ const client = await getClient();
649
665
  const result = await client.drive.createPermission(fileId, {
650
666
  type: opts.type,
651
667
  role: opts.role,
@@ -666,7 +682,7 @@ drivePermissionsCmd
666
682
  .description('Remove a permission')
667
683
  .action(async (fileId: string, permissionId: string) => {
668
684
  try {
669
- const client = getClient();
685
+ const client = await getClient();
670
686
  await client.drive.deletePermission(fileId, permissionId);
671
687
  success('Permission deleted');
672
688
  } catch (err) {
@@ -692,7 +708,7 @@ calendarListCmd
692
708
  .description('List calendars')
693
709
  .action(async () => {
694
710
  try {
695
- const client = getClient();
711
+ const client = await getClient();
696
712
  const result = await client.calendar.listCalendars();
697
713
  print(result, getFormat(calendarListCmd));
698
714
  } catch (err) {
@@ -706,7 +722,7 @@ calendarListCmd
706
722
  .description('Get a calendar')
707
723
  .action(async (id: string) => {
708
724
  try {
709
- const client = getClient();
725
+ const client = await getClient();
710
726
  const result = await client.calendar.getCalendar(id);
711
727
  print(result, getFormat(calendarListCmd));
712
728
  } catch (err) {
@@ -722,7 +738,7 @@ calendarListCmd
722
738
  .option('--timezone <tz>', 'Time zone')
723
739
  .action(async (summary: string, opts) => {
724
740
  try {
725
- const client = getClient();
741
+ const client = await getClient();
726
742
  const result = await client.calendar.createCalendar(summary, {
727
743
  description: opts.description,
728
744
  timeZone: opts.timezone,
@@ -740,7 +756,7 @@ calendarListCmd
740
756
  .description('Delete a calendar')
741
757
  .action(async (id: string) => {
742
758
  try {
743
- const client = getClient();
759
+ const client = await getClient();
744
760
  await client.calendar.deleteCalendar(id);
745
761
  success(`Calendar ${id} deleted`);
746
762
  } catch (err) {
@@ -763,7 +779,7 @@ calendarEventsCmd
763
779
  .option('-q, --query <query>', 'Search query')
764
780
  .action(async (calendarId: string = 'primary', opts) => {
765
781
  try {
766
- const client = getClient();
782
+ const client = await getClient();
767
783
  const result = await client.calendar.listEvents(calendarId, {
768
784
  maxResults: parseInt(opts.max),
769
785
  timeMin: opts.from,
@@ -784,7 +800,7 @@ calendarEventsCmd
784
800
  .description('List today\'s events')
785
801
  .action(async (calendarId: string = 'primary') => {
786
802
  try {
787
- const client = getClient();
803
+ const client = await getClient();
788
804
  const result = await client.calendar.getTodayEvents(calendarId);
789
805
  print(result, getFormat(calendarEventsCmd));
790
806
  } catch (err) {
@@ -798,7 +814,7 @@ calendarEventsCmd
798
814
  .description('List this week\'s events')
799
815
  .action(async (calendarId: string = 'primary') => {
800
816
  try {
801
- const client = getClient();
817
+ const client = await getClient();
802
818
  const result = await client.calendar.getWeekEvents(calendarId);
803
819
  print(result, getFormat(calendarEventsCmd));
804
820
  } catch (err) {
@@ -812,7 +828,7 @@ calendarEventsCmd
812
828
  .description('Get an event')
813
829
  .action(async (eventId: string, calendarId: string = 'primary') => {
814
830
  try {
815
- const client = getClient();
831
+ const client = await getClient();
816
832
  const result = await client.calendar.getEvent(calendarId, eventId);
817
833
  print(result, getFormat(calendarEventsCmd));
818
834
  } catch (err) {
@@ -833,7 +849,7 @@ calendarEventsCmd
833
849
  .option('--attendees <emails>', 'Attendee emails (comma-separated)')
834
850
  .action(async (calendarId: string = 'primary', opts) => {
835
851
  try {
836
- const client = getClient();
852
+ const client = await getClient();
837
853
  let result;
838
854
 
839
855
  if (opts.date) {
@@ -873,7 +889,7 @@ calendarEventsCmd
873
889
  .description('Quick add an event using natural language')
874
890
  .action(async (text: string, calendarId: string = 'primary') => {
875
891
  try {
876
- const client = getClient();
892
+ const client = await getClient();
877
893
  const result = await client.calendar.quickAddEvent(calendarId, text);
878
894
  success('Event created!');
879
895
  print(result, getFormat(calendarEventsCmd));
@@ -891,7 +907,7 @@ calendarEventsCmd
891
907
  .option('--location <location>', 'Event location')
892
908
  .action(async (eventId: string, calendarId: string = 'primary', opts) => {
893
909
  try {
894
- const client = getClient();
910
+ const client = await getClient();
895
911
  const result = await client.calendar.updateEvent(calendarId, eventId, {
896
912
  summary: opts.summary,
897
913
  description: opts.description,
@@ -910,7 +926,7 @@ calendarEventsCmd
910
926
  .description('Delete an event')
911
927
  .action(async (eventId: string, calendarId: string = 'primary') => {
912
928
  try {
913
- const client = getClient();
929
+ const client = await getClient();
914
930
  await client.calendar.deleteEvent(calendarId, eventId);
915
931
  success('Event deleted');
916
932
  } catch (err) {
@@ -931,7 +947,7 @@ docsCmd
931
947
  .description('Create a new document')
932
948
  .action(async (title: string) => {
933
949
  try {
934
- const client = getClient();
950
+ const client = await getClient();
935
951
  const result = await client.docs.createDocument({ title });
936
952
  success('Document created!');
937
953
  print(result, getFormat(docsCmd));
@@ -946,7 +962,7 @@ docsCmd
946
962
  .description('Get a document')
947
963
  .action(async (documentId: string) => {
948
964
  try {
949
- const client = getClient();
965
+ const client = await getClient();
950
966
  const result = await client.docs.getDocument(documentId);
951
967
  print(result, getFormat(docsCmd));
952
968
  } catch (err) {
@@ -960,7 +976,7 @@ docsCmd
960
976
  .description('Read document content as plain text')
961
977
  .action(async (documentId: string) => {
962
978
  try {
963
- const client = getClient();
979
+ const client = await getClient();
964
980
  const doc = await client.docs.getDocument(documentId);
965
981
  const text = client.docs.extractPlainText(doc);
966
982
  console.log(text);
@@ -975,7 +991,7 @@ docsCmd
975
991
  .description('Append text to a document')
976
992
  .action(async (documentId: string, text: string) => {
977
993
  try {
978
- const client = getClient();
994
+ const client = await getClient();
979
995
  await client.docs.appendText(documentId, text);
980
996
  success('Text appended to document');
981
997
  } catch (err) {
@@ -992,7 +1008,7 @@ docsCmd
992
1008
  .option('--match-case', 'Case-sensitive matching')
993
1009
  .action(async (documentId: string, opts) => {
994
1010
  try {
995
- const client = getClient();
1011
+ const client = await getClient();
996
1012
  const result = await client.docs.replaceAllText(documentId, opts.find, opts.replace, opts.matchCase);
997
1013
  success('Text replaced');
998
1014
  print(result, getFormat(docsCmd));
@@ -1010,7 +1026,7 @@ docsCmd
1010
1026
  .option('--height <height>', 'Image height in points')
1011
1027
  .action(async (documentId: string, imageUri: string, opts) => {
1012
1028
  try {
1013
- const client = getClient();
1029
+ const client = await getClient();
1014
1030
  await client.docs.insertImage(documentId, imageUri, {
1015
1031
  index: opts.index ? parseInt(opts.index) : undefined,
1016
1032
  width: opts.width ? parseInt(opts.width) : undefined,
@@ -1031,7 +1047,7 @@ docsCmd
1031
1047
  .option('--index <index>', 'Insert position')
1032
1048
  .action(async (documentId: string, opts) => {
1033
1049
  try {
1034
- const client = getClient();
1050
+ const client = await getClient();
1035
1051
  await client.docs.insertTable(documentId, parseInt(opts.rows), parseInt(opts.cols), {
1036
1052
  index: opts.index ? parseInt(opts.index) : undefined,
1037
1053
  });
@@ -1054,7 +1070,7 @@ sheetsCmd
1054
1070
  .description('Create a new spreadsheet')
1055
1071
  .action(async (title: string) => {
1056
1072
  try {
1057
- const client = getClient();
1073
+ const client = await getClient();
1058
1074
  const result = await client.sheets.createSpreadsheet({ title });
1059
1075
  success('Spreadsheet created!');
1060
1076
  print(result, getFormat(sheetsCmd));
@@ -1069,7 +1085,7 @@ sheetsCmd
1069
1085
  .description('Get spreadsheet metadata')
1070
1086
  .action(async (spreadsheetId: string) => {
1071
1087
  try {
1072
- const client = getClient();
1088
+ const client = await getClient();
1073
1089
  const result = await client.sheets.getSpreadsheetMetadata(spreadsheetId);
1074
1090
  print(result, getFormat(sheetsCmd));
1075
1091
  } catch (err) {
@@ -1083,7 +1099,7 @@ sheetsCmd
1083
1099
  .description('List sheet names in a spreadsheet')
1084
1100
  .action(async (spreadsheetId: string) => {
1085
1101
  try {
1086
- const client = getClient();
1102
+ const client = await getClient();
1087
1103
  const names = await client.sheets.getSheetNames(spreadsheetId);
1088
1104
  print(names, getFormat(sheetsCmd));
1089
1105
  } catch (err) {
@@ -1097,7 +1113,7 @@ sheetsCmd
1097
1113
  .description('Read values from a range')
1098
1114
  .action(async (spreadsheetId: string, range: string) => {
1099
1115
  try {
1100
- const client = getClient();
1116
+ const client = await getClient();
1101
1117
  const result = await client.sheets.getValues(spreadsheetId, range);
1102
1118
  print(result, getFormat(sheetsCmd));
1103
1119
  } catch (err) {
@@ -1112,7 +1128,7 @@ sheetsCmd
1112
1128
  .requiredOption('--values <json>', 'Values as JSON array (e.g., \'[["A", "B"], ["1", "2"]]\')')
1113
1129
  .action(async (spreadsheetId: string, range: string, opts) => {
1114
1130
  try {
1115
- const client = getClient();
1131
+ const client = await getClient();
1116
1132
  const values = JSON.parse(opts.values);
1117
1133
  const result = await client.sheets.updateValues(spreadsheetId, range, values);
1118
1134
  success('Values written!');
@@ -1129,7 +1145,7 @@ sheetsCmd
1129
1145
  .requiredOption('--values <json>', 'Values as JSON array')
1130
1146
  .action(async (spreadsheetId: string, range: string, opts) => {
1131
1147
  try {
1132
- const client = getClient();
1148
+ const client = await getClient();
1133
1149
  const values = JSON.parse(opts.values);
1134
1150
  const result = await client.sheets.appendValues(spreadsheetId, range, values);
1135
1151
  success('Values appended!');
@@ -1146,7 +1162,7 @@ sheetsCmd
1146
1162
  .requiredOption('--row <json>', 'Row values as JSON array (e.g., \'["value1", "value2"]\')')
1147
1163
  .action(async (spreadsheetId: string, sheetName: string, opts) => {
1148
1164
  try {
1149
- const client = getClient();
1165
+ const client = await getClient();
1150
1166
  const row = JSON.parse(opts.row);
1151
1167
  const result = await client.sheets.appendRow(spreadsheetId, sheetName, row);
1152
1168
  success('Row appended!');
@@ -1162,7 +1178,7 @@ sheetsCmd
1162
1178
  .description('Clear values from a range')
1163
1179
  .action(async (spreadsheetId: string, range: string) => {
1164
1180
  try {
1165
- const client = getClient();
1181
+ const client = await getClient();
1166
1182
  const result = await client.sheets.clearValues(spreadsheetId, range);
1167
1183
  success('Values cleared!');
1168
1184
  print(result, getFormat(sheetsCmd));
@@ -1177,7 +1193,7 @@ sheetsCmd
1177
1193
  .description('Get a single cell value')
1178
1194
  .action(async (spreadsheetId: string, sheetName: string, cell: string) => {
1179
1195
  try {
1180
- const client = getClient();
1196
+ const client = await getClient();
1181
1197
  const value = await client.sheets.getCellValue(spreadsheetId, sheetName, cell);
1182
1198
  console.log(value);
1183
1199
  } catch (err) {
@@ -1191,7 +1207,7 @@ sheetsCmd
1191
1207
  .description('Set a single cell value')
1192
1208
  .action(async (spreadsheetId: string, sheetName: string, cell: string, value: string) => {
1193
1209
  try {
1194
- const client = getClient();
1210
+ const client = await getClient();
1195
1211
  await client.sheets.setCellValue(spreadsheetId, sheetName, cell, value);
1196
1212
  success('Cell value set!');
1197
1213
  } catch (err) {
@@ -1205,7 +1221,7 @@ sheetsCmd
1205
1221
  .description('Get a row by index (1-based)')
1206
1222
  .action(async (spreadsheetId: string, sheetName: string, rowIndex: string) => {
1207
1223
  try {
1208
- const client = getClient();
1224
+ const client = await getClient();
1209
1225
  const row = await client.sheets.getRow(spreadsheetId, sheetName, parseInt(rowIndex));
1210
1226
  print(row, getFormat(sheetsCmd));
1211
1227
  } catch (err) {
@@ -1219,7 +1235,7 @@ sheetsCmd
1219
1235
  .description('Get a column by letter')
1220
1236
  .action(async (spreadsheetId: string, sheetName: string, column: string) => {
1221
1237
  try {
1222
- const client = getClient();
1238
+ const client = await getClient();
1223
1239
  const col = await client.sheets.getColumn(spreadsheetId, sheetName, column);
1224
1240
  print(col, getFormat(sheetsCmd));
1225
1241
  } catch (err) {
@@ -66,22 +66,17 @@ function getFormat(cmd: Command): OutputFormat {
66
66
  async function getClient(): Promise<GoogleCalendar> {
67
67
  let accessToken = getAccessToken();
68
68
 
69
- if (!accessToken) {
70
- error(`No access token configured. Run "${CONNECTOR_NAME} auth login" to authenticate or set GOOGLE_CALENDAR_ACCESS_TOKEN environment variable.`);
71
- process.exit(1);
72
- }
73
-
74
- // Check if token is expired and we have refresh token
75
- if (isTokenExpired()) {
69
+ // If no access token or token is expired, try to refresh using refresh token
70
+ if (!accessToken || isTokenExpired()) {
76
71
  const refreshToken = getRefreshToken();
77
72
  const clientId = getClientId();
78
73
  const clientSecret = getClientSecret();
79
74
 
80
75
  if (refreshToken && clientId && clientSecret) {
81
- info('Access token expired, refreshing...');
76
+ info(accessToken ? 'Access token expired, refreshing...' : 'No access token, attempting refresh...');
82
77
  try {
83
78
  const client = new GoogleCalendar({
84
- accessToken,
79
+ accessToken: accessToken || '',
85
80
  refreshToken,
86
81
  clientId,
87
82
  clientSecret,
@@ -94,6 +89,12 @@ async function getClient(): Promise<GoogleCalendar> {
94
89
  warn(`Failed to refresh token: ${err}. You may need to re-authenticate.`);
95
90
  }
96
91
  }
92
+
93
+ // After refresh attempt, if still no access token, exit
94
+ if (!accessToken) {
95
+ error(`No access token configured. Run "${CONNECTOR_NAME} auth login" to authenticate or set GOOGLE_CALENDAR_ACCESS_TOKEN environment variable.`);
96
+ process.exit(1);
97
+ }
97
98
  }
98
99
 
99
100
  const refreshToken = getRefreshToken();
@@ -62,10 +62,10 @@ function getFormat(cmd: Command): OutputFormat {
62
62
  }
63
63
 
64
64
  // Helper to get authenticated client
65
- function getClient(): GoogleContacts {
65
+ async function getClient(): Promise<GoogleContacts> {
66
66
  const clientId = getClientId();
67
67
  const clientSecret = getClientSecret();
68
- const accessToken = getAccessToken();
68
+ let accessToken = getAccessToken();
69
69
  const refreshToken = getRefreshToken();
70
70
  const redirectUri = getRedirectUri();
71
71
 
@@ -74,9 +74,34 @@ function getClient(): GoogleContacts {
74
74
  process.exit(1);
75
75
  }
76
76
 
77
+ // If no access token, try to refresh using refresh token
77
78
  if (!accessToken) {
78
- error(`No access token. Run "${CONNECTOR_NAME} auth login" to authenticate.`);
79
- process.exit(1);
79
+ if (refreshToken) {
80
+ try {
81
+ info('No access token, attempting refresh...');
82
+ const client = new GoogleContacts({
83
+ clientId,
84
+ clientSecret,
85
+ accessToken: '',
86
+ refreshToken,
87
+ redirectUri,
88
+ });
89
+ const tokens = await client.refreshAccessToken();
90
+ saveTokens({
91
+ accessToken: tokens.accessToken,
92
+ refreshToken: tokens.refreshToken,
93
+ expiresIn: tokens.expiresIn,
94
+ });
95
+ accessToken = tokens.accessToken;
96
+ success('Token refreshed successfully');
97
+ } catch (err) {
98
+ error(`Failed to refresh token: ${err}. Run "${CONNECTOR_NAME} auth login" to re-authenticate.`);
99
+ process.exit(1);
100
+ }
101
+ } else {
102
+ error(`No access token. Run "${CONNECTOR_NAME} auth login" to authenticate.`);
103
+ process.exit(1);
104
+ }
80
105
  }
81
106
 
82
107
  return new GoogleContacts({
@@ -462,7 +487,7 @@ contactsCmd
462
487
  .option('--normalize', 'Output in normalized format')
463
488
  .action(async (opts) => {
464
489
  try {
465
- const client = getClient();
490
+ const client = await getClient();
466
491
  const result = await client.contacts.list({
467
492
  pageSize: parseInt(opts.max),
468
493
  pageToken: opts.pageToken,
@@ -491,7 +516,7 @@ contactsCmd
491
516
  .option('--normalize', 'Output in normalized format')
492
517
  .action(async (resourceName: string, opts) => {
493
518
  try {
494
- const client = getClient();
519
+ const client = await getClient();
495
520
  const result = await client.contacts.get(resourceName);
496
521
 
497
522
  if (opts.normalize) {
@@ -516,7 +541,7 @@ contactsCmd
516
541
  .option('--title <title>', 'Job title')
517
542
  .action(async (opts) => {
518
543
  try {
519
- const client = getClient();
544
+ const client = await getClient();
520
545
  const result = await client.contacts.create({
521
546
  givenName: opts.givenName,
522
547
  familyName: opts.familyName,
@@ -547,7 +572,7 @@ contactsCmd
547
572
  .option('--title <title>', 'Job title')
548
573
  .action(async (resourceName: string, opts) => {
549
574
  try {
550
- const client = getClient();
575
+ const client = await getClient();
551
576
  const result = await client.contacts.update(resourceName, {
552
577
  givenName: opts.givenName,
553
578
  familyName: opts.familyName,
@@ -572,7 +597,7 @@ contactsCmd
572
597
  .description('Delete a contact')
573
598
  .action(async (resourceName: string) => {
574
599
  try {
575
- const client = getClient();
600
+ const client = await getClient();
576
601
  await client.contacts.delete(resourceName);
577
602
  success(`Contact ${resourceName} deleted.`);
578
603
  } catch (err) {
@@ -588,7 +613,7 @@ contactsCmd
588
613
  .option('--normalize', 'Output in normalized format')
589
614
  .action(async (query: string, opts) => {
590
615
  try {
591
- const client = getClient();
616
+ const client = await getClient();
592
617
  const result = await client.contacts.search({
593
618
  query,
594
619
  pageSize: parseInt(opts.max),
@@ -613,7 +638,7 @@ contactsCmd
613
638
  .option('--normalize', 'Export in normalized format')
614
639
  .action(async (opts) => {
615
640
  try {
616
- const client = getClient();
641
+ const client = await getClient();
617
642
  const file = Bun.file(opts.output);
618
643
  const writer = file.writer();
619
644
 
@@ -641,7 +666,7 @@ contactsCmd
641
666
  .option('-n, --max <number>', 'Maximum results', '100')
642
667
  .action(async (opts) => {
643
668
  try {
644
- const client = getClient();
669
+ const client = await getClient();
645
670
  const result = await client.contacts.listGroups(parseInt(opts.max));
646
671
  print(result, getFormat(contactsCmd));
647
672
  } catch (err) {
@@ -7,6 +7,8 @@ import {
7
7
  setApiKey,
8
8
  getAccessToken,
9
9
  setAccessToken,
10
+ getRefreshToken,
11
+ getValidAccessToken,
10
12
  clearConfig,
11
13
  getConfigDir,
12
14
  setProfileOverride,
@@ -60,13 +62,27 @@ function getFormat(cmd: Command): OutputFormat {
60
62
  }
61
63
 
62
64
  // Helper to get authenticated client
63
- function getClient(): GoogleDocs {
64
- const accessToken = getAccessToken();
65
+ async function getClient(): Promise<GoogleDocs> {
66
+ let accessToken = getAccessToken();
65
67
  const apiKey = getApiKey();
68
+
69
+ // If no access token, try to refresh using refresh token
66
70
  if (!accessToken && !apiKey) {
67
- error(`No credentials configured. Run "${CONNECTOR_NAME} config set-token <token>" or set GOOGLE_ACCESS_TOKEN environment variable.`);
68
- process.exit(1);
71
+ const refreshToken = getRefreshToken();
72
+ if (refreshToken) {
73
+ try {
74
+ accessToken = await getValidAccessToken();
75
+ } catch {
76
+ // Fall through to error below
77
+ }
78
+ }
79
+
80
+ if (!accessToken) {
81
+ error(`No credentials configured. Run "${CONNECTOR_NAME} config set-token <token>" or set GOOGLE_ACCESS_TOKEN environment variable.`);
82
+ process.exit(1);
83
+ }
69
84
  }
85
+
70
86
  return new GoogleDocs({ accessToken, apiKey });
71
87
  }
72
88
 
@@ -215,7 +231,7 @@ program
215
231
  .description('Get a document by ID')
216
232
  .action(async (documentId: string) => {
217
233
  try {
218
- const client = getClient();
234
+ const client = await getClient();
219
235
  const result = await client.documents.get(documentId);
220
236
  print(result, getFormat(program));
221
237
  } catch (err) {
@@ -229,7 +245,7 @@ program
229
245
  .description('Create a new document (requires OAuth token)')
230
246
  .action(async (title: string) => {
231
247
  try {
232
- const client = getClient();
248
+ const client = await getClient();
233
249
  if (!client.hasWriteAccess()) {
234
250
  error('Creating documents requires an OAuth access token. API key provides read-only access.');
235
251
  process.exit(1);
@@ -248,7 +264,7 @@ program
248
264
  .description('Append text to the end of a document (requires OAuth token)')
249
265
  .action(async (documentId: string, text: string) => {
250
266
  try {
251
- const client = getClient();
267
+ const client = await getClient();
252
268
  if (!client.hasWriteAccess()) {
253
269
  error('Modifying documents requires an OAuth access token. API key provides read-only access.');
254
270
  process.exit(1);
@@ -268,7 +284,7 @@ program
268
284
  .option('--match-case', 'Match case when finding text')
269
285
  .action(async (documentId: string, find: string, replace: string, opts) => {
270
286
  try {
271
- const client = getClient();
287
+ const client = await getClient();
272
288
  if (!client.hasWriteAccess()) {
273
289
  error('Modifying documents requires an OAuth access token. API key provides read-only access.');
274
290
  process.exit(1);
@@ -292,7 +308,7 @@ program
292
308
  .description('Insert text at a specific position (requires OAuth token)')
293
309
  .action(async (documentId: string, text: string, index: string) => {
294
310
  try {
295
- const client = getClient();
311
+ const client = await getClient();
296
312
  if (!client.hasWriteAccess()) {
297
313
  error('Modifying documents requires an OAuth access token. API key provides read-only access.');
298
314
  process.exit(1);
@@ -316,7 +332,7 @@ program
316
332
  .description('Delete content within a range (requires OAuth token)')
317
333
  .action(async (documentId: string, startIndex: string, endIndex: string) => {
318
334
  try {
319
- const client = getClient();
335
+ const client = await getClient();
320
336
  if (!client.hasWriteAccess()) {
321
337
  error('Modifying documents requires an OAuth access token. API key provides read-only access.');
322
338
  process.exit(1);
@@ -341,7 +357,7 @@ program
341
357
  .description('Insert an image at a specific position (requires OAuth token)')
342
358
  .action(async (documentId: string, uri: string, index: string) => {
343
359
  try {
344
- const client = getClient();
360
+ const client = await getClient();
345
361
  if (!client.hasWriteAccess()) {
346
362
  error('Modifying documents requires an OAuth access token. API key provides read-only access.');
347
363
  process.exit(1);
@@ -56,7 +56,11 @@ function getFormat(cmd: Command): OutputFormat {
56
56
  }
57
57
 
58
58
  function requireAuth(): Drive {
59
- if (!isAuthenticated()) {
59
+ // isAuthenticated() checks for both accessToken and refreshToken.
60
+ // If accessToken is missing/expired but refreshToken exists, the client's
61
+ // getValidAccessToken() will handle the refresh automatically.
62
+ const tokens = loadTokens();
63
+ if (!tokens || (!tokens.accessToken && !tokens.refreshToken)) {
60
64
  error('Not authenticated. Run "connect-googledrive auth login" first.');
61
65
  process.exit(1);
62
66
  }
@@ -67,16 +67,29 @@ function getFormat(cmd: Command): OutputFormat {
67
67
  }
68
68
 
69
69
  // Helper to get authenticated client
70
- function getClient(): GoogleSheets {
70
+ async function getClient(): Promise<GoogleSheets> {
71
71
  const apiKey = getApiKey();
72
- const accessToken = getAccessToken();
72
+ let accessToken = getAccessToken();
73
73
  const refreshToken = getRefreshToken();
74
74
  const clientId = getClientId();
75
75
  const clientSecret = getClientSecret();
76
76
 
77
+ // If no API key and no access token, try to refresh using refresh token
77
78
  if (!apiKey && !accessToken) {
78
- error(`No credentials configured. Run "${CONNECTOR_NAME} config set-key <key>" for API key auth or "${CONNECTOR_NAME} config set-token <token>" for OAuth.`);
79
- process.exit(1);
79
+ if (refreshToken && clientId && clientSecret) {
80
+ try {
81
+ info('No access token, attempting refresh...');
82
+ const tempClient = new GoogleSheets({ refreshToken, clientId, clientSecret });
83
+ accessToken = await tempClient.refreshAccessToken();
84
+ success('Token refreshed successfully');
85
+ } catch (err) {
86
+ error(`Failed to refresh token: ${err}. Run "${CONNECTOR_NAME} config set-token <token>" to re-authenticate.`);
87
+ process.exit(1);
88
+ }
89
+ } else {
90
+ error(`No credentials configured. Run "${CONNECTOR_NAME} config set-key <key>" for API key auth or "${CONNECTOR_NAME} config set-token <token>" for OAuth.`);
91
+ process.exit(1);
92
+ }
80
93
  }
81
94
 
82
95
  return new GoogleSheets({
@@ -265,7 +278,7 @@ program
265
278
  .option('--formulas', 'Return formulas instead of calculated values')
266
279
  .action(async (spreadsheetId: string, range: string, opts) => {
267
280
  try {
268
- const client = getClient();
281
+ const client = await getClient();
269
282
  const valueRenderOption = opts.formulas ? 'FORMULA' : opts.raw ? 'UNFORMATTED_VALUE' : 'FORMATTED_VALUE';
270
283
 
271
284
  const result = await client.values.get(spreadsheetId, range, {
@@ -285,7 +298,7 @@ program
285
298
  .option('--raw', 'Use RAW input (no formula parsing)')
286
299
  .action(async (spreadsheetId: string, range: string, valuesStr: string, opts) => {
287
300
  try {
288
- const client = getClient();
301
+ const client = await getClient();
289
302
 
290
303
  if (client.isApiKeyAuth()) {
291
304
  error('Writing requires OAuth authentication. Use "config set-token" to configure OAuth.');
@@ -314,7 +327,7 @@ program
314
327
  .option('--overwrite', 'Overwrite existing data instead of inserting rows')
315
328
  .action(async (spreadsheetId: string, range: string, valuesStr: string, opts) => {
316
329
  try {
317
- const client = getClient();
330
+ const client = await getClient();
318
331
 
319
332
  if (client.isApiKeyAuth()) {
320
333
  error('Writing requires OAuth authentication. Use "config set-token" to configure OAuth.');
@@ -345,7 +358,7 @@ program
345
358
  .option('--timezone <tz>', 'Spreadsheet timezone (e.g., "America/New_York")')
346
359
  .action(async (title: string, opts) => {
347
360
  try {
348
- const client = getClient();
361
+ const client = await getClient();
349
362
 
350
363
  if (client.isApiKeyAuth()) {
351
364
  error('Creating spreadsheets requires OAuth authentication. Use "config set-token" to configure OAuth.');
@@ -372,7 +385,7 @@ program
372
385
  .description('List all sheets in a spreadsheet')
373
386
  .action(async (spreadsheetId: string) => {
374
387
  try {
375
- const client = getClient();
388
+ const client = await getClient();
376
389
  const spreadsheet = await client.spreadsheets.get(spreadsheetId);
377
390
 
378
391
  console.log(chalk.bold(`Spreadsheet: ${spreadsheet.properties.title}`));
@@ -404,7 +417,7 @@ program
404
417
  .description('Get spreadsheet metadata')
405
418
  .action(async (spreadsheetId: string) => {
406
419
  try {
407
- const client = getClient();
420
+ const client = await getClient();
408
421
  const spreadsheet = await client.spreadsheets.get(spreadsheetId);
409
422
 
410
423
  print(spreadsheet, getFormat(program));
@@ -419,7 +432,7 @@ program
419
432
  .description('Clear values from a range')
420
433
  .action(async (spreadsheetId: string, range: string) => {
421
434
  try {
422
- const client = getClient();
435
+ const client = await getClient();
423
436
 
424
437
  if (client.isApiKeyAuth()) {
425
438
  error('Clearing values requires OAuth authentication. Use "config set-token" to configure OAuth.');
@@ -448,7 +461,7 @@ sheetCmd
448
461
  .option('--index <index>', 'Position to insert the sheet')
449
462
  .action(async (spreadsheetId: string, title: string, opts) => {
450
463
  try {
451
- const client = getClient();
464
+ const client = await getClient();
452
465
 
453
466
  if (client.isApiKeyAuth()) {
454
467
  error('Adding sheets requires OAuth authentication.');
@@ -477,7 +490,7 @@ sheetCmd
477
490
  .description('Delete a sheet from a spreadsheet')
478
491
  .action(async (spreadsheetId: string, sheetIdStr: string) => {
479
492
  try {
480
- const client = getClient();
493
+ const client = await getClient();
481
494
 
482
495
  if (client.isApiKeyAuth()) {
483
496
  error('Deleting sheets requires OAuth authentication.');
@@ -499,7 +512,7 @@ sheetCmd
499
512
  .description('Rename a sheet')
500
513
  .action(async (spreadsheetId: string, sheetIdStr: string, newTitle: string) => {
501
514
  try {
502
- const client = getClient();
515
+ const client = await getClient();
503
516
 
504
517
  if (client.isApiKeyAuth()) {
505
518
  error('Renaming sheets requires OAuth authentication.');
@@ -521,7 +534,7 @@ sheetCmd
521
534
  .description('Copy a sheet to another spreadsheet')
522
535
  .action(async (spreadsheetId: string, sheetIdStr: string, destSpreadsheetId: string) => {
523
536
  try {
524
- const client = getClient();
537
+ const client = await getClient();
525
538
 
526
539
  if (client.isApiKeyAuth()) {
527
540
  error('Copying sheets requires OAuth authentication.');
@@ -16,6 +16,7 @@ import {
16
16
  setTokens,
17
17
  getAccessToken,
18
18
  getRefreshToken,
19
+ isTokenExpired,
19
20
  clearTokens,
20
21
  loadProfile,
21
22
  } from '../utils/config';
@@ -40,11 +41,30 @@ function getFormat(cmd: Command): OutputFormat {
40
41
  }
41
42
 
42
43
  // Helper to get client
43
- function getClient(): GoogleTasksClient {
44
- const token = getAccessToken();
45
- if (!token) {
46
- throw new Error('Not authenticated. Run "connect-googletasks auth login" first.');
44
+ async function getClient(): Promise<GoogleTasksClient> {
45
+ let token = getAccessToken();
46
+
47
+ // If no access token or token is expired, try to refresh using refresh token
48
+ if (!token || isTokenExpired()) {
49
+ const refreshToken = getRefreshToken();
50
+ const clientId = getClientId();
51
+ const clientSecret = getClientSecret();
52
+
53
+ if (refreshToken && clientId && clientSecret) {
54
+ try {
55
+ const tokens = await GoogleTasksClient.refreshAccessToken(refreshToken, clientId, clientSecret);
56
+ setTokens(tokens.access_token, tokens.refresh_token, tokens.expires_in);
57
+ token = tokens.access_token;
58
+ } catch {
59
+ // Fall through to error below if refresh fails
60
+ }
61
+ }
62
+
63
+ if (!token) {
64
+ throw new Error('Not authenticated. Run "connect-googletasks auth login" first.');
65
+ }
47
66
  }
67
+
48
68
  return new GoogleTasksClient(token);
49
69
  }
50
70
 
@@ -307,7 +327,7 @@ listsCmd
307
327
  .description('List all task lists')
308
328
  .action(async function(this: Command) {
309
329
  try {
310
- const client = getClient();
330
+ const client = await getClient();
311
331
  const response = await client.listTaskLists();
312
332
  printTaskLists(response.items || [], getFormat(this));
313
333
  } catch (err) {
@@ -321,7 +341,7 @@ listsCmd
321
341
  .description('Get a task list by ID')
322
342
  .action(async function(this: Command, listId: string) {
323
343
  try {
324
- const client = getClient();
344
+ const client = await getClient();
325
345
  const list = await client.getTaskList(listId);
326
346
  printTaskList(list, getFormat(this));
327
347
  } catch (err) {
@@ -335,7 +355,7 @@ listsCmd
335
355
  .description('Create a new task list')
336
356
  .action(async function(this: Command, title: string) {
337
357
  try {
338
- const client = getClient();
358
+ const client = await getClient();
339
359
  const list = await client.createTaskList({ title });
340
360
  success(`Task list "${list.title}" created`);
341
361
  printTaskList(list, getFormat(this));
@@ -350,7 +370,7 @@ listsCmd
350
370
  .description('Rename a task list')
351
371
  .action(async function(this: Command, listId: string, title: string) {
352
372
  try {
353
- const client = getClient();
373
+ const client = await getClient();
354
374
  const list = await client.updateTaskList(listId, { title });
355
375
  success(`Task list renamed to "${list.title}"`);
356
376
  } catch (err) {
@@ -364,7 +384,7 @@ listsCmd
364
384
  .description('Delete a task list')
365
385
  .action(async function(this: Command, listId: string) {
366
386
  try {
367
- const client = getClient();
387
+ const client = await getClient();
368
388
  await client.deleteTaskList(listId);
369
389
  success('Task list deleted');
370
390
  } catch (err) {
@@ -389,7 +409,7 @@ tasksCmd
389
409
  .option('--max <number>', 'Maximum number of tasks', '100')
390
410
  .action(async function(this: Command, listId: string, opts) {
391
411
  try {
392
- const client = getClient();
412
+ const client = await getClient();
393
413
  const response = await client.listTasks(listId, {
394
414
  maxResults: parseInt(opts.max),
395
415
  showCompleted: opts.all || opts.completed,
@@ -408,7 +428,7 @@ tasksCmd
408
428
  .description('Get a task by ID')
409
429
  .action(async function(this: Command, listId: string, taskId: string) {
410
430
  try {
411
- const client = getClient();
431
+ const client = await getClient();
412
432
  const task = await client.getTask(listId, taskId);
413
433
  printTask(task, getFormat(this));
414
434
  } catch (err) {
@@ -424,7 +444,7 @@ tasksCmd
424
444
  .option('-d, --due <date>', 'Due date (YYYY-MM-DD)')
425
445
  .action(async function(this: Command, listId: string, title: string, opts) {
426
446
  try {
427
- const client = getClient();
447
+ const client = await getClient();
428
448
  const task = await client.createTask(listId, {
429
449
  title,
430
450
  notes: opts.notes,
@@ -446,7 +466,7 @@ tasksCmd
446
466
  .option('-d, --due <date>', 'New due date (YYYY-MM-DD)')
447
467
  .action(async function(this: Command, listId: string, taskId: string, opts) {
448
468
  try {
449
- const client = getClient();
469
+ const client = await getClient();
450
470
  const task = await client.updateTask(listId, taskId, {
451
471
  title: opts.title,
452
472
  notes: opts.notes,
@@ -466,7 +486,7 @@ tasksCmd
466
486
  .description('Mark a task as completed')
467
487
  .action(async function(this: Command, listId: string, taskId: string) {
468
488
  try {
469
- const client = getClient();
489
+ const client = await getClient();
470
490
  const task = await client.completeTask(listId, taskId);
471
491
  success(`Task "${task.title}" marked as completed`);
472
492
  } catch (err) {
@@ -481,7 +501,7 @@ tasksCmd
481
501
  .description('Mark a task as not completed')
482
502
  .action(async function(this: Command, listId: string, taskId: string) {
483
503
  try {
484
- const client = getClient();
504
+ const client = await getClient();
485
505
  const task = await client.uncompleteTask(listId, taskId);
486
506
  success(`Task "${task.title}" marked as needs action`);
487
507
  } catch (err) {
@@ -496,7 +516,7 @@ tasksCmd
496
516
  .description('Delete a task')
497
517
  .action(async function(this: Command, listId: string, taskId: string) {
498
518
  try {
499
- const client = getClient();
519
+ const client = await getClient();
500
520
  await client.deleteTask(listId, taskId);
501
521
  success('Task deleted');
502
522
  } catch (err) {
@@ -512,7 +532,7 @@ tasksCmd
512
532
  .option('--after <taskId>', 'Position after this task')
513
533
  .action(async function(this: Command, listId: string, taskId: string, opts) {
514
534
  try {
515
- const client = getClient();
535
+ const client = await getClient();
516
536
  const task = await client.moveTask(listId, taskId, {
517
537
  parent: opts.parent,
518
538
  previous: opts.after,
@@ -529,7 +549,7 @@ tasksCmd
529
549
  .description('Clear all completed tasks from a list')
530
550
  .action(async function(this: Command, listId: string) {
531
551
  try {
532
- const client = getClient();
552
+ const client = await getClient();
533
553
  await client.clearCompleted(listId);
534
554
  success('Completed tasks cleared');
535
555
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/connectors",
3
- "version": "0.3.6",
3
+ "version": "0.3.7",
4
4
  "description": "Open source connector library - Install API connectors with a single command",
5
5
  "type": "module",
6
6
  "bin": {