@ariadng/sheets 0.4.0 → 0.4.2

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 (47) hide show
  1. package/dist/cli.cjs +1610 -0
  2. package/dist/cli.cjs.map +1 -0
  3. package/dist/cli.d.cts +1 -0
  4. package/dist/cli.d.ts +0 -6
  5. package/dist/cli.js +1318 -595
  6. package/dist/cli.js.map +1 -1
  7. package/dist/index.cjs +858 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.d.cts +356 -0
  10. package/dist/index.d.ts +355 -10
  11. package/dist/index.js +810 -11
  12. package/dist/index.js.map +1 -1
  13. package/package.json +5 -3
  14. package/dist/api/index.d.ts +0 -60
  15. package/dist/api/index.d.ts.map +0 -1
  16. package/dist/api/index.js +0 -347
  17. package/dist/api/index.js.map +0 -1
  18. package/dist/auth/constants.d.ts +0 -13
  19. package/dist/auth/constants.d.ts.map +0 -1
  20. package/dist/auth/constants.js +0 -21
  21. package/dist/auth/constants.js.map +0 -1
  22. package/dist/auth/index.d.ts +0 -13
  23. package/dist/auth/index.d.ts.map +0 -1
  24. package/dist/auth/index.js +0 -22
  25. package/dist/auth/index.js.map +0 -1
  26. package/dist/auth/oauth.d.ts +0 -32
  27. package/dist/auth/oauth.d.ts.map +0 -1
  28. package/dist/auth/oauth.js +0 -80
  29. package/dist/auth/oauth.js.map +0 -1
  30. package/dist/auth/service-account.d.ts +0 -18
  31. package/dist/auth/service-account.d.ts.map +0 -1
  32. package/dist/auth/service-account.js +0 -92
  33. package/dist/auth/service-account.js.map +0 -1
  34. package/dist/auth/user-auth.d.ts +0 -24
  35. package/dist/auth/user-auth.d.ts.map +0 -1
  36. package/dist/auth/user-auth.js +0 -230
  37. package/dist/auth/user-auth.js.map +0 -1
  38. package/dist/cli.d.ts.map +0 -1
  39. package/dist/http/index.d.ts +0 -19
  40. package/dist/http/index.d.ts.map +0 -1
  41. package/dist/http/index.js +0 -68
  42. package/dist/http/index.js.map +0 -1
  43. package/dist/index.d.ts.map +0 -1
  44. package/dist/types/index.d.ts +0 -200
  45. package/dist/types/index.d.ts.map +0 -1
  46. package/dist/types/index.js +0 -16
  47. package/dist/types/index.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/types/index.ts","../src/http/index.ts","../src/auth/constants.ts","../src/auth/oauth.ts","../src/auth/service-account.ts","../src/auth/user-auth.ts","../src/auth/index.ts","../src/api/index.ts"],"sourcesContent":["/**\n * @ariadng/google-sheets\n * Google Sheets API interface and CLI tool\n */\n\n// Client\nexport { SheetsClient, createClient } from './api/index.js';\n\n// Auth\nexport { createAuthProvider, OAuthAuth, ServiceAccountAuth, UserAuth, login, loadStoredTokens, deleteTokens } from './auth/index.js';\nexport type { AuthProvider } from './auth/index.js';\n\n// HTTP\nexport { HttpClient } from './http/index.js';\n\n// Types\nexport type {\n // Grid & Sheet\n GridProperties,\n SheetProperties,\n // Spreadsheet\n Spreadsheet,\n SpreadsheetProperties,\n // Cell\n CellValue,\n CellFormat,\n Color,\n TextFormat,\n // Values\n ValueRange,\n GetValuesOptions,\n BatchGetValuesResponse,\n ClearValuesResponse,\n BatchClearValuesResponse,\n ValueRenderOption,\n DateTimeRenderOption,\n MajorDimension,\n // Write values\n ValueInputOption,\n InsertDataOption,\n RawCellValue,\n UpdateValuesOptions,\n AppendValuesOptions,\n UpdateValuesResponse,\n BatchUpdateValuesResponse,\n AppendValuesResponse,\n // Search values\n SearchMatch,\n SearchOptions,\n SearchResult,\n // Auth\n AuthConfig,\n OAuthConfig,\n ServiceAccountConfig,\n ServiceAccountCredentials,\n UserAuthConfig,\n StoredTokens,\n SheetsClientOptions,\n // Errors\n SheetsApiError,\n SheetsApiErrorDetail,\n} from './types/index.js';\n\nexport { SheetsError } from './types/index.js';\n","/**\n * Google Sheets API Type Definitions\n */\n\n// === Grid Properties ===\n\nexport interface GridProperties {\n rowCount: number;\n columnCount: number;\n frozenRowCount?: number;\n frozenColumnCount?: number;\n hideGridlines?: boolean;\n}\n\n// === Sheet Properties ===\n\nexport interface SheetProperties {\n sheetId: number;\n title: string;\n index: number;\n sheetType?: 'GRID' | 'OBJECT' | 'DATA_SOURCE';\n gridProperties?: GridProperties;\n hidden?: boolean;\n rightToLeft?: boolean;\n}\n\n// === Spreadsheet ===\n\nexport interface SpreadsheetProperties {\n title: string;\n locale?: string;\n timeZone?: string;\n autoRecalc?: 'ON_CHANGE' | 'MINUTE' | 'HOUR';\n defaultFormat?: CellFormat;\n}\n\nexport interface Spreadsheet {\n spreadsheetId: string;\n properties: SpreadsheetProperties;\n sheets: { properties: SheetProperties }[];\n spreadsheetUrl?: string;\n}\n\n// === Cell Format ===\n\nexport interface CellFormat {\n numberFormat?: {\n type: string;\n pattern?: string;\n };\n backgroundColor?: Color;\n textFormat?: TextFormat;\n}\n\nexport interface Color {\n red?: number;\n green?: number;\n blue?: number;\n alpha?: number;\n}\n\nexport interface TextFormat {\n foregroundColor?: Color;\n fontFamily?: string;\n fontSize?: number;\n bold?: boolean;\n italic?: boolean;\n strikethrough?: boolean;\n underline?: boolean;\n}\n\n// === Cell Value ===\n\nexport interface CellValue {\n value: string | number | boolean | null;\n formula?: string;\n formattedValue?: string;\n}\n\n// === Value Range ===\n\nexport type ValueRenderOption = 'FORMATTED_VALUE' | 'UNFORMATTED_VALUE' | 'FORMULA';\nexport type DateTimeRenderOption = 'SERIAL_NUMBER' | 'FORMATTED_STRING';\nexport type MajorDimension = 'ROWS' | 'COLUMNS';\n\nexport interface ValueRange {\n range: string;\n majorDimension: MajorDimension;\n values: CellValue[][];\n}\n\nexport interface GetValuesOptions {\n valueRenderOption?: ValueRenderOption;\n dateTimeRenderOption?: DateTimeRenderOption;\n majorDimension?: MajorDimension;\n}\n\nexport interface BatchGetValuesResponse {\n spreadsheetId: string;\n valueRanges: ValueRange[];\n}\n\n// === Clear Values ===\n\nexport interface ClearValuesResponse {\n spreadsheetId: string;\n clearedRange: string;\n}\n\nexport interface BatchClearValuesResponse {\n spreadsheetId: string;\n clearedRanges: string[];\n}\n\n// === Write Values ===\n\nexport type ValueInputOption = 'RAW' | 'USER_ENTERED';\nexport type InsertDataOption = 'OVERWRITE' | 'INSERT_ROWS';\nexport type RawCellValue = string | number | boolean | null;\n\nexport interface UpdateValuesOptions {\n valueInputOption?: ValueInputOption;\n majorDimension?: MajorDimension;\n includeValuesInResponse?: boolean;\n responseValueRenderOption?: ValueRenderOption;\n responseDateTimeRenderOption?: DateTimeRenderOption;\n}\n\nexport interface AppendValuesOptions extends UpdateValuesOptions {\n insertDataOption?: InsertDataOption;\n}\n\nexport interface UpdateValuesResponse {\n spreadsheetId: string;\n updatedRange: string;\n updatedRows: number;\n updatedColumns: number;\n updatedCells: number;\n updatedData?: ValueRange;\n}\n\nexport interface BatchUpdateValuesResponse {\n spreadsheetId: string;\n totalUpdatedRows: number;\n totalUpdatedColumns: number;\n totalUpdatedCells: number;\n totalUpdatedSheets: number;\n responses: UpdateValuesResponse[];\n}\n\nexport interface AppendValuesResponse {\n spreadsheetId: string;\n tableRange?: string;\n updates: UpdateValuesResponse;\n}\n\n// === Search Values ===\n\nexport interface SearchMatch {\n sheet: string;\n sheetId: number;\n address: string;\n row: number;\n column: number;\n value: string | number | boolean | null;\n}\n\nexport interface SearchOptions {\n range?: string;\n sheetIndex?: number;\n gid?: number;\n caseSensitive?: boolean;\n exactMatch?: boolean;\n regex?: boolean;\n limit?: number;\n}\n\nexport interface SearchResult {\n query: string;\n matchType: 'contains' | 'exact' | 'regex';\n caseSensitive: boolean;\n totalMatches: number;\n matches: SearchMatch[];\n}\n\n// === Authentication ===\n\nexport interface OAuthConfig {\n type: 'oauth';\n accessToken: string;\n refreshToken?: string;\n clientId?: string;\n clientSecret?: string;\n expiresAt?: number; // Unix timestamp in ms when access token expires\n}\n\nexport interface ServiceAccountConfig {\n type: 'service-account';\n credentialsPath?: string;\n credentials?: ServiceAccountCredentials;\n}\n\nexport interface ServiceAccountCredentials {\n type: 'service_account';\n project_id: string;\n private_key_id: string;\n private_key: string;\n client_email: string;\n client_id: string;\n auth_uri: string;\n token_uri: string;\n}\n\nexport interface UserAuthConfig {\n type: 'user';\n}\n\nexport interface StoredTokens {\n accessToken: string;\n refreshToken: string;\n expiresAt: number;\n email?: string;\n}\n\nexport type AuthConfig = OAuthConfig | ServiceAccountConfig | UserAuthConfig;\n\nexport interface SheetsClientOptions {\n auth: AuthConfig;\n}\n\n// === Error Types ===\n\nexport interface SheetsApiErrorDetail {\n '@type'?: string;\n reason?: string;\n domain?: string;\n metadata?: Record<string, string>;\n}\n\nexport interface SheetsApiError {\n code: number;\n message: string;\n status: string;\n details?: SheetsApiErrorDetail[];\n}\n\nexport class SheetsError extends Error {\n code: number;\n status: string;\n details?: SheetsApiErrorDetail[];\n\n constructor(error: SheetsApiError) {\n super(error.message);\n this.name = 'SheetsError';\n this.code = error.code;\n this.status = error.status;\n this.details = error.details;\n }\n}\n","/**\n * HTTP Client for Google Sheets API\n * Uses native Node.js fetch (Node 18+)\n */\n\nimport { SheetsError } from '../types/index.js';\n\nconst BASE_URL = 'https://sheets.googleapis.com/v4';\nconst MAX_RETRIES = 3;\nconst INITIAL_BACKOFF_MS = 1000;\n\nexport interface HttpClientOptions {\n getAccessToken: () => Promise<string>;\n}\n\nexport interface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n params?: Record<string, string>;\n}\n\nexport class HttpClient {\n private getAccessToken: () => Promise<string>;\n\n constructor(options: HttpClientOptions) {\n this.getAccessToken = options.getAccessToken;\n }\n\n async request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n const { method = 'GET', body, params } = options;\n\n let url = `${BASE_URL}${path}`;\n if (params) {\n const searchParams = new URLSearchParams(params);\n url += `?${searchParams.toString()}`;\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const accessToken = await this.getAccessToken();\n\n const response = await fetch(url, {\n method,\n headers: {\n 'Authorization': `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (response.status === 429) {\n const backoffMs = INITIAL_BACKOFF_MS * Math.pow(2, attempt);\n await this.sleep(backoffMs);\n continue;\n }\n\n const data = await response.json() as { error?: { code: number; message: string; status: string } };\n\n if (!response.ok) {\n if (data.error) {\n throw new SheetsError({\n code: data.error.code,\n message: data.error.message,\n status: data.error.status,\n });\n }\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return data as T;\n } catch (error) {\n lastError = error as Error;\n\n if (error instanceof SheetsError && error.code !== 429 && error.code !== 500 && error.code !== 503) {\n throw error;\n }\n\n if (attempt < MAX_RETRIES - 1) {\n const backoffMs = INITIAL_BACKOFF_MS * Math.pow(2, attempt);\n await this.sleep(backoffMs);\n }\n }\n }\n\n throw lastError || new Error('Request failed after retries');\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n","/**\n * OAuth Client Constants\n * Replace with your Google Cloud OAuth client credentials\n */\n\n// Built-in OAuth client (Desktop app type)\n// Project: ariadng-sheets\nexport const OAUTH_CLIENT_ID = '344941894490-jmdvo5ghomqi7vuisfrf80hfassk1ma5.apps.googleusercontent.com';\nexport const OAUTH_CLIENT_SECRET = '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';\n\n// Redirect URI for local callback server\nexport const OAUTH_REDIRECT_URI = 'http://localhost:8085/callback';\nexport const OAUTH_CALLBACK_PORT = 8085;\n\n// OAuth endpoints\nexport const OAUTH_AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';\nexport const OAUTH_TOKEN_URL = 'https://oauth2.googleapis.com/token';\nexport const OAUTH_USERINFO_URL = 'https://www.googleapis.com/oauth2/v2/userinfo';\n\n// Scopes\nexport const OAUTH_SCOPES = [\n 'https://www.googleapis.com/auth/spreadsheets',\n 'https://www.googleapis.com/auth/userinfo.email',\n];\n","/**\n * OAuth 2.0 Authentication\n * Supports pre-obtained access tokens with optional auto-refresh\n *\n * For automation (e.g., n8n), provide:\n * - accessToken: Current access token\n * - refreshToken: For obtaining new tokens when expired\n * - clientId: OAuth client ID\n * - clientSecret: OAuth client secret\n * - expiresAt: When the access token expires (Unix timestamp in ms)\n */\n\nimport type { OAuthConfig } from '../types/index.js';\nimport { OAUTH_TOKEN_URL } from './constants.js';\n\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n}\n\nexport class OAuthAuth {\n private config: OAuthConfig;\n private cachedToken: string;\n private expiresAt: number;\n\n constructor(config: OAuthConfig) {\n this.config = config;\n this.cachedToken = config.accessToken;\n this.expiresAt = config.expiresAt || 0;\n }\n\n async getAccessToken(): Promise<string> {\n // If no expiration tracking or no refresh credentials, return cached token\n if (!this.canRefresh()) {\n return this.cachedToken;\n }\n\n // Check if token is expired (with 60 second buffer)\n if (this.isExpired()) {\n await this.refreshToken();\n }\n\n return this.cachedToken;\n }\n\n private canRefresh(): boolean {\n return !!(\n this.config.refreshToken &&\n this.config.clientId &&\n this.config.clientSecret &&\n this.expiresAt > 0\n );\n }\n\n private isExpired(): boolean {\n return Date.now() >= this.expiresAt - 60000;\n }\n\n private async refreshToken(): Promise<void> {\n if (!this.config.refreshToken || !this.config.clientId || !this.config.clientSecret) {\n throw new Error('Token expired and missing refresh credentials (refreshToken, clientId, clientSecret)');\n }\n\n const response = await fetch(OAUTH_TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n client_id: this.config.clientId,\n client_secret: this.config.clientSecret,\n refresh_token: this.config.refreshToken,\n grant_type: 'refresh_token',\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Token refresh failed: ${error}`);\n }\n\n const tokenResponse = await response.json() as TokenResponse;\n\n this.cachedToken = tokenResponse.access_token;\n this.expiresAt = Date.now() + (tokenResponse.expires_in * 1000);\n\n // Update config with new refresh token if provided\n if (tokenResponse.refresh_token) {\n this.config.refreshToken = tokenResponse.refresh_token;\n }\n }\n\n /**\n * Get current token state for persistence in automation tools\n * Returns updated tokens after any refresh operations\n */\n getTokenState(): { accessToken: string; refreshToken?: string; expiresAt: number } {\n return {\n accessToken: this.cachedToken,\n refreshToken: this.config.refreshToken,\n expiresAt: this.expiresAt,\n };\n }\n}\n","/**\n * Service Account JWT Authentication\n * Uses RS256 signing to exchange JWT for access token\n */\n\nimport * as crypto from 'crypto';\nimport * as fs from 'fs/promises';\nimport type { ServiceAccountConfig, ServiceAccountCredentials } from '../types/index.js';\n\nconst TOKEN_URI = 'https://oauth2.googleapis.com/token';\nconst SCOPE = 'https://www.googleapis.com/auth/spreadsheets';\nconst TOKEN_LIFETIME_SECONDS = 3600;\n\ninterface TokenResponse {\n access_token: string;\n expires_in: number;\n token_type: string;\n}\n\nexport class ServiceAccountAuth {\n private config: ServiceAccountConfig;\n private credentials: ServiceAccountCredentials | null = null;\n private cachedToken: string | null = null;\n private tokenExpiresAt: number = 0;\n\n constructor(config: ServiceAccountConfig) {\n this.config = config;\n }\n\n async getAccessToken(): Promise<string> {\n if (this.cachedToken && Date.now() < this.tokenExpiresAt - 60000) {\n return this.cachedToken;\n }\n\n await this.loadCredentials();\n const jwt = this.createJwt();\n const token = await this.exchangeJwtForToken(jwt);\n\n this.cachedToken = token.access_token;\n this.tokenExpiresAt = Date.now() + (token.expires_in * 1000);\n\n return this.cachedToken;\n }\n\n private async loadCredentials(): Promise<void> {\n if (this.credentials) return;\n\n if (this.config.credentials) {\n this.credentials = this.config.credentials;\n return;\n }\n\n if (!this.config.credentialsPath) {\n throw new Error('Service account requires credentialsPath or credentials');\n }\n\n const content = await fs.readFile(this.config.credentialsPath, 'utf-8');\n this.credentials = JSON.parse(content) as ServiceAccountCredentials;\n }\n\n private createJwt(): string {\n if (!this.credentials) {\n throw new Error('Credentials not loaded');\n }\n\n const now = Math.floor(Date.now() / 1000);\n\n const header = {\n alg: 'RS256',\n typ: 'JWT',\n };\n\n const payload = {\n iss: this.credentials.client_email,\n scope: SCOPE,\n aud: TOKEN_URI,\n iat: now,\n exp: now + TOKEN_LIFETIME_SECONDS,\n };\n\n const encodedHeader = this.base64UrlEncode(JSON.stringify(header));\n const encodedPayload = this.base64UrlEncode(JSON.stringify(payload));\n const signatureInput = `${encodedHeader}.${encodedPayload}`;\n\n const sign = crypto.createSign('RSA-SHA256');\n sign.update(signatureInput);\n const signature = sign.sign(this.credentials.private_key);\n const encodedSignature = this.base64UrlEncode(signature);\n\n return `${signatureInput}.${encodedSignature}`;\n }\n\n private base64UrlEncode(input: string | Buffer): string {\n const buffer = typeof input === 'string' ? Buffer.from(input) : input;\n return buffer.toString('base64')\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=+$/, '');\n }\n\n private async exchangeJwtForToken(jwt: string): Promise<TokenResponse> {\n const response = await fetch(TOKEN_URI, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: new URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion: jwt,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n return await response.json() as TokenResponse;\n }\n}\n","/**\n * User OAuth Authentication\n * OAuth 2.0 Authorization Code flow with PKCE for personal Google accounts\n */\n\nimport * as crypto from 'crypto';\nimport * as fs from 'fs/promises';\nimport * as http from 'http';\nimport * as os from 'os';\nimport * as path from 'path';\nimport { exec } from 'child_process';\nimport type { StoredTokens } from '../types/index.js';\nimport {\n OAUTH_CLIENT_ID,\n OAUTH_CLIENT_SECRET,\n OAUTH_REDIRECT_URI,\n OAUTH_CALLBACK_PORT,\n OAUTH_AUTH_URL,\n OAUTH_TOKEN_URL,\n OAUTH_USERINFO_URL,\n OAUTH_SCOPES,\n} from './constants.js';\n\nexport interface OAuthClientCredentials {\n clientId: string;\n clientSecret: string;\n}\n\nconst CONFIG_DIR = path.join(os.homedir(), '.sheets');\nconst TOKENS_FILE = path.join(CONFIG_DIR, 'tokens.json');\n\n// === PKCE ===\n\ninterface PKCEPair {\n codeVerifier: string;\n codeChallenge: string;\n}\n\nexport function generatePKCE(): PKCEPair {\n const codeVerifier = crypto.randomBytes(32).toString('base64url');\n const codeChallenge = crypto\n .createHash('sha256')\n .update(codeVerifier)\n .digest('base64url');\n return { codeVerifier, codeChallenge };\n}\n\n// === Browser ===\n\nfunction openBrowser(url: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const platform = process.platform;\n let command: string;\n\n if (platform === 'darwin') {\n command = `open \"${url}\"`;\n } else if (platform === 'win32') {\n command = `start \"\" \"${url}\"`;\n } else {\n command = `xdg-open \"${url}\"`;\n }\n\n exec(command, (error) => {\n if (error) {\n reject(new Error(`Failed to open browser: ${error.message}`));\n } else {\n resolve();\n }\n });\n });\n}\n\n// === Callback Server ===\n\nfunction startCallbackServer(): Promise<string> {\n return new Promise((resolve, reject) => {\n let timeoutId: NodeJS.Timeout;\n\n const server = http.createServer((req, res) => {\n const url = new URL(req.url || '', `http://localhost:${OAUTH_CALLBACK_PORT}`);\n\n if (url.pathname === '/callback') {\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Authorization Failed</h1><p>You can close this window.</p></body></html>');\n clearTimeout(timeoutId);\n server.close();\n reject(new Error(`Authorization error: ${error}`));\n return;\n }\n\n if (code) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Authorization Successful</h1><p>You can close this window.</p></body></html>');\n clearTimeout(timeoutId);\n server.close();\n resolve(code);\n return;\n }\n\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Missing Code</h1></body></html>');\n } else {\n res.writeHead(404);\n res.end();\n }\n });\n\n server.on('error', (err) => {\n clearTimeout(timeoutId);\n reject(new Error(`Callback server error: ${err.message}`));\n });\n\n server.listen(OAUTH_CALLBACK_PORT, () => {\n // Server started, waiting for callback\n });\n\n // Timeout after 5 minutes\n timeoutId = setTimeout(() => {\n server.close();\n reject(new Error('Authorization timeout'));\n }, 5 * 60 * 1000);\n });\n}\n\n// === Authorization URL ===\n\nexport function getAuthorizationUrl(codeChallenge: string, clientId?: string): string {\n const params = new URLSearchParams({\n client_id: clientId || OAUTH_CLIENT_ID,\n redirect_uri: OAUTH_REDIRECT_URI,\n response_type: 'code',\n scope: OAUTH_SCOPES.join(' '),\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n access_type: 'offline',\n prompt: 'consent',\n });\n\n return `${OAUTH_AUTH_URL}?${params.toString()}`;\n}\n\n// === Token Exchange ===\n\ninterface TokenResponse {\n access_token: string;\n refresh_token?: string;\n expires_in: number;\n token_type: string;\n}\n\nasync function exchangeCodeForTokens(code: string, codeVerifier: string, credentials?: OAuthClientCredentials): Promise<TokenResponse> {\n const response = await fetch(OAUTH_TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n client_id: credentials?.clientId || OAUTH_CLIENT_ID,\n client_secret: credentials?.clientSecret || OAUTH_CLIENT_SECRET,\n code,\n code_verifier: codeVerifier,\n grant_type: 'authorization_code',\n redirect_uri: OAUTH_REDIRECT_URI,\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Token exchange failed: ${error}`);\n }\n\n return await response.json() as TokenResponse;\n}\n\nasync function refreshAccessToken(refreshToken: string): Promise<TokenResponse> {\n const response = await fetch(OAUTH_TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n client_id: OAUTH_CLIENT_ID,\n client_secret: OAUTH_CLIENT_SECRET,\n refresh_token: refreshToken,\n grant_type: 'refresh_token',\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Token refresh failed: ${error}`);\n }\n\n return await response.json() as TokenResponse;\n}\n\n// === User Info ===\n\ninterface UserInfo {\n email: string;\n id: string;\n}\n\nasync function getUserInfo(accessToken: string): Promise<UserInfo> {\n const response = await fetch(OAUTH_USERINFO_URL, {\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n\n if (!response.ok) {\n throw new Error('Failed to get user info');\n }\n\n return await response.json() as UserInfo;\n}\n\n// === Token Storage ===\n\nasync function ensureConfigDir(): Promise<void> {\n try {\n await fs.mkdir(CONFIG_DIR, { recursive: true });\n } catch {\n // Directory already exists\n }\n}\n\nexport async function loadStoredTokens(): Promise<StoredTokens | null> {\n try {\n const content = await fs.readFile(TOKENS_FILE, 'utf-8');\n return JSON.parse(content) as StoredTokens;\n } catch {\n return null;\n }\n}\n\nasync function saveTokens(tokens: StoredTokens): Promise<void> {\n await ensureConfigDir();\n await fs.writeFile(TOKENS_FILE, JSON.stringify(tokens, null, 2));\n}\n\nexport async function deleteTokens(): Promise<void> {\n try {\n await fs.unlink(TOKENS_FILE);\n } catch {\n // File doesn't exist\n }\n}\n\n// === Login Flow ===\n\nexport async function login(credentials?: OAuthClientCredentials): Promise<StoredTokens> {\n const { codeVerifier, codeChallenge } = generatePKCE();\n const authUrl = getAuthorizationUrl(codeChallenge, credentials?.clientId);\n\n console.log('Opening browser for Google login...');\n\n // Start server first, then open browser\n const codePromise = startCallbackServer();\n await openBrowser(authUrl);\n\n console.log('Waiting for authorization...');\n const code = await codePromise;\n\n console.log('Exchanging code for tokens...');\n const tokenResponse = await exchangeCodeForTokens(code, codeVerifier, credentials);\n\n const userInfo = await getUserInfo(tokenResponse.access_token);\n\n const tokens: StoredTokens = {\n accessToken: tokenResponse.access_token,\n refreshToken: tokenResponse.refresh_token || '',\n expiresAt: Date.now() + (tokenResponse.expires_in * 1000),\n email: userInfo.email,\n };\n\n await saveTokens(tokens);\n return tokens;\n}\n\n// === Auth Provider ===\n\nexport class UserAuth {\n private tokens: StoredTokens | null = null;\n\n async getAccessToken(): Promise<string> {\n if (!this.tokens) {\n this.tokens = await loadStoredTokens();\n }\n\n if (!this.tokens) {\n throw new Error('Not logged in. Run \"sheets login\" first.');\n }\n\n // Refresh if expired (with 1 minute buffer)\n if (Date.now() >= this.tokens.expiresAt - 60000) {\n if (!this.tokens.refreshToken) {\n throw new Error('Token expired and no refresh token. Run \"sheets login\" again.');\n }\n\n const tokenResponse = await refreshAccessToken(this.tokens.refreshToken);\n this.tokens.accessToken = tokenResponse.access_token;\n this.tokens.expiresAt = Date.now() + (tokenResponse.expires_in * 1000);\n\n if (tokenResponse.refresh_token) {\n this.tokens.refreshToken = tokenResponse.refresh_token;\n }\n\n await saveTokens(this.tokens);\n }\n\n return this.tokens.accessToken;\n }\n}\n","/**\n * Authentication Module Exports\n */\n\nimport type { AuthConfig } from '../types/index.js';\nimport { OAuthAuth } from './oauth.js';\nimport { ServiceAccountAuth } from './service-account.js';\nimport { UserAuth } from './user-auth.js';\n\nexport { OAuthAuth } from './oauth.js';\nexport { ServiceAccountAuth } from './service-account.js';\nexport { UserAuth, login, loadStoredTokens, deleteTokens } from './user-auth.js';\nexport type { OAuthClientCredentials } from './user-auth.js';\n\nexport interface AuthProvider {\n getAccessToken(): Promise<string>;\n}\n\nexport function createAuthProvider(config: AuthConfig): AuthProvider {\n switch (config.type) {\n case 'oauth':\n return new OAuthAuth(config);\n case 'service-account':\n return new ServiceAccountAuth(config);\n case 'user':\n return new UserAuth();\n default:\n throw new Error(`Unknown auth type: ${(config as { type: string }).type}`);\n }\n}\n","/**\n * Google Sheets API Client\n */\n\nimport type {\n Spreadsheet,\n SheetProperties,\n ValueRange,\n GetValuesOptions,\n SheetsClientOptions,\n BatchGetValuesResponse,\n ClearValuesResponse,\n BatchClearValuesResponse,\n RawCellValue,\n UpdateValuesOptions,\n UpdateValuesResponse,\n BatchUpdateValuesResponse,\n AppendValuesOptions,\n AppendValuesResponse,\n SearchOptions,\n SearchResult,\n SearchMatch,\n} from '../types/index.js';\nimport { HttpClient } from '../http/index.js';\nimport { createAuthProvider } from '../auth/index.js';\n\ninterface RawValueRange {\n range: string;\n majorDimension?: 'ROWS' | 'COLUMNS';\n values?: (string | number | boolean | null)[][];\n}\n\ninterface RawBatchGetResponse {\n spreadsheetId: string;\n valueRanges?: RawValueRange[];\n}\n\n/**\n * Convert column letter(s) to 1-based column number\n * A=1, B=2, ..., Z=26, AA=27, AB=28, etc.\n */\nfunction columnLetterToNumber(letters: string): number {\n let result = 0;\n for (let i = 0; i < letters.length; i++) {\n result = result * 26 + (letters.charCodeAt(i) - 64);\n }\n return result;\n}\n\n/**\n * Convert 1-based column number to column letter(s)\n * 1=A, 2=B, ..., 26=Z, 27=AA, 28=AB, etc.\n */\nfunction columnNumberToLetter(num: number): string {\n let result = '';\n while (num > 0) {\n const remainder = (num - 1) % 26;\n result = String.fromCharCode(65 + remainder) + result;\n num = Math.floor((num - 1) / 26);\n }\n return result;\n}\n\n/**\n * Parse A1 notation to extract starting row and column\n * Returns { startRow, startCol } (1-based)\n */\nfunction parseA1Range(range: string): { startRow: number; startCol: number } {\n // Remove sheet name if present (e.g., \"Sheet1!A1:D10\" -> \"A1:D10\")\n const cellRef = range.includes('!') ? range.split('!')[1] : range;\n\n // Extract first cell (e.g., \"A1:D10\" -> \"A1\", \"A1\" -> \"A1\")\n const firstCell = cellRef.split(':')[0];\n\n // Parse column letters and row number\n const match = firstCell.match(/^([A-Z]+)(\\d+)$/i);\n if (!match) {\n return { startRow: 1, startCol: 1 };\n }\n\n return {\n startCol: columnLetterToNumber(match[1].toUpperCase()),\n startRow: parseInt(match[2], 10),\n };\n}\n\nexport class SheetsClient {\n private http: HttpClient;\n\n constructor(options: SheetsClientOptions) {\n const authProvider = createAuthProvider(options.auth);\n this.http = new HttpClient({\n getAccessToken: () => authProvider.getAccessToken(),\n });\n }\n\n /**\n * Get a spreadsheet by ID\n */\n async getSpreadsheet(spreadsheetId: string): Promise<Spreadsheet> {\n return this.http.request<Spreadsheet>(`/spreadsheets/${spreadsheetId}`);\n }\n\n /**\n * Get list of sheets in a spreadsheet\n */\n async getSheets(spreadsheetId: string): Promise<SheetProperties[]> {\n const spreadsheet = await this.getSpreadsheet(spreadsheetId);\n return spreadsheet.sheets.map(sheet => sheet.properties);\n }\n\n /**\n * Read cell values from a range\n */\n async getValues(spreadsheetId: string, range: string, options?: GetValuesOptions): Promise<ValueRange> {\n const params: Record<string, string> = {};\n\n if (options?.valueRenderOption) {\n params.valueRenderOption = options.valueRenderOption;\n }\n if (options?.dateTimeRenderOption) {\n params.dateTimeRenderOption = options.dateTimeRenderOption;\n }\n if (options?.majorDimension) {\n params.majorDimension = options.majorDimension;\n }\n\n const encodedRange = encodeURIComponent(range);\n const response = await this.http.request<RawValueRange>(\n `/spreadsheets/${spreadsheetId}/values/${encodedRange}`,\n { params }\n );\n\n return this.normalizeValueRange(response);\n }\n\n /**\n * Read cell formulas from a range\n */\n async getFormulas(spreadsheetId: string, range: string): Promise<ValueRange> {\n return this.getValues(spreadsheetId, range, { valueRenderOption: 'FORMULA' });\n }\n\n /**\n * Read multiple ranges at once\n */\n async batchGetValues(spreadsheetId: string, ranges: string[], options?: GetValuesOptions): Promise<BatchGetValuesResponse> {\n const params: Record<string, string> = {\n ranges: ranges.join(','),\n };\n\n if (options?.valueRenderOption) {\n params.valueRenderOption = options.valueRenderOption;\n }\n if (options?.dateTimeRenderOption) {\n params.dateTimeRenderOption = options.dateTimeRenderOption;\n }\n if (options?.majorDimension) {\n params.majorDimension = options.majorDimension;\n }\n\n const response = await this.http.request<RawBatchGetResponse>(\n `/spreadsheets/${spreadsheetId}/values:batchGet`,\n { params }\n );\n\n return {\n spreadsheetId: response.spreadsheetId,\n valueRanges: (response.valueRanges || []).map(vr => this.normalizeValueRange(vr)),\n };\n }\n\n /**\n * Clear values from a single range\n */\n async clearValues(spreadsheetId: string, range: string): Promise<ClearValuesResponse> {\n const encodedRange = encodeURIComponent(range);\n return this.http.request<ClearValuesResponse>(\n `/spreadsheets/${spreadsheetId}/values/${encodedRange}:clear`,\n { method: 'POST' }\n );\n }\n\n /**\n * Clear values from multiple ranges\n */\n async batchClearValues(spreadsheetId: string, ranges: string[]): Promise<BatchClearValuesResponse> {\n return this.http.request<BatchClearValuesResponse>(\n `/spreadsheets/${spreadsheetId}/values:batchClear`,\n { method: 'POST', body: { ranges } }\n );\n }\n\n /**\n * Write values to a range (or starting cell)\n * Range can be \"A1\" or \"A1:D10\" - data array determines actual extent\n */\n async updateValues(\n spreadsheetId: string,\n range: string,\n values: RawCellValue[][],\n options?: UpdateValuesOptions\n ): Promise<UpdateValuesResponse> {\n const params: Record<string, string> = {\n valueInputOption: options?.valueInputOption || 'USER_ENTERED',\n };\n\n if (options?.includeValuesInResponse) {\n params.includeValuesInResponse = 'true';\n }\n if (options?.responseValueRenderOption) {\n params.responseValueRenderOption = options.responseValueRenderOption;\n }\n if (options?.responseDateTimeRenderOption) {\n params.responseDateTimeRenderOption = options.responseDateTimeRenderOption;\n }\n\n const encodedRange = encodeURIComponent(range);\n return this.http.request<UpdateValuesResponse>(\n `/spreadsheets/${spreadsheetId}/values/${encodedRange}`,\n {\n method: 'PUT',\n params,\n body: {\n majorDimension: options?.majorDimension || 'ROWS',\n values,\n },\n }\n );\n }\n\n /**\n * Write to multiple ranges in one request\n */\n async batchUpdateValues(\n spreadsheetId: string,\n data: { range: string; values: RawCellValue[][] }[],\n options?: UpdateValuesOptions\n ): Promise<BatchUpdateValuesResponse> {\n return this.http.request<BatchUpdateValuesResponse>(\n `/spreadsheets/${spreadsheetId}/values:batchUpdate`,\n {\n method: 'POST',\n body: {\n valueInputOption: options?.valueInputOption || 'USER_ENTERED',\n data: data.map(d => ({\n range: d.range,\n majorDimension: options?.majorDimension || 'ROWS',\n values: d.values,\n })),\n includeValuesInResponse: options?.includeValuesInResponse || false,\n responseValueRenderOption: options?.responseValueRenderOption,\n responseDateTimeRenderOption: options?.responseDateTimeRenderOption,\n },\n }\n );\n }\n\n /**\n * Append rows after the last row of detected table\n */\n async appendValues(\n spreadsheetId: string,\n range: string,\n values: RawCellValue[][],\n options?: AppendValuesOptions\n ): Promise<AppendValuesResponse> {\n const params: Record<string, string> = {\n valueInputOption: options?.valueInputOption || 'USER_ENTERED',\n };\n\n if (options?.insertDataOption) {\n params.insertDataOption = options.insertDataOption;\n }\n if (options?.includeValuesInResponse) {\n params.includeValuesInResponse = 'true';\n }\n if (options?.responseValueRenderOption) {\n params.responseValueRenderOption = options.responseValueRenderOption;\n }\n if (options?.responseDateTimeRenderOption) {\n params.responseDateTimeRenderOption = options.responseDateTimeRenderOption;\n }\n\n const encodedRange = encodeURIComponent(range);\n return this.http.request<AppendValuesResponse>(\n `/spreadsheets/${spreadsheetId}/values/${encodedRange}:append`,\n {\n method: 'POST',\n params,\n body: {\n majorDimension: options?.majorDimension || 'ROWS',\n values,\n },\n }\n );\n }\n\n /**\n * Search for values matching a query across sheets\n */\n async searchValues(\n spreadsheetId: string,\n query: string,\n options?: SearchOptions\n ): Promise<SearchResult> {\n const caseSensitive = options?.caseSensitive ?? false;\n const exactMatch = options?.exactMatch ?? false;\n const useRegex = options?.regex ?? false;\n const limit = options?.limit;\n\n // Determine match type for response\n const matchType = useRegex ? 'regex' : (exactMatch ? 'exact' : 'contains');\n\n // Build the matcher function\n let matcher: (cellValue: string) => boolean;\n\n if (useRegex) {\n const flags = caseSensitive ? '' : 'i';\n const regex = new RegExp(query, flags);\n matcher = (cellValue) => regex.test(cellValue);\n } else if (exactMatch) {\n if (caseSensitive) {\n matcher = (cellValue) => cellValue === query;\n } else {\n const lowerQuery = query.toLowerCase();\n matcher = (cellValue) => cellValue.toLowerCase() === lowerQuery;\n }\n } else {\n // Contains match (default)\n if (caseSensitive) {\n matcher = (cellValue) => cellValue.includes(query);\n } else {\n const lowerQuery = query.toLowerCase();\n matcher = (cellValue) => cellValue.toLowerCase().includes(lowerQuery);\n }\n }\n\n const matches: SearchMatch[] = [];\n\n // Get sheets to search\n const allSheets = await this.getSheets(spreadsheetId);\n let sheetsToSearch: SheetProperties[];\n\n if (options?.sheetIndex !== undefined) {\n const sheet = allSheets.find(s => s.index === options.sheetIndex);\n if (!sheet) {\n throw new Error(`Sheet index ${options.sheetIndex} not found.`);\n }\n sheetsToSearch = [sheet];\n } else if (options?.gid !== undefined) {\n const sheet = allSheets.find(s => s.sheetId === options.gid);\n if (!sheet) {\n throw new Error(`Sheet with gid ${options.gid} not found.`);\n }\n sheetsToSearch = [sheet];\n } else if (options?.range && options.range.includes('!')) {\n // Range includes sheet name, use as-is\n sheetsToSearch = []; // Will handle specially below\n } else {\n // Search all sheets\n sheetsToSearch = allSheets.filter(s => !s.hidden);\n }\n\n // Search logic\n if (options?.range && options.range.includes('!')) {\n // Specific range with sheet name provided\n const valueRange = await this.getValues(spreadsheetId, options.range);\n const sheetName = options.range.split('!')[0].replace(/^'|'$/g, '').replace(/''/g, \"'\");\n const sheet = allSheets.find(s => s.title === sheetName);\n const { startRow, startCol } = parseA1Range(options.range);\n\n this.collectMatches(\n valueRange,\n sheetName,\n sheet?.sheetId ?? 0,\n startRow,\n startCol,\n matcher,\n matches,\n limit\n );\n } else {\n // Search across sheets\n for (const sheet of sheetsToSearch) {\n if (limit && matches.length >= limit) break;\n\n const escapedTitle = sheet.title.replace(/'/g, \"''\");\n const range = options?.range\n ? `'${escapedTitle}'!${options.range}`\n : `'${escapedTitle}'`; // Entire sheet\n\n try {\n const valueRange = await this.getValues(spreadsheetId, range);\n const { startRow, startCol } = parseA1Range(valueRange.range);\n\n this.collectMatches(\n valueRange,\n sheet.title,\n sheet.sheetId,\n startRow,\n startCol,\n matcher,\n matches,\n limit\n );\n } catch {\n // Skip sheets that fail (e.g., empty sheets)\n continue;\n }\n }\n }\n\n return {\n query,\n matchType,\n caseSensitive,\n totalMatches: matches.length,\n matches,\n };\n }\n\n private collectMatches(\n valueRange: ValueRange,\n sheetName: string,\n sheetId: number,\n startRow: number,\n startCol: number,\n matcher: (value: string) => boolean,\n matches: SearchMatch[],\n limit?: number\n ): void {\n for (let rowIndex = 0; rowIndex < valueRange.values.length; rowIndex++) {\n if (limit && matches.length >= limit) return;\n\n const row = valueRange.values[rowIndex];\n for (let colIndex = 0; colIndex < row.length; colIndex++) {\n if (limit && matches.length >= limit) return;\n\n const cell = row[colIndex];\n const cellValue = cell.value;\n\n // Skip null/undefined values\n if (cellValue == null) continue;\n\n // Convert to string for matching\n const stringValue = String(cellValue);\n\n if (matcher(stringValue)) {\n const actualRow = startRow + rowIndex;\n const actualCol = startCol + colIndex;\n\n matches.push({\n sheet: sheetName,\n sheetId,\n address: columnNumberToLetter(actualCol) + actualRow,\n row: actualRow,\n column: actualCol,\n value: cellValue,\n });\n }\n }\n }\n }\n\n private normalizeValueRange(raw: RawValueRange): ValueRange {\n const values = (raw.values || []).map(row =>\n row.map(cell => ({\n value: cell,\n }))\n );\n\n return {\n range: raw.range,\n majorDimension: raw.majorDimension || 'ROWS',\n values,\n };\n }\n}\n\nexport function createClient(options: SheetsClientOptions): SheetsClient {\n return new SheetsClient(options);\n}\n"],"mappings":"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","names":["path","crypto","fs"]}
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Google Sheets API Type Definitions
3
+ */
4
+ interface GridProperties {
5
+ rowCount: number;
6
+ columnCount: number;
7
+ frozenRowCount?: number;
8
+ frozenColumnCount?: number;
9
+ hideGridlines?: boolean;
10
+ }
11
+ interface SheetProperties {
12
+ sheetId: number;
13
+ title: string;
14
+ index: number;
15
+ sheetType?: 'GRID' | 'OBJECT' | 'DATA_SOURCE';
16
+ gridProperties?: GridProperties;
17
+ hidden?: boolean;
18
+ rightToLeft?: boolean;
19
+ }
20
+ interface SpreadsheetProperties {
21
+ title: string;
22
+ locale?: string;
23
+ timeZone?: string;
24
+ autoRecalc?: 'ON_CHANGE' | 'MINUTE' | 'HOUR';
25
+ defaultFormat?: CellFormat;
26
+ }
27
+ interface Spreadsheet {
28
+ spreadsheetId: string;
29
+ properties: SpreadsheetProperties;
30
+ sheets: {
31
+ properties: SheetProperties;
32
+ }[];
33
+ spreadsheetUrl?: string;
34
+ }
35
+ interface CellFormat {
36
+ numberFormat?: {
37
+ type: string;
38
+ pattern?: string;
39
+ };
40
+ backgroundColor?: Color;
41
+ textFormat?: TextFormat;
42
+ }
43
+ interface Color {
44
+ red?: number;
45
+ green?: number;
46
+ blue?: number;
47
+ alpha?: number;
48
+ }
49
+ interface TextFormat {
50
+ foregroundColor?: Color;
51
+ fontFamily?: string;
52
+ fontSize?: number;
53
+ bold?: boolean;
54
+ italic?: boolean;
55
+ strikethrough?: boolean;
56
+ underline?: boolean;
57
+ }
58
+ interface CellValue {
59
+ value: string | number | boolean | null;
60
+ formula?: string;
61
+ formattedValue?: string;
62
+ }
63
+ type ValueRenderOption = 'FORMATTED_VALUE' | 'UNFORMATTED_VALUE' | 'FORMULA';
64
+ type DateTimeRenderOption = 'SERIAL_NUMBER' | 'FORMATTED_STRING';
65
+ type MajorDimension = 'ROWS' | 'COLUMNS';
66
+ interface ValueRange {
67
+ range: string;
68
+ majorDimension: MajorDimension;
69
+ values: CellValue[][];
70
+ }
71
+ interface GetValuesOptions {
72
+ valueRenderOption?: ValueRenderOption;
73
+ dateTimeRenderOption?: DateTimeRenderOption;
74
+ majorDimension?: MajorDimension;
75
+ }
76
+ interface BatchGetValuesResponse {
77
+ spreadsheetId: string;
78
+ valueRanges: ValueRange[];
79
+ }
80
+ interface ClearValuesResponse {
81
+ spreadsheetId: string;
82
+ clearedRange: string;
83
+ }
84
+ interface BatchClearValuesResponse {
85
+ spreadsheetId: string;
86
+ clearedRanges: string[];
87
+ }
88
+ type ValueInputOption = 'RAW' | 'USER_ENTERED';
89
+ type InsertDataOption = 'OVERWRITE' | 'INSERT_ROWS';
90
+ type RawCellValue = string | number | boolean | null;
91
+ interface UpdateValuesOptions {
92
+ valueInputOption?: ValueInputOption;
93
+ majorDimension?: MajorDimension;
94
+ includeValuesInResponse?: boolean;
95
+ responseValueRenderOption?: ValueRenderOption;
96
+ responseDateTimeRenderOption?: DateTimeRenderOption;
97
+ }
98
+ interface AppendValuesOptions extends UpdateValuesOptions {
99
+ insertDataOption?: InsertDataOption;
100
+ }
101
+ interface UpdateValuesResponse {
102
+ spreadsheetId: string;
103
+ updatedRange: string;
104
+ updatedRows: number;
105
+ updatedColumns: number;
106
+ updatedCells: number;
107
+ updatedData?: ValueRange;
108
+ }
109
+ interface BatchUpdateValuesResponse {
110
+ spreadsheetId: string;
111
+ totalUpdatedRows: number;
112
+ totalUpdatedColumns: number;
113
+ totalUpdatedCells: number;
114
+ totalUpdatedSheets: number;
115
+ responses: UpdateValuesResponse[];
116
+ }
117
+ interface AppendValuesResponse {
118
+ spreadsheetId: string;
119
+ tableRange?: string;
120
+ updates: UpdateValuesResponse;
121
+ }
122
+ interface SearchMatch {
123
+ sheet: string;
124
+ sheetId: number;
125
+ address: string;
126
+ row: number;
127
+ column: number;
128
+ value: string | number | boolean | null;
129
+ }
130
+ interface SearchOptions {
131
+ range?: string;
132
+ sheetIndex?: number;
133
+ gid?: number;
134
+ caseSensitive?: boolean;
135
+ exactMatch?: boolean;
136
+ regex?: boolean;
137
+ limit?: number;
138
+ }
139
+ interface SearchResult {
140
+ query: string;
141
+ matchType: 'contains' | 'exact' | 'regex';
142
+ caseSensitive: boolean;
143
+ totalMatches: number;
144
+ matches: SearchMatch[];
145
+ }
146
+ interface OAuthConfig {
147
+ type: 'oauth';
148
+ accessToken: string;
149
+ refreshToken?: string;
150
+ clientId?: string;
151
+ clientSecret?: string;
152
+ expiresAt?: number;
153
+ }
154
+ interface ServiceAccountConfig {
155
+ type: 'service-account';
156
+ credentialsPath?: string;
157
+ credentials?: ServiceAccountCredentials;
158
+ }
159
+ interface ServiceAccountCredentials {
160
+ type: 'service_account';
161
+ project_id: string;
162
+ private_key_id: string;
163
+ private_key: string;
164
+ client_email: string;
165
+ client_id: string;
166
+ auth_uri: string;
167
+ token_uri: string;
168
+ }
169
+ interface UserAuthConfig {
170
+ type: 'user';
171
+ }
172
+ interface StoredTokens {
173
+ accessToken: string;
174
+ refreshToken: string;
175
+ expiresAt: number;
176
+ email?: string;
177
+ }
178
+ type AuthConfig = OAuthConfig | ServiceAccountConfig | UserAuthConfig;
179
+ interface SheetsClientOptions {
180
+ auth: AuthConfig;
181
+ }
182
+ interface SheetsApiErrorDetail {
183
+ '@type'?: string;
184
+ reason?: string;
185
+ domain?: string;
186
+ metadata?: Record<string, string>;
187
+ }
188
+ interface SheetsApiError {
189
+ code: number;
190
+ message: string;
191
+ status: string;
192
+ details?: SheetsApiErrorDetail[];
193
+ }
194
+ declare class SheetsError extends Error {
195
+ code: number;
196
+ status: string;
197
+ details?: SheetsApiErrorDetail[];
198
+ constructor(error: SheetsApiError);
199
+ }
200
+
201
+ /**
202
+ * Google Sheets API Client
203
+ */
204
+
205
+ declare class SheetsClient {
206
+ private http;
207
+ constructor(options: SheetsClientOptions);
208
+ /**
209
+ * Get a spreadsheet by ID
210
+ */
211
+ getSpreadsheet(spreadsheetId: string): Promise<Spreadsheet>;
212
+ /**
213
+ * Get list of sheets in a spreadsheet
214
+ */
215
+ getSheets(spreadsheetId: string): Promise<SheetProperties[]>;
216
+ /**
217
+ * Read cell values from a range
218
+ */
219
+ getValues(spreadsheetId: string, range: string, options?: GetValuesOptions): Promise<ValueRange>;
220
+ /**
221
+ * Read cell formulas from a range
222
+ */
223
+ getFormulas(spreadsheetId: string, range: string): Promise<ValueRange>;
224
+ /**
225
+ * Read multiple ranges at once
226
+ */
227
+ batchGetValues(spreadsheetId: string, ranges: string[], options?: GetValuesOptions): Promise<BatchGetValuesResponse>;
228
+ /**
229
+ * Clear values from a single range
230
+ */
231
+ clearValues(spreadsheetId: string, range: string): Promise<ClearValuesResponse>;
232
+ /**
233
+ * Clear values from multiple ranges
234
+ */
235
+ batchClearValues(spreadsheetId: string, ranges: string[]): Promise<BatchClearValuesResponse>;
236
+ /**
237
+ * Write values to a range (or starting cell)
238
+ * Range can be "A1" or "A1:D10" - data array determines actual extent
239
+ */
240
+ updateValues(spreadsheetId: string, range: string, values: RawCellValue[][], options?: UpdateValuesOptions): Promise<UpdateValuesResponse>;
241
+ /**
242
+ * Write to multiple ranges in one request
243
+ */
244
+ batchUpdateValues(spreadsheetId: string, data: {
245
+ range: string;
246
+ values: RawCellValue[][];
247
+ }[], options?: UpdateValuesOptions): Promise<BatchUpdateValuesResponse>;
248
+ /**
249
+ * Append rows after the last row of detected table
250
+ */
251
+ appendValues(spreadsheetId: string, range: string, values: RawCellValue[][], options?: AppendValuesOptions): Promise<AppendValuesResponse>;
252
+ /**
253
+ * Search for values matching a query across sheets
254
+ */
255
+ searchValues(spreadsheetId: string, query: string, options?: SearchOptions): Promise<SearchResult>;
256
+ private collectMatches;
257
+ private normalizeValueRange;
258
+ }
259
+ declare function createClient(options: SheetsClientOptions): SheetsClient;
260
+
261
+ /**
262
+ * OAuth 2.0 Authentication
263
+ * Supports pre-obtained access tokens with optional auto-refresh
264
+ *
265
+ * For automation (e.g., n8n), provide:
266
+ * - accessToken: Current access token
267
+ * - refreshToken: For obtaining new tokens when expired
268
+ * - clientId: OAuth client ID
269
+ * - clientSecret: OAuth client secret
270
+ * - expiresAt: When the access token expires (Unix timestamp in ms)
271
+ */
272
+
273
+ declare class OAuthAuth {
274
+ private config;
275
+ private cachedToken;
276
+ private expiresAt;
277
+ constructor(config: OAuthConfig);
278
+ getAccessToken(): Promise<string>;
279
+ private canRefresh;
280
+ private isExpired;
281
+ private refreshToken;
282
+ /**
283
+ * Get current token state for persistence in automation tools
284
+ * Returns updated tokens after any refresh operations
285
+ */
286
+ getTokenState(): {
287
+ accessToken: string;
288
+ refreshToken?: string;
289
+ expiresAt: number;
290
+ };
291
+ }
292
+
293
+ /**
294
+ * Service Account JWT Authentication
295
+ * Uses RS256 signing to exchange JWT for access token
296
+ */
297
+
298
+ declare class ServiceAccountAuth {
299
+ private config;
300
+ private credentials;
301
+ private cachedToken;
302
+ private tokenExpiresAt;
303
+ constructor(config: ServiceAccountConfig);
304
+ getAccessToken(): Promise<string>;
305
+ private loadCredentials;
306
+ private createJwt;
307
+ private base64UrlEncode;
308
+ private exchangeJwtForToken;
309
+ }
310
+
311
+ /**
312
+ * User OAuth Authentication
313
+ * OAuth 2.0 Authorization Code flow with PKCE for personal Google accounts
314
+ */
315
+
316
+ interface OAuthClientCredentials {
317
+ clientId: string;
318
+ clientSecret: string;
319
+ }
320
+ declare function loadStoredTokens(): Promise<StoredTokens | null>;
321
+ declare function deleteTokens(): Promise<void>;
322
+ declare function login(credentials?: OAuthClientCredentials): Promise<StoredTokens>;
323
+ declare class UserAuth {
324
+ private tokens;
325
+ getAccessToken(): Promise<string>;
326
+ }
327
+
328
+ /**
329
+ * Authentication Module Exports
330
+ */
331
+
332
+ interface AuthProvider {
333
+ getAccessToken(): Promise<string>;
334
+ }
335
+ declare function createAuthProvider(config: AuthConfig): AuthProvider;
336
+
337
+ /**
338
+ * HTTP Client for Google Sheets API
339
+ * Uses native Node.js fetch (Node 18+)
340
+ */
341
+ interface HttpClientOptions {
342
+ getAccessToken: () => Promise<string>;
343
+ }
344
+ interface RequestOptions {
345
+ method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
346
+ body?: unknown;
347
+ params?: Record<string, string>;
348
+ }
349
+ declare class HttpClient {
350
+ private getAccessToken;
351
+ constructor(options: HttpClientOptions);
352
+ request<T>(path: string, options?: RequestOptions): Promise<T>;
353
+ private sleep;
354
+ }
355
+
356
+ export { type AppendValuesOptions, type AppendValuesResponse, type AuthConfig, type AuthProvider, type BatchClearValuesResponse, type BatchGetValuesResponse, type BatchUpdateValuesResponse, type CellFormat, type CellValue, type ClearValuesResponse, type Color, type DateTimeRenderOption, type GetValuesOptions, type GridProperties, HttpClient, type InsertDataOption, type MajorDimension, OAuthAuth, type OAuthConfig, type RawCellValue, type SearchMatch, type SearchOptions, type SearchResult, ServiceAccountAuth, type ServiceAccountConfig, type ServiceAccountCredentials, type SheetProperties, type SheetsApiError, type SheetsApiErrorDetail, SheetsClient, type SheetsClientOptions, SheetsError, type Spreadsheet, type SpreadsheetProperties, type StoredTokens, type TextFormat, type UpdateValuesOptions, type UpdateValuesResponse, UserAuth, type UserAuthConfig, type ValueInputOption, type ValueRange, type ValueRenderOption, createAuthProvider, createClient, deleteTokens, loadStoredTokens, login };