@ariadng/sheets 0.1.1 → 0.3.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 (72) hide show
  1. package/LICENSE +2 -2
  2. package/README.md +453 -299
  3. package/bin/sheets.js +3 -0
  4. package/dist/api/index.d.ts +31 -0
  5. package/dist/api/index.d.ts.map +1 -0
  6. package/dist/api/index.js +87 -0
  7. package/dist/api/index.js.map +1 -0
  8. package/dist/auth/constants.d.ts +13 -0
  9. package/dist/auth/constants.d.ts.map +1 -0
  10. package/dist/auth/constants.js +21 -0
  11. package/dist/auth/constants.js.map +1 -0
  12. package/dist/auth/index.d.ts +13 -0
  13. package/dist/auth/index.d.ts.map +1 -0
  14. package/dist/auth/index.js +22 -0
  15. package/dist/auth/index.js.map +1 -0
  16. package/dist/auth/oauth.d.ts +11 -0
  17. package/dist/auth/oauth.d.ts.map +1 -0
  18. package/dist/auth/oauth.js +14 -0
  19. package/dist/auth/oauth.js.map +1 -0
  20. package/dist/auth/service-account.d.ts +18 -0
  21. package/dist/auth/service-account.d.ts.map +1 -0
  22. package/dist/auth/service-account.js +92 -0
  23. package/dist/auth/service-account.js.map +1 -0
  24. package/dist/auth/user-auth.d.ts +24 -0
  25. package/dist/auth/user-auth.d.ts.map +1 -0
  26. package/dist/auth/user-auth.js +230 -0
  27. package/dist/auth/user-auth.js.map +1 -0
  28. package/dist/cli.d.ts +7 -0
  29. package/dist/cli.d.ts.map +1 -0
  30. package/dist/cli.js +412 -0
  31. package/dist/cli.js.map +1 -0
  32. package/dist/http/index.d.ts +19 -0
  33. package/dist/http/index.d.ts.map +1 -0
  34. package/dist/http/index.js +68 -0
  35. package/dist/http/index.js.map +1 -0
  36. package/dist/index.d.ts +11 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +12 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/types/index.d.ts +133 -0
  41. package/dist/types/index.d.ts.map +1 -0
  42. package/dist/types/index.js +16 -0
  43. package/dist/types/index.js.map +1 -0
  44. package/package.json +58 -79
  45. package/dist/advanced/index.d.ts +0 -5
  46. package/dist/advanced/index.d.ts.map +0 -1
  47. package/dist/advanced/index.js +0 -1063
  48. package/dist/advanced/index.mjs +0 -1005
  49. package/dist/advanced/metrics.d.ts +0 -50
  50. package/dist/advanced/metrics.d.ts.map +0 -1
  51. package/dist/advanced/rate-limit.d.ts +0 -27
  52. package/dist/advanced/rate-limit.d.ts.map +0 -1
  53. package/dist/core/auth.d.ts +0 -33
  54. package/dist/core/auth.d.ts.map +0 -1
  55. package/dist/core/client.d.ts +0 -35
  56. package/dist/core/client.d.ts.map +0 -1
  57. package/dist/core/errors.d.ts +0 -11
  58. package/dist/core/errors.d.ts.map +0 -1
  59. package/dist/core/index.d.ts +0 -6
  60. package/dist/core/index.d.ts.map +0 -1
  61. package/dist/core/index.js +0 -315
  62. package/dist/core/index.mjs +0 -271
  63. package/dist/plus/batch.d.ts +0 -25
  64. package/dist/plus/batch.d.ts.map +0 -1
  65. package/dist/plus/cache.d.ts +0 -19
  66. package/dist/plus/cache.d.ts.map +0 -1
  67. package/dist/plus/index.d.ts +0 -7
  68. package/dist/plus/index.d.ts.map +0 -1
  69. package/dist/plus/index.js +0 -742
  70. package/dist/plus/index.mjs +0 -691
  71. package/dist/plus/types.d.ts +0 -39
  72. package/dist/plus/types.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,439 +1,593 @@
1
- # Sheets
1
+ # @ariadng/sheets
2
2
 
3
- A pragmatic TypeScript client for Google Sheets API v4 with stellar performance, that provides essential features without over-engineering. Start simple and add complexity only when needed.
3
+ A command-line tool and library for reading Google Sheets. Works with personal Google accounts and service accounts.
4
4
 
5
- ## Features
5
+ ## For AI Agents
6
6
 
7
- - **Progressive Enhancement** - Start with core features, add more as needed
8
- - **Modular Packages** - Core (~3KB), Plus (~5KB), Advanced (~2KB)
9
- - **Smart Retry Logic** - Exponential backoff with jitter
10
- - **Optional Caching** - Reduce API calls with configurable TTL
11
- - **Type Safety** - Full TypeScript support with type utilities
12
- - **Rate Limiting** - Adaptive or token bucket strategies
13
- - **Metrics Collection** - Track performance and errors
14
- - **Batch Operations** - Efficient bulk reads/writes
7
+ If you are an AI agent (Claude, GPT, Copilot, or other AI assistants), use the npx version of this tool. This allows you to run commands without installing the package globally.
8
+
9
+ **Authentication**: Before reading spreadsheets, the user must be logged in. Check login status first, then prompt the user to login if needed.
10
+
11
+ ```bash
12
+ # Check if user is logged in
13
+ npx @ariadng/sheets whoami
14
+
15
+ # If not logged in, ask user to run this command
16
+ npx @ariadng/sheets login
17
+ ```
18
+
19
+ **Reading data**: Use `--format json` for structured output that is easier to parse.
20
+
21
+ ```bash
22
+ # Get spreadsheet metadata
23
+ npx @ariadng/sheets get SPREADSHEET_ID --format json
24
+
25
+ # List all sheets
26
+ npx @ariadng/sheets list SPREADSHEET_ID --format json
27
+
28
+ # Read cell values
29
+ npx @ariadng/sheets read SPREADSHEET_ID "Sheet1!A1:D10" --format json
30
+
31
+ # Read formulas instead of values
32
+ npx @ariadng/sheets read SPREADSHEET_ID "Sheet1!A1:D10" --formula --format json
33
+ ```
34
+
35
+ **Getting the spreadsheet ID**: Extract the ID from the Google Sheets URL. The URL format is `https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit`. The spreadsheet ID is the string between `/d/` and `/edit`.
36
+
37
+ ## What This Tool Does
38
+
39
+ - Read data from Google Sheets spreadsheets
40
+ - View spreadsheet information and sheet lists
41
+ - Read cell values or formulas
42
+ - Authenticate with your Google account or a service account
43
+
44
+ ## Requirements
45
+
46
+ - Node.js version 18 or higher
47
+ - A Google account (for personal use) or a Google Cloud service account
15
48
 
16
49
  ## Installation
17
50
 
18
51
  ```bash
19
- # Core package only
20
- npm install @ariadng/sheets
52
+ npm install -g @ariadng/sheets
53
+ ```
21
54
 
22
- # With specific packages
23
- npm install @ariadng/sheets
55
+ After installation, the `sheets` command will be available in your terminal.
56
+
57
+ ## Usage Summary
58
+
59
+ | Command | Description |
60
+ |---------|-------------|
61
+ | `sheets login` | Login with Google account |
62
+ | `sheets logout` | Remove saved login |
63
+ | `sheets whoami` | Show current login status |
64
+ | `sheets auth <file>` | Test service account credentials |
65
+ | `sheets get <id>` | Get spreadsheet metadata |
66
+ | `sheets list <id>` | List sheets in spreadsheet |
67
+ | `sheets read <id> <range>` | Read cell values |
68
+ | `sheets read <id> <range> --formula` | Read formulas |
69
+ | `sheets read <id> <range> --format json` | Output as JSON |
70
+ | `sheets install-claude-skill` | Install Claude Code skill |
71
+
72
+ ## Using with npx
73
+
74
+ You can also run this tool without installing it:
75
+
76
+ ```bash
77
+ npx @ariadng/sheets login
78
+ npx @ariadng/sheets read SPREADSHEET_ID "Sheet1!A1:D10"
24
79
  ```
25
80
 
26
- ## Quick Start
81
+ ## Claude Code Integration
27
82
 
28
- ### Basic Usage
83
+ This tool includes a Claude Skill that teaches Claude Code how to use the sheets CLI. To install the skill:
29
84
 
30
- ```typescript
31
- import { GoogleSheetsCore, createServiceAccountAuth } from '@ariadng/sheets/core';
85
+ ```bash
86
+ sheets install-claude-skill
87
+ ```
32
88
 
33
- // Setup with service account
34
- const auth = await createServiceAccountAuth('./service-account-key.json');
35
- const sheets = new GoogleSheetsCore({ auth });
89
+ Or with npx:
36
90
 
37
- // Simple read
38
- const data = await sheets.read('spreadsheetId', 'Sheet1!A1:B10');
39
- console.log(data); // [[value1, value2], [value3, value4], ...]
91
+ ```bash
92
+ npx @ariadng/sheets install-claude-skill
93
+ ```
40
94
 
41
- // Simple write
42
- await sheets.write('spreadsheetId', 'Sheet1!A1:B2', [
43
- ['Name', 'Score'],
44
- ['Alice', 100]
45
- ]);
95
+ After installation, you can use `/sheets` in Claude Code to read Google Sheets data. The skill is installed to `~/.claude/skills/sheets/SKILL.md`.
96
+
97
+ ## Getting Started
98
+
99
+ ### Step 1: Login to Your Google Account
100
+
101
+ Run this command to connect your Google account:
102
+
103
+ ```bash
104
+ sheets login
46
105
  ```
47
106
 
48
- ### With Caching
107
+ This will:
108
+ 1. Open your web browser
109
+ 2. Ask you to sign in to your Google account
110
+ 3. Ask you to allow the app to read your spreadsheets
111
+ 4. Save your login for future use
49
112
 
50
- ```typescript
51
- import { withCache } from '@ariadng/sheets/plus';
113
+ After login, you will see your email address displayed.
52
114
 
53
- const cachedSheets = withCache(sheets, {
54
- ttlSeconds: 300 // 5-minute cache
55
- });
115
+ ### Step 2: Read a Spreadsheet
56
116
 
57
- // First read hits API
58
- const data1 = await cachedSheets.read(id, 'A1:B10');
117
+ Find the spreadsheet ID from your Google Sheets URL. The URL looks like this:
59
118
 
60
- // Second read uses cache (within 5 minutes)
61
- const data2 = await cachedSheets.read(id, 'A1:B10'); // Much faster!
119
+ ```
120
+ https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit
62
121
  ```
63
122
 
64
- ### With Rate Limiting
123
+ The spreadsheet ID is the long string of letters and numbers between `/d/` and `/edit`.
65
124
 
66
- ```typescript
67
- import { withAdaptiveRateLimit } from '@ariadng/sheets/advanced';
125
+ Now you can read data:
68
126
 
69
- const rateLimitedSheets = withAdaptiveRateLimit(sheets);
127
+ ```bash
128
+ # Get spreadsheet information
129
+ sheets get SPREADSHEET_ID
70
130
 
71
- // Automatically handles rate limits
72
- for (let i = 0; i < 1000; i++) {
73
- await rateLimitedSheets.read(id, `A${i}`);
74
- // Automatically slows down if hitting limits
75
- }
131
+ # List all sheets in the spreadsheet
132
+ sheets list SPREADSHEET_ID
133
+
134
+ # Read cells from a range
135
+ sheets read SPREADSHEET_ID "Sheet1!A1:D10"
76
136
  ```
77
137
 
78
138
  ## Authentication
79
139
 
80
- ### Service Account
140
+ This tool supports three ways to authenticate:
81
141
 
82
- ```typescript
83
- import { createServiceAccountAuth } from '@ariadng/sheets/core';
142
+ ### 1. Personal Google Account (Recommended for Most Users)
84
143
 
85
- // From file
86
- const auth = await createServiceAccountAuth('./service-account.json');
144
+ Use the `login` command to authenticate with your personal Google account:
87
145
 
88
- // From object
89
- const auth = await createServiceAccountAuth({
90
- client_email: 'your-service-account@project.iam.gserviceaccount.com',
91
- private_key: '-----BEGIN PRIVATE KEY-----...',
92
- // ... other fields
93
- });
146
+ ```bash
147
+ sheets login
94
148
  ```
95
149
 
96
- ### OAuth2
150
+ Your login will be saved and used automatically for future commands. To check your login status:
97
151
 
98
- ```typescript
99
- import { createOAuth2Client, generateAuthUrl, getTokenFromCode } from '@ariadng/sheets/core';
152
+ ```bash
153
+ sheets whoami
154
+ ```
100
155
 
101
- const client = await createOAuth2Client({
102
- client_id: 'your-client-id',
103
- client_secret: 'your-client-secret',
104
- redirect_uris: ['http://localhost:3000/callback']
105
- });
156
+ To remove your saved login:
106
157
 
107
- // Generate auth URL
108
- const authUrl = generateAuthUrl(client);
109
- console.log('Visit:', authUrl);
158
+ ```bash
159
+ sheets logout
160
+ ```
110
161
 
111
- // After user authorizes, exchange code for token
112
- const tokens = await getTokenFromCode(client, authorizationCode);
162
+ ### 2. Service Account (For Automated Systems)
163
+
164
+ Service accounts are special Google accounts for applications and scripts. To use a service account:
165
+
166
+ 1. Create a service account in Google Cloud Console
167
+ 2. Download the JSON credentials file
168
+ 3. Share your spreadsheet with the service account email address
169
+ 4. Use the `--credentials` option with commands:
170
+
171
+ ```bash
172
+ sheets get SPREADSHEET_ID --credentials path/to/credentials.json
113
173
  ```
114
174
 
115
- ## Core Features
175
+ To test if your service account credentials are valid:
116
176
 
117
- ### CRUD Operations
177
+ ```bash
178
+ sheets auth path/to/credentials.json
179
+ ```
118
180
 
119
- ```typescript
120
- // Read
121
- const values = await sheets.read(spreadsheetId, 'Sheet1!A1:C10');
181
+ ### 3. Access Token (For Advanced Use)
122
182
 
123
- // Write (replaces existing data)
124
- await sheets.write(spreadsheetId, 'Sheet1!A1:C3', [
125
- ['Header1', 'Header2', 'Header3'],
126
- ['Value1', 'Value2', 'Value3']
127
- ]);
183
+ If you have an OAuth access token, you can use it directly:
128
184
 
129
- // Append (adds to end)
130
- await sheets.append(spreadsheetId, 'Sheet1!A:C', [
131
- ['New1', 'New2', 'New3']
132
- ]);
185
+ ```bash
186
+ sheets get SPREADSHEET_ID --token YOUR_ACCESS_TOKEN
187
+ ```
188
+
189
+ ## CLI Commands Reference
190
+
191
+ ### Authentication Commands
133
192
 
134
- // Clear
135
- await sheets.clear(spreadsheetId, 'Sheet1!A1:C10');
193
+ #### sheets login
194
+
195
+ Connect your Google account.
196
+
197
+ ```bash
198
+ sheets login
136
199
  ```
137
200
 
138
- ### Batch Operations
201
+ Options:
202
+ - `--client <file>`: Use custom OAuth client credentials (optional)
139
203
 
140
- ```typescript
141
- // Batch read multiple ranges
142
- const results = await sheets.batchRead(spreadsheetId, [
143
- 'Sheet1!A1:B10',
144
- 'Sheet2!C1:D5'
145
- ]);
204
+ What happens:
205
+ 1. Opens your browser to Google sign-in page
206
+ 2. Starts a local server on port 8085 to receive the response
207
+ 3. Saves your tokens to `~/.sheets/tokens.json`
146
208
 
147
- // Batch write multiple ranges
148
- await sheets.batchWrite(spreadsheetId, [
149
- { range: 'Sheet1!A1:B2', values: [['A', 'B'], ['C', 'D']] },
150
- { range: 'Sheet2!A1:B2', values: [['E', 'F'], ['G', 'H']] }
151
- ]);
209
+ #### sheets logout
210
+
211
+ Remove your saved login.
212
+
213
+ ```bash
214
+ sheets logout
152
215
  ```
153
216
 
154
- ## Plus Package Features
217
+ This deletes the stored tokens from your computer.
155
218
 
156
- ### Type Utilities
219
+ #### sheets whoami
157
220
 
158
- ```typescript
159
- import { A1, TypedSheets, Parsers, Serializers } from '@ariadng/sheets/plus';
160
-
161
- // A1 notation utilities
162
- const col = A1.columnToIndex('C'); // 2
163
- const letter = A1.indexToColumn(2); // 'C'
164
- const range = A1.build('Sheet1', 'A', 1, 'C', 10); // 'Sheet1!A1:C10'
165
-
166
- // Type-safe operations
167
- interface User {
168
- name: string;
169
- email: string;
170
- age: number;
171
- }
221
+ Show your current login status.
222
+
223
+ ```bash
224
+ sheets whoami
225
+ ```
226
+
227
+ Output includes:
228
+ - Your email address
229
+ - Token expiration time
230
+ - Whether the token is still valid
231
+
232
+ Exit code: 0 if logged in, 1 if not logged in.
233
+
234
+ #### sheets auth
235
+
236
+ Test service account credentials.
172
237
 
173
- const typed = new TypedSheets<User[]>(sheets);
174
- const users = await typed.read(
175
- spreadsheetId,
176
- 'Users!A1:C100',
177
- Parsers.rowsToObjects<User>
178
- );
238
+ ```bash
239
+ sheets auth path/to/credentials.json
240
+ ```
241
+
242
+ This validates the credentials file format and shows:
243
+ - Project ID
244
+ - Service account email
245
+
246
+ ### Spreadsheet Commands
247
+
248
+ #### sheets get
249
+
250
+ Get spreadsheet information.
179
251
 
180
- // Data transformation
181
- const objects = [
182
- { name: 'Alice', age: 30 },
183
- { name: 'Bob', age: 25 }
184
- ];
185
- const rows = Serializers.objectsToRows(objects);
186
- // [['name', 'age'], ['Alice', 30], ['Bob', 25]]
252
+ ```bash
253
+ sheets get SPREADSHEET_ID
187
254
  ```
188
255
 
189
- ### Batch Operations Manager
256
+ Options:
257
+ - `--credentials <file>`: Use service account credentials
258
+ - `--token <token>`: Use OAuth access token
259
+ - `--format <format>`: Output format, either `table` (default) or `json`
190
260
 
191
- ```typescript
192
- import { BatchOperations } from '@ariadng/sheets/plus';
261
+ Output includes:
262
+ - Spreadsheet title
263
+ - Spreadsheet ID
264
+ - Locale and timezone
265
+ - Number of sheets
266
+ - Spreadsheet URL
193
267
 
194
- const batchOps = new BatchOperations(sheets);
268
+ #### sheets list
195
269
 
196
- // Automatically chunks large batches
197
- const operations = Array.from({ length: 500 }, (_, i) => ({
198
- range: `Sheet1!A${i}:B${i}`,
199
- values: [[`Row${i}`, `Value${i}`]]
200
- }));
270
+ List all sheets in a spreadsheet.
201
271
 
202
- await batchOps.batchWrite(spreadsheetId, operations); // Handles chunking
272
+ ```bash
273
+ sheets list SPREADSHEET_ID
203
274
  ```
204
275
 
205
- ### Simple Cache
276
+ Options:
277
+ - `--credentials <file>`: Use service account credentials
278
+ - `--token <token>`: Use OAuth access token
279
+ - `--format <format>`: Output format, either `table` (default) or `json`
206
280
 
207
- ```typescript
208
- import { SimpleCache } from '@ariadng/sheets/plus';
281
+ Output includes:
282
+ - Sheet index
283
+ - Sheet title
284
+ - Grid size (rows and columns)
285
+ - Hidden status
209
286
 
210
- const cache = new SimpleCache({
211
- ttlSeconds: 60,
212
- maxEntries: 100
213
- });
287
+ #### sheets read
214
288
 
215
- cache.set('key', data);
216
- const cached = cache.get('key');
217
- cache.invalidate('pattern*'); // Wildcard invalidation
218
- cache.clear(); // Clear all
289
+ Read cell values from a spreadsheet range.
290
+
291
+ ```bash
292
+ sheets read SPREADSHEET_ID "Sheet1!A1:D10"
219
293
  ```
220
294
 
221
- ## Advanced Package Features
295
+ Options:
296
+ - `--credentials <file>`: Use service account credentials
297
+ - `--token <token>`: Use OAuth access token
298
+ - `--format <format>`: Output format, either `table` (default) or `json`
299
+ - `--formula`: Show formulas instead of calculated values
222
300
 
223
- ### Adaptive Rate Limiting
301
+ Examples:
224
302
 
225
- ```typescript
226
- import { AdaptiveRateLimiter } from '@ariadng/sheets/advanced';
303
+ ```bash
304
+ # Read a range of cells
305
+ sheets read SPREADSHEET_ID "Sheet1!A1:D10"
227
306
 
228
- const limiter = new AdaptiveRateLimiter();
307
+ # Read an entire column
308
+ sheets read SPREADSHEET_ID "Sheet1!A:A"
229
309
 
230
- // Automatically adjusts delay based on success/failure
231
- await limiter.execute(async () => {
232
- return sheets.read(id, range);
233
- });
310
+ # Read with formulas visible
311
+ sheets read SPREADSHEET_ID "Sheet1!A1:D10" --formula
234
312
 
235
- // Get current stats
236
- const stats = limiter.getStats();
237
- console.log(stats); // { requestsInWindow: 45, successRate: 0.98, baseDelay: 0 }
313
+ # Output as JSON
314
+ sheets read SPREADSHEET_ID "Sheet1!A1:D10" --format json
238
315
  ```
239
316
 
240
- ### Metrics Collection
317
+ Range format:
318
+ - `Sheet1!A1:D10`: Cells A1 through D10 on Sheet1
319
+ - `Sheet1!A:A`: Entire column A on Sheet1
320
+ - `Sheet1!1:1`: Entire row 1 on Sheet1
321
+ - `A1:D10`: Cells A1 through D10 on the first sheet
241
322
 
242
- ```typescript
243
- import { withMetrics } from '@ariadng/sheets/advanced';
323
+ #### sheets install-claude-skill
324
+
325
+ Install the Claude Code skill for this tool.
326
+
327
+ ```bash
328
+ sheets install-claude-skill
329
+ ```
330
+
331
+ This installs a skill file to `~/.claude/skills/sheets/SKILL.md` that teaches Claude Code how to use the sheets CLI. After installation, you can use `/sheets` in Claude Code.
244
332
 
245
- const metricsSheets = withMetrics(sheets);
333
+ ### Global Options
246
334
 
247
- // Use normally
248
- await metricsSheets.read(id, range);
249
- await metricsSheets.write(id, range, values);
335
+ These options work with all spreadsheet commands:
250
336
 
251
- // Get metrics
252
- const metrics = metricsSheets.metrics.getMetrics();
253
- console.log(metrics);
254
- // {
255
- // totalRequests: 150,
256
- // successfulRequests: 148,
257
- // failedRequests: 2,
258
- // averageLatency: 123.5,
259
- // rateLimitHits: 1,
260
- // errorsByCode: Map { 429 => 1, 500 => 1 }
261
- // }
337
+ | Option | Description |
338
+ |--------|-------------|
339
+ | `--credentials <file>` | Path to service account JSON file |
340
+ | `--token <token>` | OAuth access token string |
341
+ | `--format <format>` | Output format: `table` or `json` |
342
+ | `--version` | Show version number |
343
+ | `--help` | Show help message |
262
344
 
263
- const summary = metricsSheets.metrics.getSummary();
264
- console.log(summary);
265
- // {
266
- // successRate: 0.987,
267
- // requestsPerSecond: 2.5,
268
- // uptimeSeconds: 60
269
- // }
345
+ ## Library Usage
346
+
347
+ You can also use this package as a library in your Node.js applications.
348
+
349
+ ### Installation
350
+
351
+ ```bash
352
+ npm install @ariadng/sheets
270
353
  ```
271
354
 
272
- ## Error Handling
355
+ ### Basic Example
273
356
 
274
357
  ```typescript
275
- import { GoogleSheetsError } from '@ariadng/sheets/core';
358
+ import { createClient } from '@ariadng/sheets';
276
359
 
277
- try {
278
- await sheets.read(spreadsheetId, range);
279
- } catch (error) {
280
- if (error instanceof GoogleSheetsError) {
281
- console.error(`API Error ${error.code}: ${error.message}`);
360
+ // Create a client with user authentication (after running "sheets login")
361
+ const client = createClient({
362
+ auth: { type: 'user' }
363
+ });
282
364
 
283
- if (error.isRetryable) {
284
- console.log('This error is retryable');
285
- }
365
+ // Get spreadsheet information
366
+ const spreadsheet = await client.getSpreadsheet('SPREADSHEET_ID');
367
+ console.log(spreadsheet.properties.title);
368
+
369
+ // Read cell values
370
+ const values = await client.getValues('SPREADSHEET_ID', 'Sheet1!A1:D10');
371
+ console.log(values.values);
372
+ ```
286
373
 
287
- if (error.isPermissionError()) {
288
- console.log('Share the sheet with service account');
374
+ ### Service Account Example
375
+
376
+ ```typescript
377
+ import { createClient } from '@ariadng/sheets';
378
+
379
+ const client = createClient({
380
+ auth: {
381
+ type: 'service-account',
382
+ credentialsPath: './credentials.json'
289
383
  }
384
+ });
385
+
386
+ const values = await client.getValues('SPREADSHEET_ID', 'Sheet1!A1:D10');
387
+ ```
388
+
389
+ ### OAuth Token Example
290
390
 
291
- if (error.isRateLimitError()) {
292
- console.log('Hit rate limit, slow down');
391
+ ```typescript
392
+ import { createClient } from '@ariadng/sheets';
393
+
394
+ const client = createClient({
395
+ auth: {
396
+ type: 'oauth',
397
+ accessToken: 'YOUR_ACCESS_TOKEN'
293
398
  }
399
+ });
294
400
 
295
- // User-friendly message
296
- console.log(error.getUserMessage());
297
- }
298
- }
401
+ const values = await client.getValues('SPREADSHEET_ID', 'Sheet1!A1:D10');
299
402
  ```
300
403
 
301
- ## Common Patterns
404
+ ### Available Methods
405
+
406
+ #### getSpreadsheet(spreadsheetId)
302
407
 
303
- ### Progressive Enhancement
408
+ Get spreadsheet metadata.
304
409
 
305
410
  ```typescript
306
- import { GoogleSheetsCore } from '@ariadng/sheets/core';
307
- import { withCache } from '@ariadng/sheets/plus';
308
- import { withAdaptiveRateLimit, withMetrics } from '@ariadng/sheets/advanced';
411
+ const spreadsheet = await client.getSpreadsheet('SPREADSHEET_ID');
412
+ // Returns: { spreadsheetId, properties, sheets, spreadsheetUrl }
413
+ ```
309
414
 
310
- // Start simple
311
- let sheets = new GoogleSheetsCore({ auth });
415
+ #### getSheets(spreadsheetId)
312
416
 
313
- // Add features as needed
314
- sheets = withCache(sheets, { ttlSeconds: 300 });
315
- sheets = withAdaptiveRateLimit(sheets);
316
- sheets = withMetrics(sheets);
417
+ Get list of sheets in a spreadsheet.
317
418
 
318
- // Now have all features!
419
+ ```typescript
420
+ const sheets = await client.getSheets('SPREADSHEET_ID');
421
+ // Returns: [{ sheetId, title, index, gridProperties, hidden }]
319
422
  ```
320
423
 
321
- ### Data Processing Pipeline
424
+ #### getValues(spreadsheetId, range, options?)
425
+
426
+ Read cell values from a range.
322
427
 
323
428
  ```typescript
324
- import { Parsers, Serializers } from '@ariadng/sheets/plus';
429
+ const values = await client.getValues('SPREADSHEET_ID', 'Sheet1!A1:D10');
430
+ // Returns: { range, majorDimension, values }
325
431
 
326
- // Read raw data
327
- const raw = await sheets.read(id, 'Data!A1:Z1000');
432
+ // With options
433
+ const values = await client.getValues('SPREADSHEET_ID', 'Sheet1!A1:D10', {
434
+ valueRenderOption: 'UNFORMATTED_VALUE',
435
+ dateTimeRenderOption: 'SERIAL_NUMBER'
436
+ });
437
+ ```
328
438
 
329
- // Parse to objects
330
- const records = Parsers.rowsToObjects(raw);
439
+ Options:
440
+ - `valueRenderOption`: How values should be rendered
441
+ - `FORMATTED_VALUE` (default): Values as displayed in the UI
442
+ - `UNFORMATTED_VALUE`: Raw values without formatting
443
+ - `FORMULA`: Formulas instead of calculated values
444
+ - `dateTimeRenderOption`: How dates should be rendered
445
+ - `FORMATTED_STRING` (default): Date as formatted string
446
+ - `SERIAL_NUMBER`: Date as serial number
447
+ - `majorDimension`: How data is organized
448
+ - `ROWS` (default): Data organized by rows
449
+ - `COLUMNS`: Data organized by columns
331
450
 
332
- // Process data
333
- const processed = records
334
- .filter(r => r.status === 'active')
335
- .map(r => ({ ...r, processed: true }));
451
+ #### getFormulas(spreadsheetId, range)
336
452
 
337
- // Convert back to rows
338
- const rows = Serializers.objectsToRows(processed);
453
+ Read formulas from a range. This is a shortcut for `getValues` with `valueRenderOption: 'FORMULA'`.
339
454
 
340
- // Write back
341
- await sheets.write(id, 'Processed!A1', rows);
455
+ ```typescript
456
+ const formulas = await client.getFormulas('SPREADSHEET_ID', 'Sheet1!A1:D10');
342
457
  ```
343
458
 
344
- ### Efficient Batch Processing
459
+ #### batchGetValues(spreadsheetId, ranges, options?)
460
+
461
+ Read multiple ranges in a single request.
345
462
 
346
463
  ```typescript
347
- import { BatchOperations } from '@ariadng/sheets/plus';
464
+ const result = await client.batchGetValues('SPREADSHEET_ID', [
465
+ 'Sheet1!A1:D10',
466
+ 'Sheet2!A1:B5'
467
+ ]);
468
+ // Returns: { spreadsheetId, valueRanges: [...] }
469
+ ```
348
470
 
349
- const batch = new BatchOperations(sheets);
471
+ ### Authentication Functions
350
472
 
351
- // Mixed operations
352
- const results = await batch.executeBatch(spreadsheetId, {
353
- reads: ['Summary!A1:Z1', 'Config!A1:B10'],
354
- writes: [
355
- { range: 'Output!A1:B100', values: outputData }
356
- ],
357
- clears: ['Temp!A:Z']
358
- });
473
+ ```typescript
474
+ import { login, loadStoredTokens, deleteTokens } from '@ariadng/sheets';
359
475
 
360
- // All executed efficiently in parallel when possible
476
+ // Perform OAuth login flow
477
+ const tokens = await login();
478
+ console.log(tokens.email);
479
+
480
+ // Load stored tokens
481
+ const stored = await loadStoredTokens();
482
+ if (stored) {
483
+ console.log('Logged in as:', stored.email);
484
+ }
485
+
486
+ // Delete stored tokens
487
+ await deleteTokens();
361
488
  ```
362
489
 
363
- ## API Reference
490
+ ## Troubleshooting
364
491
 
365
- ### Core Package
492
+ ### "Not logged in" Error
366
493
 
367
- #### GoogleSheetsCore
494
+ Run `sheets login` to authenticate with your Google account.
368
495
 
369
- - `constructor(config: GoogleSheetsConfig)`
370
- - `read(spreadsheetId: string, range: string): Promise<any[][]>`
371
- - `write(spreadsheetId: string, range: string, values: any[][]): Promise<UpdateValuesResponse>`
372
- - `append(spreadsheetId: string, range: string, values: any[][]): Promise<AppendValuesResponse>`
373
- - `clear(spreadsheetId: string, range: string): Promise<ClearValuesResponse>`
374
- - `batchRead(spreadsheetId: string, ranges: string[]): Promise<ValueRange[]>`
375
- - `batchWrite(spreadsheetId: string, data: BatchWriteData[]): Promise<BatchUpdateValuesResponse>`
376
- - `getSpreadsheet(spreadsheetId: string): Promise<Spreadsheet>`
377
- - `getApi(): sheets_v4.Sheets`
496
+ ### "Access denied" or "Permission denied" Error
378
497
 
379
- ### Plus Package
498
+ Make sure you have access to the spreadsheet:
499
+ - For personal accounts: The spreadsheet must be shared with your Google account
500
+ - For service accounts: Share the spreadsheet with the service account email address
380
501
 
381
- #### A1 Utilities
502
+ ### "Invalid credentials" Error
382
503
 
383
- - `A1.columnToIndex(column: string): number`
384
- - `A1.indexToColumn(index: number): string`
385
- - `A1.parse(notation: string): A1Components`
386
- - `A1.build(sheet?, startCol, startRow, endCol?, endRow?): string`
387
- - `A1.getDimensions(notation: string): { rows: number, columns: number }`
388
- - `A1.offset(notation: string, rowOffset: number, colOffset: number): string`
504
+ For service accounts:
505
+ - Check that the JSON file is valid
506
+ - Make sure the file contains `type: "service_account"`
507
+ - Verify the private key is correct
389
508
 
390
- #### Parsers
509
+ ### Browser Does Not Open During Login
391
510
 
392
- - `Parsers.rowsToObjects<T>(data: any[][]): T[]`
393
- - `Parsers.asNumbers(data: any[][]): number[][]`
394
- - `Parsers.asStrings(data: any[][]): string[][]`
395
- - `Parsers.asMap<V>(data: any[][]): Map<string, V>`
396
- - `Parsers.column<T>(data: any[][], columnIndex: number): T[]`
511
+ Try these solutions:
512
+ - Open the URL manually (it will be displayed in the terminal)
513
+ - Make sure port 8085 is not in use by another application
397
514
 
398
- #### Serializers
515
+ ### Token Expired
399
516
 
400
- - `Serializers.objectsToRows<T>(objects: T[], headers?: string[]): any[][]`
401
- - `Serializers.mapToRows<K,V>(map: Map<K,V>): any[][]`
402
- - `Serializers.arrayToColumn<T>(array: T[]): any[][]`
403
- - `Serializers.transpose(data: any[][]): any[][]`
517
+ Tokens are automatically refreshed when they expire. If you see token errors, try logging out and logging in again:
404
518
 
405
- ## Performance
519
+ ```bash
520
+ sheets logout
521
+ sheets login
522
+ ```
406
523
 
407
- | Operation | Base Latency | With Cache | With Rate Limit |
408
- |-----------|-------------|------------|-----------------|
409
- | Single Read | 100-200ms | 0-1ms (hit) | +0-50ms |
410
- | Batch Read (10) | 150-250ms | 0-1ms (hit) | +0-50ms |
411
- | Single Write | 150-300ms | N/A | +0-50ms |
412
- | Batch Write (100) | 300-500ms | N/A | +0-100ms |
524
+ ## Token Storage
413
525
 
414
- ## Best Practices
526
+ When you run `sheets login`, your authentication tokens are saved to:
415
527
 
416
- 1. **Use batch operations** when reading/writing multiple ranges
417
- 2. **Enable caching** for frequently read, rarely changed data
418
- 3. **Add rate limiting** for bulk operations or scripts
419
- 4. **Use type utilities** for better type safety and code clarity
420
- 5. **Handle errors gracefully** with proper retry logic
421
- 6. **Monitor with metrics** in production environments
528
+ ```
529
+ ~/.sheets/tokens.json
530
+ ```
422
531
 
423
- ## Requirements
532
+ This file contains:
533
+ - Access token (used to make API requests)
534
+ - Refresh token (used to get new access tokens)
535
+ - Token expiration time
536
+ - Your email address
424
537
 
425
- - Node.js 14+
426
- - Google Sheets API enabled in Google Cloud Console
427
- - Service account or OAuth2 credentials
538
+ Keep this file secure. Do not share it with others.
428
539
 
429
- ## License
540
+ ## How It Works
430
541
 
431
- MIT
542
+ This tool uses the Google Sheets API v4 to read spreadsheet data. It does not use the official Google SDK. Instead, it makes direct HTTP requests to the API.
432
543
 
433
- ## Contributing
544
+ Authentication methods:
545
+ - Personal accounts: OAuth 2.0 with PKCE (Proof Key for Code Exchange)
546
+ - Service accounts: JWT (JSON Web Token) signed with RS256
434
547
 
435
- Contributions are welcome! Please read our contributing guidelines before submitting PRs.
548
+ The tool only requests read-only access to your spreadsheets. It cannot modify your data.
436
549
 
437
- ## Support
550
+ ## Project Structure
438
551
 
439
- For issues and feature requests, please use the [GitHub issues page](https://github.com/ariadng/sheets/issues).
552
+ ```
553
+ src/
554
+ index.ts Public API exports
555
+ cli.ts CLI entry point
556
+ api/index.ts SheetsClient class
557
+ auth/
558
+ index.ts Auth provider factory
559
+ constants.ts OAuth configuration
560
+ oauth.ts OAuth token wrapper
561
+ user-auth.ts User OAuth with PKCE
562
+ service-account.ts Service account JWT auth
563
+ http/index.ts HTTP client with retry
564
+ types/index.ts TypeScript definitions
565
+ ```
566
+
567
+ ## Development
568
+
569
+ ### Build
570
+
571
+ ```bash
572
+ npm run build
573
+ ```
574
+
575
+ This compiles TypeScript to JavaScript in the `dist` folder.
576
+
577
+ ### Development Mode
578
+
579
+ ```bash
580
+ npm run dev
581
+ ```
582
+
583
+ This runs the CLI with automatic reloading when files change.
584
+
585
+ ### Run Without Building
586
+
587
+ ```bash
588
+ npx tsx src/cli.ts <command>
589
+ ```
590
+
591
+ ## License
592
+
593
+ MIT