@heroku/heroku-fetch 0.1.1-beta.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 (47) hide show
  1. package/LICENSE.txt +206 -0
  2. package/README.md +525 -0
  3. package/dist/auth/auth.d.ts +66 -0
  4. package/dist/auth/auth.js +93 -0
  5. package/dist/browser.d.ts +13 -0
  6. package/dist/browser.js +12 -0
  7. package/dist/cli/cli-login.d.ts +7 -0
  8. package/dist/cli/cli-login.js +7 -0
  9. package/dist/cli/cli-two-factor-prompt.d.ts +62 -0
  10. package/dist/cli/cli-two-factor-prompt.js +93 -0
  11. package/dist/cli/login/browser-login.d.ts +8 -0
  12. package/dist/cli/login/browser-login.js +115 -0
  13. package/dist/cli/login/index.d.ts +34 -0
  14. package/dist/cli/login/index.js +193 -0
  15. package/dist/cli/login/interactive-login.d.ts +8 -0
  16. package/dist/cli/login/interactive-login.js +59 -0
  17. package/dist/cli/login/netrc-utils.d.ts +22 -0
  18. package/dist/cli/login/netrc-utils.js +85 -0
  19. package/dist/cli/login/oauth.d.ts +20 -0
  20. package/dist/cli/login/oauth.js +142 -0
  21. package/dist/cli/login/sso-login.d.ts +8 -0
  22. package/dist/cli/login/sso-login.js +41 -0
  23. package/dist/cli/login/types.d.ts +42 -0
  24. package/dist/cli/login/types.js +11 -0
  25. package/dist/client/browser-environment-defaults.d.ts +22 -0
  26. package/dist/client/browser-environment-defaults.js +27 -0
  27. package/dist/client/http-error-handler.d.ts +10 -0
  28. package/dist/client/http-error-handler.js +44 -0
  29. package/dist/client/http-request-hooks.d.ts +18 -0
  30. package/dist/client/http-request-hooks.js +62 -0
  31. package/dist/client/index.d.ts +57 -0
  32. package/dist/client/index.js +164 -0
  33. package/dist/client/node-environment-defaults.d.ts +31 -0
  34. package/dist/client/node-environment-defaults.js +68 -0
  35. package/dist/client/service-configurations.d.ts +2 -0
  36. package/dist/client/service-configurations.js +21 -0
  37. package/dist/client/two-factor-authentication-handler.d.ts +16 -0
  38. package/dist/client/two-factor-authentication-handler.js +53 -0
  39. package/dist/debug-loggers.d.ts +6 -0
  40. package/dist/debug-loggers.js +6 -0
  41. package/dist/errors.d.ts +25 -0
  42. package/dist/errors.js +57 -0
  43. package/dist/index.d.ts +6 -0
  44. package/dist/index.js +5 -0
  45. package/dist/types.d.ts +65 -0
  46. package/dist/types.js +1 -0
  47. package/package.json +70 -0
package/README.md ADDED
@@ -0,0 +1,525 @@
1
+ # heroku-fetch
2
+
3
+ A modern JavaScript/TypeScript API client for Heroku APIs, built on the Fetch API and designed to work seamlessly in both Node.js and browser environments.
4
+
5
+ ## Features
6
+
7
+ - ✨ **Universal**: Works in Node.js and browsers
8
+ - 🔐 **Authentication**: Support for bearer tokens and dynamic token providers
9
+ - 🛡️ **2FA Support**: Automatic handling of two-factor authentication challenges
10
+ - 🎯 **Multi-API Support**: Pre-configured for Platform API, Data API, and Particleboard
11
+ - 📊 **Streaming**: Native support for streaming responses and Server-Sent Events
12
+ - 🐛 **Debugging**: Built-in debugging with the `debug` package
13
+ - 💪 **TypeScript**: Full TypeScript support with complete type definitions
14
+ - ⚡ **Modern**: Built on `ky` for a clean, promise-based API
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @heroku/heroku-fetch
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ### Basic Usage
25
+
26
+ ```typescript
27
+ import { HerokuApiClient } from '@heroku/heroku-fetch';
28
+
29
+ // Create a client for the Platform API
30
+ // Automatically uses token from HEROKU_API_KEY env var or ~/.netrc
31
+ const client = new HerokuApiClient({
32
+ service: 'platform',
33
+ });
34
+
35
+ // Make a request
36
+ const response = await client.get('/apps');
37
+ const apps = await response.json();
38
+ console.log(apps);
39
+ ```
40
+
41
+ ### Service Configuration
42
+
43
+ The client comes with pre-configured settings for different Heroku services:
44
+
45
+ ```typescript
46
+ // Platform API (default)
47
+ const platformClient = new HerokuApiClient({
48
+ service: 'platform',
49
+ token: 'your_token',
50
+ });
51
+
52
+ // Data API
53
+ const dataClient = new HerokuApiClient({
54
+ service: 'data',
55
+ token: 'your_token',
56
+ });
57
+
58
+ // Data API with EU region
59
+ const euDataClient = new HerokuApiClient({
60
+ service: 'data',
61
+ region: 'eu',
62
+ token: 'your_token',
63
+ });
64
+
65
+ // Particleboard
66
+ const particleboardClient = new HerokuApiClient({
67
+ service: 'particleboard',
68
+ token: 'your_token',
69
+ });
70
+
71
+ // Custom API
72
+ const customClient = new HerokuApiClient({
73
+ service: 'custom',
74
+ baseUrl: 'https://your-custom-api.heroku.com',
75
+ token: 'your_token',
76
+ });
77
+ ```
78
+
79
+ ## Authentication
80
+
81
+ ### Automatic Token from Environment or Netrc (Default)
82
+
83
+ By default, the client automatically fetches tokens from `HEROKU_API_KEY` environment variable or `~/.netrc` file. **No manual token management required!**
84
+
85
+ ```typescript
86
+ import { HerokuApiClient } from '@heroku/heroku-fetch';
87
+
88
+ // Token automatically loaded from HEROKU_API_KEY or ~/.netrc
89
+ const client = new HerokuApiClient({
90
+ service: 'platform',
91
+ });
92
+ ```
93
+
94
+ The token priority is:
95
+ 1. `HEROKU_API_KEY` environment variable
96
+ 2. `~/.netrc` file (api.heroku.com machine)
97
+
98
+ If you need to manually retrieve the token for other purposes, you can use `getAuthToken()`:
99
+
100
+ ```typescript
101
+ import { getAuthToken } from '@heroku/heroku-fetch';
102
+
103
+ const token = getAuthToken(); // Returns string | undefined
104
+ ```
105
+
106
+ ### Static Bearer Token
107
+
108
+ ```typescript
109
+ const client = new HerokuApiClient({
110
+ service: 'platform',
111
+ token: 'your_static_heroku_bearer_token',
112
+ });
113
+ ```
114
+
115
+ ### Dynamic Token Provider
116
+
117
+ Use a function to dynamically retrieve or refresh tokens:
118
+
119
+ ```typescript
120
+ import { getAuthTokenProvider } from '@heroku/heroku-fetch';
121
+
122
+ // Option 1: Use the built-in provider for dynamic token fetching
123
+ const client = new HerokuApiClient({
124
+ service: 'platform',
125
+ token: getAuthTokenProvider(), // Returns a function that fetches token each time
126
+ });
127
+
128
+ // Option 2: Provide your own custom token function
129
+ const client = new HerokuApiClient({
130
+ service: 'platform',
131
+ token: async () => {
132
+ // Fetch token from secure store or refresh mechanism
133
+ const token = await fetchFreshHerokuToken();
134
+ return token;
135
+ },
136
+ });
137
+ ```
138
+
139
+ ### Two-Factor Authentication
140
+
141
+ Handle 2FA challenges automatically:
142
+
143
+ ```typescript
144
+ const client = new HerokuApiClient({
145
+ service: 'platform',
146
+ token: 'your_token',
147
+ twoFactor: {
148
+ onChallenge: async () => {
149
+ // Prompt user for 2FA code
150
+ const code = await promptUserFor2FA();
151
+ return code;
152
+ },
153
+ },
154
+ });
155
+ ```
156
+
157
+ ## HTTP Methods
158
+
159
+ The client provides convenience methods for common HTTP operations:
160
+
161
+ ### GET
162
+
163
+ ```typescript
164
+ const response = await client.get('/apps');
165
+ const apps = await response.json();
166
+ ```
167
+
168
+ ### POST
169
+
170
+ ```typescript
171
+ const response = await client.post('/apps', {
172
+ name: 'my-new-app',
173
+ region: 'us',
174
+ });
175
+ const app = await response.json();
176
+ ```
177
+
178
+ ### PUT
179
+
180
+ ```typescript
181
+ const response = await client.put('/apps/my-app', {
182
+ maintenance: true,
183
+ });
184
+ ```
185
+
186
+ ### PATCH
187
+
188
+ ```typescript
189
+ const response = await client.patch('/apps/my-app', {
190
+ name: 'renamed-app',
191
+ });
192
+ ```
193
+
194
+ ### DELETE
195
+
196
+ ```typescript
197
+ const response = await client.delete('/apps/my-app');
198
+ ```
199
+
200
+ ## Request Options
201
+
202
+ All HTTP methods accept an optional `RequestOptions` object:
203
+
204
+ ```typescript
205
+ const response = await client.get('/apps', {
206
+ headers: {
207
+ 'X-Custom-Header': 'value',
208
+ },
209
+ timeout: 5000, // Override default timeout
210
+ searchParams: {
211
+ limit: 10,
212
+ offset: 0,
213
+ },
214
+ });
215
+ ```
216
+
217
+ ### Cancellation
218
+
219
+ Pass an `AbortSignal` to cancel an in-flight request. Aborting rejects the
220
+ returned promise with an `AbortError`:
221
+
222
+ ```typescript
223
+ const controller = new AbortController();
224
+
225
+ // Cancel after 2 seconds
226
+ const timer = setTimeout(() => controller.abort(), 2000);
227
+
228
+ try {
229
+ const response = await client.get('/apps', {signal: controller.signal});
230
+ const apps = await response.json();
231
+ clearTimeout(timer);
232
+ console.log(apps);
233
+ } catch (error) {
234
+ if ((error as Error).name === 'AbortError') {
235
+ console.log('Request cancelled');
236
+ } else {
237
+ throw error;
238
+ }
239
+ }
240
+ ```
241
+
242
+ `signal` is also forwarded to `client.stream()`, so the same controller can
243
+ cancel a long-lived streaming response.
244
+
245
+ ## Streaming
246
+
247
+ Stream data from endpoints like Logplex:
248
+
249
+ ```typescript
250
+ const response = await client.stream('/apps/my-app/log-sessions/session-id');
251
+
252
+ // Node.js - use the response body as a stream
253
+ if (response.body) {
254
+ const reader = response.body.getReader();
255
+ const decoder = new TextDecoder();
256
+
257
+ while (true) {
258
+ const { done, value } = await reader.read();
259
+ if (done) break;
260
+
261
+ const chunk = decoder.decode(value, { stream: true });
262
+ console.log(chunk);
263
+ }
264
+ }
265
+ ```
266
+
267
+ ### Server-Sent Events (SSE)
268
+
269
+ ```typescript
270
+ const response = await client.stream('/apps/my-app/log-sessions/session-id');
271
+
272
+ // Process SSE events
273
+ const reader = response.body?.getReader();
274
+ const decoder = new TextDecoder();
275
+
276
+ if (reader) {
277
+ while (true) {
278
+ const { done, value } = await reader.read();
279
+ if (done) break;
280
+
281
+ const text = decoder.decode(value);
282
+ // Parse SSE format: "data: {...}\n\n"
283
+ const events = text.split('\n\n').filter(Boolean);
284
+
285
+ for (const event of events) {
286
+ if (event.startsWith('data: ')) {
287
+ const data = event.slice(6);
288
+ console.log('Event:', data);
289
+ }
290
+ }
291
+ }
292
+ }
293
+ ```
294
+
295
+ ## Error Handling
296
+
297
+ The client throws specific error types for different scenarios:
298
+
299
+ ```typescript
300
+ import {
301
+ HerokuApiError,
302
+ AuthenticationError,
303
+ NotFoundError,
304
+ TwoFactorRequiredError,
305
+ RateLimitError,
306
+ } from '@heroku/heroku-fetch';
307
+
308
+ try {
309
+ const response = await client.get('/apps/nonexistent');
310
+ } catch (error) {
311
+ if (error instanceof NotFoundError) {
312
+ console.error('App not found');
313
+ } else if (error instanceof AuthenticationError) {
314
+ console.error('Invalid credentials');
315
+ } else if (error instanceof RateLimitError) {
316
+ console.error(`Rate limited. Retry after ${error.retryAfter} seconds`);
317
+ } else if (error instanceof TwoFactorRequiredError) {
318
+ console.error('2FA required but not configured');
319
+ } else if (error instanceof HerokuApiError) {
320
+ console.error(`API Error: ${error.message}`);
321
+ console.error(`Status: ${error.statusCode}`);
322
+ console.error(`ID: ${error.id}`);
323
+ console.error(`Errors: ${JSON.stringify(error.errors)}`);
324
+ }
325
+ }
326
+ ```
327
+
328
+ ## Debugging
329
+
330
+ Enable debugging output using the `DEBUG` environment variable (Node.js) or `localStorage.debug` (browser):
331
+
332
+ ```bash
333
+ # Enable all heroku-fetch debugging
334
+ DEBUG=heroku-fetch:* node your-script.js
335
+
336
+ # Enable specific namespaces
337
+ DEBUG=heroku-fetch:request,heroku-fetch:response node your-script.js
338
+ ```
339
+
340
+ Available debug namespaces:
341
+ - `heroku-fetch:request` - Outgoing HTTP requests
342
+ - `heroku-fetch:response` - Incoming HTTP responses
343
+ - `heroku-fetch:auth` - Authentication and token management
344
+ - `heroku-fetch:error` - Error details
345
+
346
+ In the browser:
347
+ ```javascript
348
+ localStorage.debug = 'heroku-fetch:*';
349
+ ```
350
+
351
+ ## Configuration Options
352
+
353
+ ```typescript
354
+ interface HerokuApiClientOptions {
355
+ /** Heroku service type */
356
+ service?: 'platform' | 'data' | 'particleboard' | 'custom';
357
+
358
+ /** Static bearer token or function to retrieve token */
359
+ token?: string | (() => string | Promise<string>);
360
+
361
+ /** Two-factor authentication configuration */
362
+ twoFactor?: {
363
+ onChallenge: () => string | Promise<string>;
364
+ };
365
+
366
+ /** Custom base URL (required for 'custom' service) */
367
+ baseUrl?: string;
368
+
369
+ /** Service region (e.g., 'eu', 'us') */
370
+ region?: string;
371
+
372
+ /** Request timeout in milliseconds (default: 30000) */
373
+ timeout?: number;
374
+
375
+ /** Additional custom headers */
376
+ headers?: Record<string, string>;
377
+
378
+ /** Enable debug output */
379
+ debug?: boolean;
380
+ }
381
+ ```
382
+
383
+ ## Updating Options
384
+
385
+ You can update client options after instantiation:
386
+
387
+ ```typescript
388
+ const client = new HerokuApiClient({ service: 'platform' });
389
+
390
+ // Update token
391
+ client.setOption('token', 'new_token');
392
+
393
+ // Update timeout
394
+ client.setOption('timeout', 5000);
395
+ ```
396
+
397
+ ## TypeScript Support
398
+
399
+ The library is written in TypeScript and provides full type definitions:
400
+
401
+ ```typescript
402
+ import type {
403
+ HerokuApiClientOptions,
404
+ RequestOptions,
405
+ HerokuService,
406
+ TokenProvider,
407
+ } from '@heroku/heroku-fetch';
408
+ ```
409
+
410
+ ## Examples
411
+
412
+ ### Create and Deploy an App
413
+
414
+ ```typescript
415
+ const client = new HerokuApiClient({
416
+ service: 'platform',
417
+ token: process.env.HEROKU_TOKEN,
418
+ });
419
+
420
+ // Create app
421
+ const createResponse = await client.post('/apps', {
422
+ name: 'my-awesome-app',
423
+ region: 'us',
424
+ });
425
+ const app = await createResponse.json();
426
+ console.log('Created app:', app.name);
427
+
428
+ // Get app details
429
+ const appResponse = await client.get(`/apps/${app.name}`);
430
+ const appDetails = await appResponse.json();
431
+ console.log('App details:', appDetails);
432
+ ```
433
+
434
+ ### Stream Logs
435
+
436
+ ```typescript
437
+ const client = new HerokuApiClient({
438
+ service: 'platform',
439
+ token: process.env.HEROKU_TOKEN,
440
+ });
441
+
442
+ // Create log session
443
+ const sessionResponse = await client.post('/apps/my-app/log-sessions', {
444
+ dyno: 'web.1',
445
+ lines: 100,
446
+ tail: true,
447
+ });
448
+ const session = await sessionResponse.json();
449
+
450
+ // Stream logs
451
+ const logsResponse = await client.stream(session.logplex_url);
452
+ const reader = logsResponse.body?.getReader();
453
+ const decoder = new TextDecoder();
454
+
455
+ if (reader) {
456
+ while (true) {
457
+ const { done, value } = await reader.read();
458
+ if (done) break;
459
+
460
+ const logs = decoder.decode(value, { stream: true });
461
+ process.stdout.write(logs);
462
+ }
463
+ }
464
+ ```
465
+
466
+ ### Work with Postgres
467
+
468
+ ```typescript
469
+ const client = new HerokuApiClient({
470
+ service: 'data',
471
+ token: process.env.HEROKU_TOKEN,
472
+ });
473
+
474
+ // List databases
475
+ const response = await client.get('/databases');
476
+ const databases = await response.json();
477
+ console.log('Databases:', databases);
478
+ ```
479
+
480
+ ### Oclif CLI Commands
481
+
482
+ Complete examples for building oclif CLI commands are available in `examples/oclif/`:
483
+
484
+ ```typescript
485
+ import { Command } from '@oclif/core';
486
+ import { HerokuApiClient } from '@heroku/heroku-fetch';
487
+
488
+ export default class AppsList extends Command {
489
+ async run() {
490
+ // Client automatically uses token from env or netrc
491
+ const client = new HerokuApiClient({
492
+ service: 'platform',
493
+ });
494
+
495
+ const response = await client.get('/apps');
496
+ const apps = await response.json();
497
+
498
+ // Display apps...
499
+ }
500
+ }
501
+ ```
502
+
503
+ See [examples/oclif/README.md](examples/oclif/README.md) for complete working examples including:
504
+ - Listing apps with table formatting
505
+ - Creating apps with validation
506
+ - Streaming logs in real-time
507
+ - Error handling patterns
508
+ - 2FA support
509
+
510
+ ## Contributing
511
+
512
+ Contributions are welcome! Please see the repository for contribution guidelines.
513
+
514
+ ## License
515
+
516
+ MIT
517
+
518
+ ## Related Projects
519
+
520
+ - [ky](https://github.com/sindresorhus/ky) - The underlying HTTP client
521
+ - [debug](https://github.com/debug-js/debug) - Debugging utility
522
+
523
+ ## Support
524
+
525
+ For issues and questions, please visit the [GitHub repository](https://github.com/heroku/heroku-fetch).
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Authentication utilities for Heroku API
3
+ * Handles token retrieval from environment variables and netrc file
4
+ */
5
+ /**
6
+ * Get the Heroku API token from environment variable or netrc file
7
+ *
8
+ * Priority:
9
+ * 1. HEROKU_API_KEY environment variable
10
+ * 2. ~/.netrc file (uses api.heroku.com or HEROKU_HOST if set)
11
+ *
12
+ * @returns The API token or undefined if not found
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { getAuthToken, HerokuApiClient } from '@heroku/heroku-fetch';
17
+ *
18
+ * const token = getAuthToken();
19
+ * const client = new HerokuApiClient({
20
+ * service: 'platform',
21
+ * token,
22
+ * });
23
+ * ```
24
+ */
25
+ export declare function getAuthToken(): string | undefined;
26
+ /**
27
+ * Get the API host from environment or default
28
+ *
29
+ * @returns The API host (default: 'api.heroku.com')
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const host = getApiHost();
34
+ * // Returns 'api.heroku.com' or value of HEROKU_HOST env var
35
+ * ```
36
+ */
37
+ export declare function getApiHost(): string;
38
+ /**
39
+ * Get the full API URL from environment or default
40
+ *
41
+ * @returns The API URL (default: 'https://api.heroku.com')
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * const url = getApiUrl();
46
+ * // Returns 'https://api.heroku.com' or https://{HEROKU_HOST}
47
+ * ```
48
+ */
49
+ export declare function getApiUrl(): string;
50
+ /**
51
+ * Create a token provider function for use with HerokuApiClient
52
+ * This is useful when you want the token to be fetched dynamically
53
+ *
54
+ * @returns A function that returns the current auth token
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * import { getAuthTokenProvider, HerokuApiClient } from '@heroku/heroku-fetch';
59
+ *
60
+ * const client = new HerokuApiClient({
61
+ * service: 'platform',
62
+ * token: getAuthTokenProvider(),
63
+ * });
64
+ * ```
65
+ */
66
+ export declare function getAuthTokenProvider(): () => string | undefined;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Authentication utilities for Heroku API
3
+ * Handles token retrieval from environment variables and netrc file
4
+ */
5
+ import { Netrc } from 'netrc-parser';
6
+ // Defer netrc instantiation to avoid eager .netrc file operations at module load time
7
+ let _netrc;
8
+ function getNetrc() {
9
+ if (!_netrc) {
10
+ _netrc = new Netrc();
11
+ }
12
+ return _netrc;
13
+ }
14
+ /**
15
+ * Get the Heroku API token from environment variable or netrc file
16
+ *
17
+ * Priority:
18
+ * 1. HEROKU_API_KEY environment variable
19
+ * 2. ~/.netrc file (uses api.heroku.com or HEROKU_HOST if set)
20
+ *
21
+ * @returns The API token or undefined if not found
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * import { getAuthToken, HerokuApiClient } from '@heroku/heroku-fetch';
26
+ *
27
+ * const token = getAuthToken();
28
+ * const client = new HerokuApiClient({
29
+ * service: 'platform',
30
+ * token,
31
+ * });
32
+ * ```
33
+ */
34
+ export function getAuthToken() {
35
+ // Check environment variable first
36
+ let token = process.env.HEROKU_API_KEY;
37
+ if (!token) {
38
+ // Fall back to netrc
39
+ const netrc = getNetrc();
40
+ netrc.loadSync();
41
+ const apiHost = getApiHost();
42
+ token = netrc.machines[apiHost]?.password;
43
+ }
44
+ return token;
45
+ }
46
+ /**
47
+ * Get the API host from environment or default
48
+ *
49
+ * @returns The API host (default: 'api.heroku.com')
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * const host = getApiHost();
54
+ * // Returns 'api.heroku.com' or value of HEROKU_HOST env var
55
+ * ```
56
+ */
57
+ export function getApiHost() {
58
+ return process.env.HEROKU_HOST || 'api.heroku.com';
59
+ }
60
+ /**
61
+ * Get the full API URL from environment or default
62
+ *
63
+ * @returns The API URL (default: 'https://api.heroku.com')
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const url = getApiUrl();
68
+ * // Returns 'https://api.heroku.com' or https://{HEROKU_HOST}
69
+ * ```
70
+ */
71
+ export function getApiUrl() {
72
+ const host = getApiHost();
73
+ return `https://${host}`;
74
+ }
75
+ /**
76
+ * Create a token provider function for use with HerokuApiClient
77
+ * This is useful when you want the token to be fetched dynamically
78
+ *
79
+ * @returns A function that returns the current auth token
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * import { getAuthTokenProvider, HerokuApiClient } from '@heroku/heroku-fetch';
84
+ *
85
+ * const client = new HerokuApiClient({
86
+ * service: 'platform',
87
+ * token: getAuthTokenProvider(),
88
+ * });
89
+ * ```
90
+ */
91
+ export function getAuthTokenProvider() {
92
+ return () => getAuthToken();
93
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Browser-specific entry point for @heroku/heroku-fetch
3
+ *
4
+ * This entry point excludes Node.js-specific features like:
5
+ * - CLI utilities (login, 2FA prompts)
6
+ * - File system access (netrc)
7
+ * - Process environment variables
8
+ *
9
+ * Use this entry point when bundling for browser environments.
10
+ */
11
+ export { HerokuApiClient } from './client/index.js';
12
+ export { AuthenticationError, HerokuApiError, NotFoundError, RateLimitError, TwoFactorRequiredError, } from './errors.js';
13
+ export type { HerokuApiClientOptions, HerokuError, HerokuErrorResponse, HerokuService, RequestOptions, ServiceConfig, TokenProvider, TwoFactorOptions, } from './types.js';
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Browser-specific entry point for @heroku/heroku-fetch
3
+ *
4
+ * This entry point excludes Node.js-specific features like:
5
+ * - CLI utilities (login, 2FA prompts)
6
+ * - File system access (netrc)
7
+ * - Process environment variables
8
+ *
9
+ * Use this entry point when bundling for browser environments.
10
+ */
11
+ export { HerokuApiClient } from './client/index.js';
12
+ export { AuthenticationError, HerokuApiError, NotFoundError, RateLimitError, TwoFactorRequiredError, } from './errors.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * CLI Login Module
3
+ *
4
+ * Re-exports the Login class from the login subfolder.
5
+ * This file maintains backward compatibility with the original import path.
6
+ */
7
+ export { Login, type LoginOptions } from './login/index.js';