oauth2-cli 0.8.3 → 0.8.5

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
4
4
 
5
+ ## [0.8.5](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.8.4...oauth2-cli/0.8.5) (2026-02-19)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * include error response when unparseable as JSON ([0138b14](https://github.com/battis/oauth2-cli/commit/0138b145b564be46e9dbcda0b546305375839826))
11
+
12
+ ## [0.8.4](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.8.3...oauth2-cli/0.8.4) (2026-02-19)
13
+
14
+
15
+ ### Features
16
+
17
+ * human-readable client name for clarity ([68b4287](https://github.com/battis/oauth2-cli/commit/68b42872998ec423440d07447012282528e3ee76))
18
+
5
19
  ## [0.8.3](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.8.2...oauth2-cli/0.8.3) (2026-02-18)
6
20
 
7
21
 
package/dist/Client.d.ts CHANGED
@@ -14,6 +14,8 @@ import * as Token from './Token/index.js';
14
14
  */
15
15
  export declare const DEFAULT_REDIRECT_URI = "http://localhost:3000/oauth2-cli/redirect";
16
16
  export type ClientOptions<C extends Credentials = Credentials> = {
17
+ /** Human-readable name for client in messages */
18
+ name?: string;
17
19
  /** Credentials for server access */
18
20
  credentials: C;
19
21
  /** Optional request components to inject */
@@ -66,6 +68,7 @@ type GetTokenOptions = {
66
68
  */
67
69
  export declare class Client<C extends Credentials = Credentials> extends EventEmitter {
68
70
  static readonly TokenEvent = "token";
71
+ readonly name?: string;
69
72
  protected credentials: C;
70
73
  protected base_url?: requestish.URL.ish;
71
74
  protected config?: OpenIDClient.Configuration;
@@ -74,7 +77,8 @@ export declare class Client<C extends Credentials = Credentials> extends EventEm
74
77
  private token?;
75
78
  private tokenLock;
76
79
  private storage?;
77
- constructor({ credentials, base_url, views, inject, storage }: ClientOptions<C>);
80
+ constructor({ name, credentials, base_url, views, inject, storage }: ClientOptions<C>);
81
+ clientName(): string;
78
82
  get redirect_uri(): requestish.URL.ish;
79
83
  /**
80
84
  * @throws IndeterminateConfiguration if provided credentials combined with
package/dist/Client.js CHANGED
@@ -19,6 +19,7 @@ export const DEFAULT_REDIRECT_URI = 'http://localhost:3000/oauth2-cli/redirect';
19
19
  */
20
20
  export class Client extends EventEmitter {
21
21
  static TokenEvent = 'token';
22
+ name;
22
23
  credentials;
23
24
  base_url;
24
25
  config;
@@ -27,14 +28,21 @@ export class Client extends EventEmitter {
27
28
  token;
28
29
  tokenLock = new Mutex();
29
30
  storage;
30
- constructor({ credentials, base_url, views, inject, storage }) {
31
+ constructor({ name, credentials, base_url, views, inject, storage }) {
31
32
  super();
33
+ this.name = name;
32
34
  this.credentials = credentials;
33
35
  this.base_url = base_url;
34
36
  this.views = views;
35
37
  this.inject = inject;
36
38
  this.storage = storage;
37
39
  }
40
+ clientName() {
41
+ if (this.name && this.name.length > 0) {
42
+ return this.name;
43
+ }
44
+ return 'oauth2-cli';
45
+ }
38
46
  get redirect_uri() {
39
47
  return this.credentials.redirect_uri;
40
48
  }
@@ -61,7 +69,7 @@ export class Client extends EventEmitter {
61
69
  }, this.credentials.client_id, { client_secret: this.credentials.client_secret });
62
70
  }
63
71
  if (!this.config) {
64
- throw new Error('The client configuration could not be constructed from provided credentials.', {
72
+ throw new Error(`The ${this.clientName()} configuration could not be constructed from provided credentials.`, {
65
73
  cause: {
66
74
  credentials: this.credentials,
67
75
  'OpenID configuration result': error
@@ -121,7 +129,7 @@ export class Client extends EventEmitter {
121
129
  : undefined));
122
130
  }
123
131
  catch (cause) {
124
- session.reject(new Error('Error making Authorization Code Grant request', { cause }));
132
+ session.reject(new Error(`Error making ${this.clientName()} Authorization Code Grant request`, { cause }));
125
133
  }
126
134
  }
127
135
  async refreshTokenGrant({ refresh_token = this.token?.refresh_token, inject: request } = {}) {
@@ -161,7 +169,7 @@ export class Client extends EventEmitter {
161
169
  async save(token) {
162
170
  this.token = token;
163
171
  if (!token.access_token) {
164
- throw new Error('No access_token in response.', {
172
+ throw new Error(`No access_token in response to ${this.clientName()}.`, {
165
173
  cause: token
166
174
  });
167
175
  }
@@ -190,7 +198,7 @@ export class Client extends EventEmitter {
190
198
  requestish.URL.toString(this.base_url || this.credentials.issuer), requestish.URL.toString(url).replace(/^\/?/, ''));
191
199
  }
192
200
  else {
193
- throw new Error(`Invalid request URL "${url}"`, {
201
+ throw new Error(`Invalid request URL "${url}" to ${this.clientName()}`, {
194
202
  cause: {
195
203
  base_url: this.base_url,
196
204
  issuer: this.credentials.issuer,
@@ -221,8 +229,15 @@ export class Client extends EventEmitter {
221
229
  return (await response.json());
222
230
  }
223
231
  else {
224
- throw new Error('The response could not be parsed as JSON.', {
225
- cause: response
232
+ throw new Error(`The response could not be parsed as JSON by ${this.clientName()}.`, {
233
+ cause: {
234
+ response: {
235
+ status: response.status,
236
+ statusText: response.statusText,
237
+ headers: Object.fromEntries(response.headers.entries()),
238
+ body: await response.text()
239
+ }
240
+ }
226
241
  });
227
242
  }
228
243
  }
package/dist/Session.d.ts CHANGED
@@ -13,7 +13,7 @@ export type SessionOptions = {
13
13
  };
14
14
  export type SessionResolver = (response: Token.Response) => void | Promise<void>;
15
15
  export declare class Session {
16
- private readonly client;
16
+ readonly client: Client;
17
17
  private readonly outOfBandRedirectServer;
18
18
  /** PKCE code_verifier */
19
19
  readonly code_verifier: string;
package/dist/Session.js CHANGED
@@ -20,16 +20,16 @@ export class Session {
20
20
  */
21
21
  get resolve() {
22
22
  if (!this._resolve) {
23
- throw new Error(`Session resolve method is ${this._resolve}`);
23
+ throw new Error(`${this.client.clientName()}'s Session resolve method is ${this._resolve}`);
24
24
  }
25
25
  return this._resolve;
26
26
  }
27
27
  reject(cause) {
28
- throw new Error('Session failed', { cause });
28
+ throw new Error(`${this.client.clientName()}'s Session failed`, { cause });
29
29
  }
30
30
  constructor({ client, views, inject: request }) {
31
- this.spinner = ora('Awaiting interactive authorization').start();
32
31
  this.client = client;
32
+ this.spinner = ora(`${this.client.clientName()} awaiting interactive authorization`).start();
33
33
  this.inject = request;
34
34
  this.outOfBandRedirectServer = this.instantiateWebServer({ views });
35
35
  }
@@ -47,17 +47,16 @@ export class Session {
47
47
  try {
48
48
  this._resolve = (response) => {
49
49
  let closed = false;
50
- this.spinner.text =
51
- 'Waiting for out-of-band redirect server to shut down';
50
+ this.spinner.text = `${this.client.clientName()} waiting for out-of-band redirect server to shut down`;
52
51
  this.outOfBandRedirectServer.close().then(() => {
53
52
  closed = true;
54
- this.spinner.succeed('Interactive authorization complete');
53
+ this.spinner.succeed(`Interactive authorization for ${this.client.clientName()} complete`);
55
54
  resolve(response);
56
55
  });
57
56
  setTimeout(() => {
58
57
  if (!closed) {
59
58
  this.spinner.text =
60
- 'Still waiting for out-of-band redirect server to shut down.\n' +
59
+ `Still waiting for out-of-band redirect server for ${this.client.clientName()} to shut down.\n` +
61
60
  ' Your browser may be holding the connection to the server open.\n\n' +
62
61
  ' Please close the "Authorization Complete" tab in your browser.';
63
62
  }
@@ -65,7 +64,7 @@ export class Session {
65
64
  setTimeout(() => {
66
65
  if (!closed) {
67
66
  this.spinner.text =
68
- 'Still waiting for out-of-band redirect server to shut down.\n' +
67
+ `Still waiting for out-of-band redirect server for ${this.client.clientName()} to shut down.\n` +
69
68
  ' Your browser may be holding the connection to the server open.\n\n' +
70
69
  ' Please close the browser window.';
71
70
  }
@@ -73,7 +72,7 @@ export class Session {
73
72
  setTimeout(() => {
74
73
  if (!closed) {
75
74
  this.spinner.text =
76
- 'Still waiting for out-of-band redirect server to shut down.\n' +
75
+ `Still waiting for out-of-band redirect server for ${this.client.clientName()} to shut down.\n` +
77
76
  ' Your browser may be holding the connection to the server open.\n\n' +
78
77
  ' Please quit the browser.';
79
78
  }
@@ -83,14 +82,13 @@ export class Session {
83
82
  .expand(this.outOfBandRedirectServer.authorization_endpoint, this.client.redirect_uri)
84
83
  .toString();
85
84
  //open(url);
86
- this.spinner.text = `Please continue interactive authorization at ${Colors.url(url)} in your browser`;
85
+ this.spinner.text = `Please continue interactive authorization for ${this.client.clientName()} at ${Colors.url(url)} in your browser`;
87
86
  }
88
87
  catch (cause) {
89
- this.spinner.text =
90
- 'Waiting for out-of-band redirect server to shut down';
88
+ this.spinner.text = `Waiting for out-of-band redirect server for ${this.client.clientName()} to shut down`;
91
89
  this.outOfBandRedirectServer.close().then(() => {
92
- this.spinner.fail('Interactive authorization failed');
93
- reject(new Error('Error in Authorization Code flow', { cause }));
90
+ this.spinner.fail(`Interactive authorization for ${this.client.clientName()} failed`);
91
+ reject(new Error(`Error in Authorization Code flow for ${this.client.clientName()}`, { cause }));
94
92
  });
95
93
  }
96
94
  });
@@ -107,8 +105,7 @@ export class Session {
107
105
  * Code Grant flow
108
106
  */
109
107
  async handleAuthorizationCodeRedirect(req) {
110
- this.spinner.text =
111
- 'Completing access token request with provided authorization code';
108
+ this.spinner.text = `Completing access token request fro ${this.client.clientName()} with provided authorization code`;
112
109
  return await this.client.handleAuthorizationCodeRedirect(req, this);
113
110
  }
114
111
  }
package/dist/WebServer.js CHANGED
@@ -65,11 +65,12 @@ export class WebServer {
65
65
  this.views = views;
66
66
  }
67
67
  async render(res, template, data = {}) {
68
+ const name = this.session.client.clientName();
68
69
  async function attemptToRender(views) {
69
70
  if (ejs && views) {
70
71
  const viewPath = path.resolve(import.meta.dirname, views, template);
71
72
  if (fs.existsSync(viewPath)) {
72
- res.send(await ejs.renderFile(viewPath, data));
73
+ res.send(await ejs.renderFile(viewPath, { name, ...data }));
73
74
  return true;
74
75
  }
75
76
  }
@@ -91,12 +92,15 @@ export class WebServer {
91
92
  try {
92
93
  await this.session.handleAuthorizationCodeRedirect(req);
93
94
  if (!(await this.render(res, 'complete.ejs'))) {
94
- res.send('Authorization complete. You may close this window.');
95
+ res.send(`${this.session.client.clientName()} authorization complete. You may close this window.`);
95
96
  }
96
97
  }
97
98
  catch (error) {
98
99
  if (!(await this.render(res, 'error.ejs', { error }))) {
99
- res.send(error);
100
+ res.send({
101
+ client: this.session.client.clientName(),
102
+ error
103
+ });
100
104
  }
101
105
  }
102
106
  }
@@ -105,7 +109,7 @@ export class WebServer {
105
109
  return new Promise((resolve, reject) => {
106
110
  this.server.close((cause) => {
107
111
  if (cause) {
108
- reject(new Error('Error shutting down out-of-band redirect web server', {
112
+ reject(new Error(`Error shutting down ${this.session.client.clientName()} out-of-band redirect web server`, {
109
113
  cause
110
114
  }));
111
115
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oauth2-cli",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "Acquire API access tokens via OAuth 2.0 within CLI tools",
5
5
  "homepage": "https://github.com/battis/oauth2-cli/tree/main/packages/oauth2-cli#readme",
6
6
  "repository": {
@@ -30,7 +30,10 @@
30
30
  <body>
31
31
  <div class="wrapper">
32
32
  <div class="center container">
33
- <h1>Authorization Complete</h1>
33
+ <h1>
34
+ <%= name %>
35
+ Authorization Complete
36
+ </h1>
34
37
  <p>You may close this window.</p>
35
38
  </div>
36
39
  </div>
package/views/error.ejs CHANGED
@@ -30,7 +30,10 @@
30
30
  <body>
31
31
  <div class="wrapper">
32
32
  <div class="center container">
33
- <h1>Authorization Error</h1>
33
+ <h1>
34
+ <%= name %>
35
+ Authorization Error
36
+ </h1>
34
37
  <div class="alert alert-danger" role="alert">
35
38
  <pre><%= JSON.stringify(error, null, 2) %></pre>
36
39
  </div>