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