google-workspace-mcp 2.0.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 (75) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +765 -0
  3. package/dist/accounts.d.ts +85 -0
  4. package/dist/accounts.d.ts.map +1 -0
  5. package/dist/accounts.js +520 -0
  6. package/dist/accounts.js.map +1 -0
  7. package/dist/auth.d.ts +4 -0
  8. package/dist/auth.d.ts.map +1 -0
  9. package/dist/auth.js +206 -0
  10. package/dist/auth.js.map +1 -0
  11. package/dist/cli.d.ts +3 -0
  12. package/dist/cli.d.ts.map +1 -0
  13. package/dist/cli.js +426 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/errorHelpers.d.ts +40 -0
  16. package/dist/errorHelpers.d.ts.map +1 -0
  17. package/dist/errorHelpers.js +52 -0
  18. package/dist/errorHelpers.js.map +1 -0
  19. package/dist/googleDocsApiHelpers.d.ts +118 -0
  20. package/dist/googleDocsApiHelpers.d.ts.map +1 -0
  21. package/dist/googleDocsApiHelpers.js +850 -0
  22. package/dist/googleDocsApiHelpers.js.map +1 -0
  23. package/dist/googleSheetsApiHelpers.d.ts +75 -0
  24. package/dist/googleSheetsApiHelpers.d.ts.map +1 -0
  25. package/dist/googleSheetsApiHelpers.js +376 -0
  26. package/dist/googleSheetsApiHelpers.js.map +1 -0
  27. package/dist/server.d.ts +2 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +119 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/serverWrapper.d.ts +21 -0
  32. package/dist/serverWrapper.d.ts.map +1 -0
  33. package/dist/serverWrapper.js +74 -0
  34. package/dist/serverWrapper.js.map +1 -0
  35. package/dist/tools/accounts.tools.d.ts +3 -0
  36. package/dist/tools/accounts.tools.d.ts.map +1 -0
  37. package/dist/tools/accounts.tools.js +154 -0
  38. package/dist/tools/accounts.tools.js.map +1 -0
  39. package/dist/tools/calendar.tools.d.ts +3 -0
  40. package/dist/tools/calendar.tools.d.ts.map +1 -0
  41. package/dist/tools/calendar.tools.js +487 -0
  42. package/dist/tools/calendar.tools.js.map +1 -0
  43. package/dist/tools/docs.tools.d.ts +3 -0
  44. package/dist/tools/docs.tools.d.ts.map +1 -0
  45. package/dist/tools/docs.tools.js +1766 -0
  46. package/dist/tools/docs.tools.js.map +1 -0
  47. package/dist/tools/drive.tools.d.ts +3 -0
  48. package/dist/tools/drive.tools.d.ts.map +1 -0
  49. package/dist/tools/drive.tools.js +1001 -0
  50. package/dist/tools/drive.tools.js.map +1 -0
  51. package/dist/tools/forms.tools.d.ts +3 -0
  52. package/dist/tools/forms.tools.d.ts.map +1 -0
  53. package/dist/tools/forms.tools.js +370 -0
  54. package/dist/tools/forms.tools.js.map +1 -0
  55. package/dist/tools/gmail.tools.d.ts +3 -0
  56. package/dist/tools/gmail.tools.d.ts.map +1 -0
  57. package/dist/tools/gmail.tools.js +520 -0
  58. package/dist/tools/gmail.tools.js.map +1 -0
  59. package/dist/tools/sheets.tools.d.ts +3 -0
  60. package/dist/tools/sheets.tools.d.ts.map +1 -0
  61. package/dist/tools/sheets.tools.js +521 -0
  62. package/dist/tools/sheets.tools.js.map +1 -0
  63. package/dist/tools/slides.tools.d.ts +3 -0
  64. package/dist/tools/slides.tools.d.ts.map +1 -0
  65. package/dist/tools/slides.tools.js +323 -0
  66. package/dist/tools/slides.tools.js.map +1 -0
  67. package/dist/types.d.ts +507 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +185 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/urlHelpers.d.ts +60 -0
  72. package/dist/urlHelpers.d.ts.map +1 -0
  73. package/dist/urlHelpers.js +101 -0
  74. package/dist/urlHelpers.js.map +1 -0
  75. package/package.json +77 -0
@@ -0,0 +1,85 @@
1
+ import { type docs_v1, type drive_v3, type sheets_v4, type gmail_v1, type calendar_v3, type slides_v1, type forms_v1 } from 'googleapis';
2
+ import { type OAuth2Client } from 'google-auth-library';
3
+ export interface AccountConfig {
4
+ name: string;
5
+ email?: string;
6
+ tokenPath: string;
7
+ credentialsPath?: string;
8
+ addedAt: string;
9
+ }
10
+ export interface AccountsConfig {
11
+ accounts: Record<string, AccountConfig | undefined>;
12
+ credentialsPath: string;
13
+ }
14
+ export interface AccountClients {
15
+ authClient: OAuth2Client;
16
+ docs: docs_v1.Docs;
17
+ drive: drive_v3.Drive;
18
+ sheets: sheets_v4.Sheets;
19
+ gmail: gmail_v1.Gmail;
20
+ calendar: calendar_v3.Calendar;
21
+ slides: slides_v1.Slides;
22
+ forms: forms_v1.Forms;
23
+ }
24
+ /**
25
+ * Initialize the accounts system - validates config and tokens exist
26
+ */
27
+ export declare function initializeAccounts(): Promise<void>;
28
+ /**
29
+ * Get the API clients for a specific account
30
+ */
31
+ export declare function getAccountClients(accountName: string): Promise<AccountClients>;
32
+ /**
33
+ * List all configured accounts
34
+ */
35
+ export declare function listAccounts(): Promise<AccountConfig[]>;
36
+ /**
37
+ * Check if any accounts are configured
38
+ */
39
+ export declare function hasAccounts(): Promise<boolean>;
40
+ /**
41
+ * Get token info including scopes for an account
42
+ */
43
+ export declare function getTokenInfo(accountName: string): Promise<{
44
+ email?: string;
45
+ scopes?: string[];
46
+ expiry_date?: number;
47
+ access_token_preview?: string;
48
+ }>;
49
+ /**
50
+ * Add a new account via OAuth flow
51
+ * Returns the auth URL that user needs to visit
52
+ * @param accountName - Name for the account
53
+ * @param credentialsPath - Optional path to a credentials.json file for this account
54
+ */
55
+ export declare function startAddAccount(accountName: string, credentialsPath?: string): Promise<{
56
+ authUrl: string;
57
+ port: number;
58
+ credentialsPath?: string;
59
+ }>;
60
+ /**
61
+ * Complete the OAuth flow by listening for the callback
62
+ * @param accountName - Name for the account
63
+ * @param port - Port number for the OAuth callback server
64
+ * @param credentialsPath - Optional path to a credentials.json file for this account
65
+ * @param onAuthUrl - Optional callback to receive the auth URL
66
+ */
67
+ export declare function completeAddAccount(accountName: string, port: number, credentialsPath?: string, onAuthUrl?: (url: string) => void): Promise<AccountConfig>;
68
+ /**
69
+ * Remove an account
70
+ */
71
+ export declare function removeAccount(accountName: string): Promise<void>;
72
+ /**
73
+ * Get the config directory path (for display purposes)
74
+ */
75
+ export declare function getConfigDir(): string;
76
+ /**
77
+ * Get credentials path (for setup instructions)
78
+ */
79
+ export declare function getCredentialsPath(): string;
80
+ /**
81
+ * Get the email address associated with an account
82
+ * Returns the stored email if available, otherwise returns the account name as fallback
83
+ */
84
+ export declare function getAccountEmail(accountName: string): Promise<string>;
85
+ //# sourceMappingURL=accounts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.d.ts","sourceRoot":"","sources":["../src/accounts.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,QAAQ,EACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,qBAAqB,CAAC;AAyB1E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAC,CAAC;IACpD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,YAAY,CAAC;IACzB,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;IACnB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;IACtB,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;IACzB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;IACtB,QAAQ,EAAE,WAAW,CAAC,QAAQ,CAAC;IAC/B,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC;IACzB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC;CACvB;AAgKD;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAyBxD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAiCpF;AAED;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAG7D;AAED;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC,CAGpD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B,CAAC,CAgCD;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,WAAW,EAAE,MAAM,EACnB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CA0DtE;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,eAAe,CAAC,EAAE,MAAM,EACxB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAChC,OAAO,CAAC,aAAa,CAAC,CA4IxB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBtE;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB1E"}
@@ -0,0 +1,520 @@
1
+ // src/accounts.ts
2
+ // Multi-account management for Google Workspace MCP Server
3
+ import { google, } from 'googleapis';
4
+ import * as fs from 'fs/promises';
5
+ import * as path from 'path';
6
+ import * as http from 'http';
7
+ // --- Configuration paths ---
8
+ const CONFIG_DIR = path.join(process.env.HOME || '~', '.google-mcp');
9
+ const ACCOUNTS_CONFIG_PATH = path.join(CONFIG_DIR, 'accounts.json');
10
+ const CREDENTIALS_PATH = path.join(CONFIG_DIR, 'credentials.json');
11
+ const CREDENTIALS_DIR = path.join(CONFIG_DIR, 'credentials');
12
+ const TOKENS_DIR = path.join(CONFIG_DIR, 'tokens');
13
+ const SCOPES = [
14
+ 'https://www.googleapis.com/auth/documents',
15
+ 'https://www.googleapis.com/auth/drive',
16
+ 'https://www.googleapis.com/auth/spreadsheets',
17
+ 'https://www.googleapis.com/auth/gmail.modify',
18
+ 'https://www.googleapis.com/auth/calendar',
19
+ 'https://www.googleapis.com/auth/presentations',
20
+ 'https://www.googleapis.com/auth/forms.body',
21
+ 'https://www.googleapis.com/auth/forms.responses.readonly',
22
+ ];
23
+ // --- No in-memory caching - always read fresh from disk ---
24
+ // --- Helper Functions ---
25
+ async function ensureConfigDir() {
26
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- CONFIG_DIR and TOKENS_DIR are derived from known safe paths
27
+ await fs.mkdir(CONFIG_DIR, { recursive: true });
28
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- TOKENS_DIR is derived from known safe paths
29
+ await fs.mkdir(TOKENS_DIR, { recursive: true });
30
+ }
31
+ /** Type guard for Node.js file system errors */
32
+ function isNodeError(error) {
33
+ return error instanceof Error && 'code' in error;
34
+ }
35
+ async function loadAccountsConfig() {
36
+ try {
37
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- ACCOUNTS_CONFIG_PATH is derived from known safe paths
38
+ const content = await fs.readFile(ACCOUNTS_CONFIG_PATH, 'utf8');
39
+ return JSON.parse(content);
40
+ }
41
+ catch (err) {
42
+ if (isNodeError(err) && err.code === 'ENOENT') {
43
+ // Create default config
44
+ const defaultConfig = {
45
+ accounts: {},
46
+ credentialsPath: CREDENTIALS_PATH,
47
+ };
48
+ await saveAccountsConfig(defaultConfig);
49
+ return defaultConfig;
50
+ }
51
+ throw err;
52
+ }
53
+ }
54
+ async function saveAccountsConfig(config) {
55
+ await ensureConfigDir();
56
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- ACCOUNTS_CONFIG_PATH is derived from known safe paths
57
+ await fs.writeFile(ACCOUNTS_CONFIG_PATH, JSON.stringify(config, null, 2));
58
+ }
59
+ async function fileExists(filePath) {
60
+ try {
61
+ await fs.access(filePath);
62
+ return true;
63
+ }
64
+ catch {
65
+ return false;
66
+ }
67
+ }
68
+ /** Parse OAuth credentials from a file path */
69
+ async function parseCredentialsFile(credPath) {
70
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- credPath is validated or from known config paths
71
+ const content = await fs.readFile(credPath, 'utf8');
72
+ const keys = JSON.parse(content);
73
+ const key = keys.installed ?? keys.web;
74
+ if (!key)
75
+ throw new Error(`Could not find client secrets in ${credPath}.`);
76
+ return {
77
+ client_id: key.client_id,
78
+ client_secret: key.client_secret,
79
+ };
80
+ }
81
+ async function loadCredentials(accountName) {
82
+ const config = await loadAccountsConfig();
83
+ let credPath;
84
+ // Priority: 1) Account-specific credentials, 2) Global credentials
85
+ if (accountName) {
86
+ // eslint-disable-next-line security/detect-object-injection -- accountName is validated with regex /^[a-zA-Z0-9_-]+$/
87
+ const account = config.accounts[accountName];
88
+ // Check for explicit per-account credentials path in config
89
+ if (account?.credentialsPath && (await fileExists(account.credentialsPath))) {
90
+ credPath = account.credentialsPath;
91
+ }
92
+ // Check for credentials in the credentials directory by account name
93
+ else {
94
+ const accountCredPath = path.join(CREDENTIALS_DIR, `${accountName}.json`);
95
+ if (await fileExists(accountCredPath)) {
96
+ credPath = accountCredPath;
97
+ }
98
+ else {
99
+ // Fall back to global credentials
100
+ credPath = config.credentialsPath || CREDENTIALS_PATH;
101
+ }
102
+ }
103
+ }
104
+ else {
105
+ // No account specified, use global credentials
106
+ credPath = config.credentialsPath || CREDENTIALS_PATH;
107
+ }
108
+ try {
109
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- credPath is from validated config or known paths
110
+ const content = await fs.readFile(credPath, 'utf8');
111
+ const keys = JSON.parse(content);
112
+ const key = keys.installed ?? keys.web;
113
+ if (!key)
114
+ throw new Error(`Could not find client secrets in ${credPath}.`);
115
+ return {
116
+ client_id: key.client_id,
117
+ client_secret: key.client_secret,
118
+ redirect_uris: key.redirect_uris ?? ['http://localhost:3000'],
119
+ };
120
+ }
121
+ catch (err) {
122
+ if (isNodeError(err) && err.code === 'ENOENT') {
123
+ throw new Error(`Credentials file not found at ${credPath}. Please copy your OAuth credentials.json to this location.`);
124
+ }
125
+ throw err;
126
+ }
127
+ }
128
+ async function loadTokenForAccount(accountName) {
129
+ const config = await loadAccountsConfig();
130
+ // eslint-disable-next-line security/detect-object-injection -- accountName is validated with regex /^[a-zA-Z0-9_-]+$/
131
+ const account = config.accounts[accountName];
132
+ if (!account) {
133
+ return null;
134
+ }
135
+ try {
136
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- tokenPath is from validated account config
137
+ const tokenContent = await fs.readFile(account.tokenPath, 'utf8');
138
+ const credentials = JSON.parse(tokenContent);
139
+ // Use account-specific credentials if available
140
+ const { client_id, client_secret, redirect_uris } = await loadCredentials(accountName);
141
+ const client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
142
+ client.setCredentials(credentials);
143
+ return client;
144
+ }
145
+ catch {
146
+ return null;
147
+ }
148
+ }
149
+ async function saveTokenForAccount(accountName, client) {
150
+ await ensureConfigDir();
151
+ const tokenPath = path.join(TOKENS_DIR, `${accountName}.json`);
152
+ // Use account-specific credentials if available
153
+ const { client_id, client_secret } = await loadCredentials(accountName);
154
+ const payload = JSON.stringify({
155
+ type: 'authorized_user',
156
+ client_id,
157
+ client_secret,
158
+ refresh_token: client.credentials.refresh_token,
159
+ });
160
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- tokenPath is constructed from validated accountName and known TOKENS_DIR
161
+ await fs.writeFile(tokenPath, payload);
162
+ return tokenPath;
163
+ }
164
+ // --- Public API ---
165
+ /**
166
+ * Initialize the accounts system - validates config and tokens exist
167
+ */
168
+ export async function initializeAccounts() {
169
+ await ensureConfigDir();
170
+ const config = await loadAccountsConfig();
171
+ let validCount = 0;
172
+ // Validate all configured accounts have valid tokens
173
+ for (const [name, account] of Object.entries(config.accounts)) {
174
+ if (!account)
175
+ continue;
176
+ try {
177
+ const authClient = await loadTokenForAccount(name);
178
+ if (authClient) {
179
+ validCount++;
180
+ console.error(`Loaded account: ${name}${account.email ? ` (${account.email})` : ''}`);
181
+ }
182
+ else {
183
+ console.error(`Warning: Could not load token for account "${name}" - may need re-authentication`);
184
+ }
185
+ }
186
+ catch (err) {
187
+ const message = err instanceof Error ? err.message : String(err);
188
+ console.error(`Warning: Failed to load account "${name}": ${message}`);
189
+ }
190
+ }
191
+ console.error(`Accounts initialized: ${validCount} account(s) loaded`);
192
+ }
193
+ /**
194
+ * Get the API clients for a specific account
195
+ */
196
+ export async function getAccountClients(accountName) {
197
+ // Always load fresh from disk - no caching
198
+ const config = await loadAccountsConfig();
199
+ // eslint-disable-next-line security/detect-object-injection -- accountName is validated by caller
200
+ if (!config.accounts[accountName]) {
201
+ const available = Object.keys(config.accounts);
202
+ if (available.length === 0) {
203
+ throw new Error(`Account "${accountName}" not found. No accounts configured. Use the addAccount tool to add an account.`);
204
+ }
205
+ throw new Error(`Account "${accountName}" not found. Available accounts: ${available.join(', ')}`);
206
+ }
207
+ const authClient = await loadTokenForAccount(accountName);
208
+ if (!authClient) {
209
+ throw new Error(`Account "${accountName}" exists but token is invalid or missing. Use addAccount to re-authenticate.`);
210
+ }
211
+ return {
212
+ authClient,
213
+ docs: google.docs({ version: 'v1', auth: authClient }),
214
+ drive: google.drive({ version: 'v3', auth: authClient }),
215
+ sheets: google.sheets({ version: 'v4', auth: authClient }),
216
+ gmail: google.gmail({ version: 'v1', auth: authClient }),
217
+ calendar: google.calendar({ version: 'v3', auth: authClient }),
218
+ slides: google.slides({ version: 'v1', auth: authClient }),
219
+ forms: google.forms({ version: 'v1', auth: authClient }),
220
+ };
221
+ }
222
+ /**
223
+ * List all configured accounts
224
+ */
225
+ export async function listAccounts() {
226
+ const config = await loadAccountsConfig();
227
+ return Object.values(config.accounts).filter((a) => a !== undefined);
228
+ }
229
+ /**
230
+ * Check if any accounts are configured
231
+ */
232
+ export async function hasAccounts() {
233
+ const config = await loadAccountsConfig();
234
+ return Object.keys(config.accounts).length > 0;
235
+ }
236
+ /**
237
+ * Get token info including scopes for an account
238
+ */
239
+ export async function getTokenInfo(accountName) {
240
+ const clients = await getAccountClients(accountName);
241
+ const authClient = clients.authClient;
242
+ // Get the current credentials
243
+ const credentials = authClient.credentials;
244
+ // Try to get token info from Google
245
+ try {
246
+ const oauth2 = google.oauth2({ version: 'v2', auth: authClient });
247
+ const tokenInfo = await oauth2.tokeninfo({
248
+ access_token: credentials.access_token || undefined,
249
+ });
250
+ return {
251
+ email: tokenInfo.data.email || undefined,
252
+ scopes: tokenInfo.data.scope?.split(' ') ?? [],
253
+ expiry_date: credentials.expiry_date || undefined,
254
+ access_token_preview: credentials.access_token
255
+ ? `${credentials.access_token.substring(0, 20)}...`
256
+ : undefined,
257
+ };
258
+ }
259
+ catch (_error) {
260
+ // If tokeninfo fails, return what we have from credentials
261
+ return {
262
+ expiry_date: credentials.expiry_date || undefined,
263
+ access_token_preview: credentials.access_token
264
+ ? `${credentials.access_token.substring(0, 20)}...`
265
+ : undefined,
266
+ scopes: [], // Can't determine scopes without tokeninfo
267
+ };
268
+ }
269
+ }
270
+ /**
271
+ * Add a new account via OAuth flow
272
+ * Returns the auth URL that user needs to visit
273
+ * @param accountName - Name for the account
274
+ * @param credentialsPath - Optional path to a credentials.json file for this account
275
+ */
276
+ export async function startAddAccount(accountName, credentialsPath) {
277
+ const config = await loadAccountsConfig();
278
+ // Validate account name
279
+ if (!/^[a-zA-Z0-9_-]+$/.test(accountName)) {
280
+ throw new Error('Account name must contain only letters, numbers, underscores, and hyphens');
281
+ }
282
+ // eslint-disable-next-line security/detect-object-injection -- accountName is validated above with regex
283
+ if (config.accounts[accountName]) {
284
+ throw new Error(`Account "${accountName}" already exists. Use removeAccount first if you want to re-add it.`);
285
+ }
286
+ // If credentials path provided, verify it exists
287
+ if (credentialsPath && !(await fileExists(credentialsPath))) {
288
+ throw new Error(`Credentials file not found at ${credentialsPath}`);
289
+ }
290
+ // Temporarily store the credentials path for this account so loadCredentials can find it
291
+ // We'll do this by checking the credentials path directly or using account-name based lookup
292
+ let client_id, client_secret;
293
+ if (credentialsPath) {
294
+ // Load from the specified path
295
+ const parsed = await parseCredentialsFile(credentialsPath);
296
+ client_id = parsed.client_id;
297
+ client_secret = parsed.client_secret;
298
+ }
299
+ else {
300
+ // Check for account-specific credentials in the credentials directory
301
+ const accountCredPath = path.join(CREDENTIALS_DIR, `${accountName}.json`);
302
+ if (await fileExists(accountCredPath)) {
303
+ const parsed = await parseCredentialsFile(accountCredPath);
304
+ client_id = parsed.client_id;
305
+ client_secret = parsed.client_secret;
306
+ credentialsPath = accountCredPath;
307
+ }
308
+ else {
309
+ // Fall back to global credentials
310
+ const creds = await loadCredentials();
311
+ client_id = creds.client_id;
312
+ client_secret = creds.client_secret;
313
+ }
314
+ }
315
+ // Find an available port
316
+ const port = 3000 + Math.floor(Math.random() * 1000);
317
+ const redirectUri = `http://localhost:${port}`;
318
+ const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirectUri);
319
+ const authUrl = oAuth2Client.generateAuthUrl({
320
+ access_type: 'offline',
321
+ scope: SCOPES.join(' '),
322
+ prompt: 'consent', // Force consent to get refresh token
323
+ });
324
+ return { authUrl, port, credentialsPath };
325
+ }
326
+ /**
327
+ * Complete the OAuth flow by listening for the callback
328
+ * @param accountName - Name for the account
329
+ * @param port - Port number for the OAuth callback server
330
+ * @param credentialsPath - Optional path to a credentials.json file for this account
331
+ * @param onAuthUrl - Optional callback to receive the auth URL
332
+ */
333
+ export async function completeAddAccount(accountName, port, credentialsPath, onAuthUrl) {
334
+ // Load credentials for this account (using per-account if available)
335
+ let client_id, client_secret;
336
+ if (credentialsPath) {
337
+ const parsed = await parseCredentialsFile(credentialsPath);
338
+ client_id = parsed.client_id;
339
+ client_secret = parsed.client_secret;
340
+ }
341
+ else {
342
+ // Check for account-specific credentials
343
+ const accountCredPath = path.join(CREDENTIALS_DIR, `${accountName}.json`);
344
+ if (await fileExists(accountCredPath)) {
345
+ const parsed = await parseCredentialsFile(accountCredPath);
346
+ client_id = parsed.client_id;
347
+ client_secret = parsed.client_secret;
348
+ credentialsPath = accountCredPath;
349
+ }
350
+ else {
351
+ const creds = await loadCredentials();
352
+ client_id = creds.client_id;
353
+ client_secret = creds.client_secret;
354
+ }
355
+ }
356
+ const redirectUri = `http://localhost:${port}`;
357
+ const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirectUri);
358
+ const authUrl = oAuth2Client.generateAuthUrl({
359
+ access_type: 'offline',
360
+ scope: SCOPES.join(' '),
361
+ prompt: 'consent',
362
+ });
363
+ if (onAuthUrl) {
364
+ onAuthUrl(authUrl);
365
+ }
366
+ return new Promise((resolve, reject) => {
367
+ // Track connections so we can destroy them when closing
368
+ const connections = new Set();
369
+ // Timeout ID will be assigned after server is created
370
+ // Using object wrapper to allow const declaration while still being mutable inside closure
371
+ const timeout = {};
372
+ const server = http.createServer((req, res) => {
373
+ void (async () => {
374
+ try {
375
+ const url = new URL(req.url ?? '', redirectUri);
376
+ const code = url.searchParams.get('code');
377
+ if (code) {
378
+ res.writeHead(200, { 'Content-Type': 'text/html', Connection: 'close' });
379
+ res.end(`<html><body><h1>Authentication successful for "${accountName}"!</h1><p>You can close this window.</p></body></html>`);
380
+ // Close server, clear timeout, and destroy all connections
381
+ clearTimeout(timeout.id);
382
+ server.close();
383
+ connections.forEach((conn) => conn.destroy());
384
+ const { tokens } = await oAuth2Client.getToken(code);
385
+ oAuth2Client.setCredentials(tokens);
386
+ // Get user email
387
+ const oauth2 = google.oauth2({ version: 'v2', auth: oAuth2Client });
388
+ let email;
389
+ try {
390
+ const userInfo = await oauth2.userinfo.get();
391
+ email = userInfo.data.email || undefined;
392
+ }
393
+ catch {
394
+ // Email fetch failed, continue without it
395
+ }
396
+ // Save token
397
+ const tokenPath = await saveTokenForAccount(accountName, oAuth2Client);
398
+ // Update config - include credentialsPath if it was specified
399
+ const config = await loadAccountsConfig();
400
+ const accountConfig = {
401
+ name: accountName,
402
+ email,
403
+ tokenPath,
404
+ ...(credentialsPath && { credentialsPath }),
405
+ addedAt: new Date().toISOString(),
406
+ };
407
+ // eslint-disable-next-line security/detect-object-injection -- accountName validated at function entry
408
+ config.accounts[accountName] = accountConfig;
409
+ await saveAccountsConfig(config);
410
+ resolve(accountConfig);
411
+ }
412
+ else {
413
+ const error = url.searchParams.get('error');
414
+ res.writeHead(400, { 'Content-Type': 'text/html', Connection: 'close' });
415
+ res.end(`<html><body><h1>Authentication failed</h1><p>${error || 'No code received'}</p></body></html>`);
416
+ clearTimeout(timeout.id);
417
+ server.close();
418
+ connections.forEach((conn) => conn.destroy());
419
+ reject(new Error(error || 'No authorization code received'));
420
+ }
421
+ }
422
+ catch (err) {
423
+ res.writeHead(500, { 'Content-Type': 'text/html', Connection: 'close' });
424
+ res.end('<html><body><h1>Authentication failed</h1></body></html>');
425
+ clearTimeout(timeout.id);
426
+ server.close();
427
+ connections.forEach((conn) => conn.destroy());
428
+ reject(err instanceof Error ? err : new Error(String(err)));
429
+ }
430
+ })();
431
+ });
432
+ // Track connections so we can properly close them
433
+ server.on('connection', (conn) => {
434
+ connections.add(conn);
435
+ conn.on('close', () => connections.delete(conn));
436
+ });
437
+ server.listen(port, () => {
438
+ console.error(`OAuth callback server listening on port ${port}`);
439
+ });
440
+ server.on('error', (err) => {
441
+ if (err.code === 'EADDRINUSE') {
442
+ reject(new Error(`Port ${port} is in use. Please try again.`));
443
+ }
444
+ else {
445
+ reject(err);
446
+ }
447
+ });
448
+ // Timeout after 5 minutes
449
+ timeout.id = setTimeout(() => {
450
+ server.close();
451
+ connections.forEach((conn) => conn.destroy());
452
+ reject(new Error('Authentication timed out after 5 minutes'));
453
+ }, 5 * 60 * 1000);
454
+ });
455
+ }
456
+ /**
457
+ * Remove an account
458
+ */
459
+ export async function removeAccount(accountName) {
460
+ const config = await loadAccountsConfig();
461
+ // eslint-disable-next-line security/detect-object-injection -- accountName comes from user input but is used safely
462
+ const accountToRemove = config.accounts[accountName];
463
+ if (!accountToRemove) {
464
+ throw new Error(`Account "${accountName}" not found`);
465
+ }
466
+ // Remove token file
467
+ try {
468
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- tokenPath is from validated account config
469
+ await fs.unlink(accountToRemove.tokenPath);
470
+ }
471
+ catch {
472
+ // Ignore if file doesn't exist
473
+ }
474
+ // Remove from config using object rest spread instead of delete
475
+ const { [accountName]: _removed, ...remainingAccounts } = config.accounts;
476
+ config.accounts = remainingAccounts;
477
+ await saveAccountsConfig(config);
478
+ }
479
+ /**
480
+ * Get the config directory path (for display purposes)
481
+ */
482
+ export function getConfigDir() {
483
+ return CONFIG_DIR;
484
+ }
485
+ /**
486
+ * Get credentials path (for setup instructions)
487
+ */
488
+ export function getCredentialsPath() {
489
+ return CREDENTIALS_PATH;
490
+ }
491
+ /**
492
+ * Get the email address associated with an account
493
+ * Returns the stored email if available, otherwise returns the account name as fallback
494
+ */
495
+ export async function getAccountEmail(accountName) {
496
+ const config = await loadAccountsConfig();
497
+ // eslint-disable-next-line security/detect-object-injection -- accountName is validated by caller
498
+ const account = config.accounts[accountName];
499
+ if (account?.email) {
500
+ return account.email;
501
+ }
502
+ // Fallback: try to get email from token info
503
+ try {
504
+ const tokenInfo = await getTokenInfo(accountName);
505
+ if (tokenInfo.email) {
506
+ // Cache the email in the account config for future use
507
+ if (account) {
508
+ account.email = tokenInfo.email;
509
+ await saveAccountsConfig(config);
510
+ }
511
+ return tokenInfo.email;
512
+ }
513
+ }
514
+ catch {
515
+ // Ignore errors, use fallback
516
+ }
517
+ // Last resort fallback - return account name (won't work for authuser but better than nothing)
518
+ return accountName;
519
+ }
520
+ //# sourceMappingURL=accounts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accounts.js","sourceRoot":"","sources":["../src/accounts.ts"],"names":[],"mappings":"AAAA,kBAAkB;AAClB,2DAA2D;AAE3D,OAAO,EACL,MAAM,GAQP,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,8BAA8B;AAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,EAAE,aAAa,CAAC,CAAC;AACrE,MAAM,oBAAoB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AACpE,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AACnE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAEnD,MAAM,MAAM,GAAG;IACb,2CAA2C;IAC3C,uCAAuC;IACvC,8CAA8C;IAC9C,8CAA8C;IAC9C,0CAA0C;IAC1C,+CAA+C;IAC/C,4CAA4C;IAC5C,0DAA0D;CAC3D,CAAC;AA2BF,6DAA6D;AAE7D,2BAA2B;AAE3B,KAAK,UAAU,eAAe;IAC5B,kIAAkI;IAClI,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,kHAAkH;IAClH,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAClD,CAAC;AAED,gDAAgD;AAChD,SAAS,WAAW,CAAC,KAAc;IACjC,OAAO,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,CAAC;AACnD,CAAC;AAED,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC;QACH,4HAA4H;QAC5H,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAmB,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9C,wBAAwB;YACxB,MAAM,aAAa,GAAmB;gBACpC,QAAQ,EAAE,EAAE;gBACZ,eAAe,EAAE,gBAAgB;aAClC,CAAC;YACF,MAAM,kBAAkB,CAAC,aAAa,CAAC,CAAC;YACxC,OAAO,aAAa,CAAC;QACvB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,MAAsB;IACtD,MAAM,eAAe,EAAE,CAAC;IACxB,4HAA4H;IAC5H,MAAM,EAAE,CAAC,SAAS,CAAC,oBAAoB,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,+CAA+C;AAC/C,KAAK,UAAU,oBAAoB,CACjC,QAAgB;IAEhB,uHAAuH;IACvH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAyB,CAAC;IACzD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC;IACvC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,GAAG,CAAC,CAAC;IAC3E,OAAO;QACL,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,aAAa,EAAE,GAAG,CAAC,aAAa;KACjC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,WAAoB;IACjD,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,IAAI,QAAgB,CAAC;IAErB,mEAAmE;IACnE,IAAI,WAAW,EAAE,CAAC;QAChB,sHAAsH;QACtH,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAE7C,4DAA4D;QAC5D,IAAI,OAAO,EAAE,eAAe,IAAI,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;YAC5E,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC;QACrC,CAAC;QACD,qEAAqE;aAChE,CAAC;YACJ,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;YAC1E,IAAI,MAAM,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;gBACtC,QAAQ,GAAG,eAAe,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,kCAAkC;gBAClC,QAAQ,GAAG,MAAM,CAAC,eAAe,IAAI,gBAAgB,CAAC;YACxD,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,+CAA+C;QAC/C,QAAQ,GAAG,MAAM,CAAC,eAAe,IAAI,gBAAgB,CAAC;IACxD,CAAC;IAED,IAAI,CAAC;QACH,uHAAuH;QACvH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAyB,CAAC;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,CAAC;QACvC,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,QAAQ,GAAG,CAAC,CAAC;QAC3E,OAAO;YACL,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,aAAa,EAAE,GAAG,CAAC,aAAa;YAChC,aAAa,EAAE,GAAG,CAAC,aAAa,IAAI,CAAC,uBAAuB,CAAC;SAC9D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CACb,iCAAiC,QAAQ,6DAA6D,CACvG,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,WAAmB;IACpD,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,sHAAsH;IACtH,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,iHAAiH;QACjH,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAgB,CAAC;QAC5D,gDAAgD;QAChD,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;QAEvF,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,WAAmB,EAAE,MAAoB;IAC1E,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;IAE/D,gDAAgD;IAChD,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,eAAe,CAAC,WAAW,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,EAAE,iBAAiB;QACvB,SAAS;QACT,aAAa;QACb,aAAa,EAAE,MAAM,CAAC,WAAW,CAAC,aAAa;KAChD,CAAC,CAAC;IAEH,+IAA+I;IAC/I,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACvC,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,qBAAqB;AAErB;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,eAAe,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAE1C,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,qDAAqD;IACrD,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;YACnD,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,mBAAmB,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACxF,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,KAAK,CACX,8CAA8C,IAAI,gCAAgC,CACnF,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,OAAO,CAAC,KAAK,CAAC,oCAAoC,IAAI,MAAM,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;IACH,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,yBAAyB,UAAU,oBAAoB,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAAmB;IACzD,2CAA2C;IAC3C,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,kGAAkG;IAClG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,YAAY,WAAW,iFAAiF,CACzG,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CACb,YAAY,WAAW,oCAAoC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClF,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,YAAY,WAAW,8EAA8E,CACtG,CAAC;IACJ,CAAC;IAED,OAAO;QACL,UAAU;QACV,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QACtD,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QACxD,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QAC1D,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QACxD,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QAC9D,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QAC1D,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;KACzD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAsB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;AAC3F,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IAMpD,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,WAAW,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAEtC,8BAA8B;IAC9B,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;IAE3C,oCAAoC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QAClE,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC;YACvC,YAAY,EAAE,WAAW,CAAC,YAAY,IAAI,SAAS;SACpD,CAAC,CAAC;QAEH,OAAO;YACL,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS;YACxC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;YAC9C,WAAW,EAAE,WAAW,CAAC,WAAW,IAAI,SAAS;YACjD,oBAAoB,EAAE,WAAW,CAAC,YAAY;gBAC5C,CAAC,CAAC,GAAG,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK;gBACnD,CAAC,CAAC,SAAS;SACd,CAAC;IACJ,CAAC;IAAC,OAAO,MAAe,EAAE,CAAC;QACzB,2DAA2D;QAC3D,OAAO;YACL,WAAW,EAAE,WAAW,CAAC,WAAW,IAAI,SAAS;YACjD,oBAAoB,EAAE,WAAW,CAAC,YAAY;gBAC5C,CAAC,CAAC,GAAG,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK;gBACnD,CAAC,CAAC,SAAS;YACb,MAAM,EAAE,EAAE,EAAE,2CAA2C;SACxD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,eAAwB;IAExB,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAE1C,wBAAwB;IACxB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IAED,yGAAyG;IACzG,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,YAAY,WAAW,qEAAqE,CAC7F,CAAC;IACJ,CAAC;IAED,iDAAiD;IACjD,IAAI,eAAe,IAAI,CAAC,CAAC,MAAM,UAAU,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,iCAAiC,eAAe,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,yFAAyF;IACzF,6FAA6F;IAC7F,IAAI,SAAiB,EAAE,aAAqB,CAAC;IAE7C,IAAI,eAAe,EAAE,CAAC;QACpB,+BAA+B;QAC/B,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,eAAe,CAAC,CAAC;QAC3D,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAC7B,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,sEAAsE;QACtE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;QAC1E,IAAI,MAAM,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,eAAe,CAAC,CAAC;YAC3D,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YAC7B,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;YACrC,eAAe,GAAG,eAAe,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,kCAAkC;YAClC,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;YACtC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YAC5B,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QACtC,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,oBAAoB,IAAI,EAAE,CAAC;IAE/C,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAEnF,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,CAAC;QAC3C,WAAW,EAAE,SAAS;QACtB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,MAAM,EAAE,SAAS,EAAE,qCAAqC;KACzD,CAAC,CAAC;IAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,WAAmB,EACnB,IAAY,EACZ,eAAwB,EACxB,SAAiC;IAEjC,qEAAqE;IACrE,IAAI,SAAiB,EAAE,aAAqB,CAAC;IAE7C,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,eAAe,CAAC,CAAC;QAC3D,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAC7B,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,yCAAyC;QACzC,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;QAC1E,IAAI,MAAM,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,eAAe,CAAC,CAAC;YAC3D,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;YAC7B,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;YACrC,eAAe,GAAG,eAAe,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;YACtC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;YAC5B,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QACtC,CAAC;IACH,CAAC;IAED,MAAM,WAAW,GAAG,oBAAoB,IAAI,EAAE,CAAC;IAC/C,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAEnF,MAAM,OAAO,GAAG,YAAY,CAAC,eAAe,CAAC;QAC3C,WAAW,EAAE,SAAS;QACtB,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;QACvB,MAAM,EAAE,SAAS;KAClB,CAAC,CAAC;IAEH,IAAI,SAAS,EAAE,CAAC;QACd,SAAS,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,wDAAwD;QACxD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAwB,CAAC;QACpD,sDAAsD;QACtD,2FAA2F;QAC3F,MAAM,OAAO,GAA4B,EAAE,CAAC;QAE5C,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;YAC5C,KAAK,CAAC,KAAK,IAAI,EAAE;gBACf,IAAI,CAAC;oBACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,EAAE,WAAW,CAAC,CAAC;oBAChD,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBAE1C,IAAI,IAAI,EAAE,CAAC;wBACT,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;wBACzE,GAAG,CAAC,GAAG,CACL,kDAAkD,WAAW,wDAAwD,CACtH,CAAC;wBAEF,2DAA2D;wBAC3D,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;wBACzB,MAAM,CAAC,KAAK,EAAE,CAAC;wBACf,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;wBAE9C,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;wBACrD,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;wBAEpC,iBAAiB;wBACjB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;wBACpE,IAAI,KAAyB,CAAC;wBAC9B,IAAI,CAAC;4BACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;4BAC7C,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;wBAC3C,CAAC;wBAAC,MAAM,CAAC;4BACP,0CAA0C;wBAC5C,CAAC;wBAED,aAAa;wBACb,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;wBAEvE,8DAA8D;wBAC9D,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;wBAC1C,MAAM,aAAa,GAAkB;4BACnC,IAAI,EAAE,WAAW;4BACjB,KAAK;4BACL,SAAS;4BACT,GAAG,CAAC,eAAe,IAAI,EAAE,eAAe,EAAE,CAAC;4BAC3C,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;yBAClC,CAAC;wBACF,uGAAuG;wBACvG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,aAAa,CAAC;wBAC7C,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;wBAEjC,OAAO,CAAC,aAAa,CAAC,CAAC;oBACzB,CAAC;yBAAM,CAAC;wBACN,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;wBAC5C,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;wBACzE,GAAG,CAAC,GAAG,CACL,gDAAgD,KAAK,IAAI,kBAAkB,oBAAoB,CAChG,CAAC;wBACF,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;wBACzB,MAAM,CAAC,KAAK,EAAE,CAAC;wBACf,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;wBAC9C,MAAM,CAAC,IAAI,KAAK,CAAC,KAAK,IAAI,gCAAgC,CAAC,CAAC,CAAC;oBAC/D,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;oBACzE,GAAG,CAAC,GAAG,CAAC,0DAA0D,CAAC,CAAC;oBACpE,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;oBACzB,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;oBAC9C,MAAM,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC,CAAC,CAAC;QAEH,kDAAkD;QAClD,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE;YAC/B,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACtB,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;YACvB,OAAO,CAAC,KAAK,CAAC,2CAA2C,IAAI,EAAE,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;YAChD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,KAAK,CAAC,QAAQ,IAAI,+BAA+B,CAAC,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,0BAA0B;QAC1B,OAAO,CAAC,EAAE,GAAG,UAAU,CACrB,GAAG,EAAE;YACH,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC,CAAC;QAChE,CAAC,EACD,CAAC,GAAG,EAAE,GAAG,IAAI,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAE1C,oHAAoH;IACpH,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IACrD,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,YAAY,WAAW,aAAa,CAAC,CAAC;IACxD,CAAC;IAED,oBAAoB;IACpB,IAAI,CAAC;QACH,iHAAiH;QACjH,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IAED,gEAAgE;IAEhE,MAAM,EAAE,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,GAAG,iBAAiB,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC1E,MAAM,CAAC,QAAQ,GAAG,iBAAiB,CAAC;IACpC,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,WAAmB;IACvD,MAAM,MAAM,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAC1C,kGAAkG;IAClG,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC7C,IAAI,OAAO,EAAE,KAAK,EAAE,CAAC;QACnB,OAAO,OAAO,CAAC,KAAK,CAAC;IACvB,CAAC;IACD,6CAA6C;IAC7C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACpB,uDAAuD;YACvD,IAAI,OAAO,EAAE,CAAC;gBACZ,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC;gBAChC,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,SAAS,CAAC,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,8BAA8B;IAChC,CAAC;IACD,+FAA+F;IAC/F,OAAO,WAAW,CAAC;AACrB,CAAC"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { OAuth2Client } from 'google-auth-library';
2
+ import { JWT } from 'google-auth-library';
3
+ export declare function authorize(): Promise<OAuth2Client | JWT>;
4
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,GAAG,EAAE,MAAM,qBAAqB,CAAC;AA8M1C,wBAAsB,SAAS,IAAI,OAAO,CAAC,YAAY,GAAG,GAAG,CAAC,CAkB7D"}