oauth2-cli 0.7.3 → 0.8.1

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,115 +2,132 @@
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.7.3](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.7.2...oauth2-cli/0.7.3) (2026-02-17)
5
+ ## [0.8.1](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.8.0...oauth2-cli/0.8.1) (2026-02-18)
6
6
 
7
7
 
8
- ### Bug Fixes
8
+ ### Features
9
9
 
10
- * push past failed well-known URL ([48eca87](https://github.com/battis/oauth2-cli/commit/48eca875e9fffe30adc88ad1b5fdf0202722bb12))
10
+ * provide parameterized credentials with simplified typing ([5a92c67](https://github.com/battis/oauth2-cli/commit/5a92c67dbd4ab52fa4f0b02a910e788f5ae67adb))
11
11
 
12
- ## [0.7.2](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.7.1...oauth2-cli/0.7.2) (2026-02-16)
12
+ ## [0.8.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.7.3...oauth2-cli/0.8.0) (2026-02-17)
13
+
14
+ ### ⚠ BREAKING CHANGES
15
+
16
+ - clarify subclass groupings and extensibility
17
+ - simplify credentials structure
18
+ - rename Token.TokenStorage to less redundant Token.Storage
19
+ - simplify namespacing of Injection and Scope
20
+ - improved clarity of errors and causes
13
21
 
22
+ ### Features
23
+
24
+ - base_url for API requests preempts issuer, if present ([972496a](https://github.com/battis/oauth2-cli/commit/972496a663751c12dce7271b33134c8055d84191))
25
+ - clarify subclass groupings and extensibility ([4fec372](https://github.com/battis/oauth2-cli/commit/4fec372019603c4bfada0e26d1813b3c196db536))
26
+ - rename Token.TokenStorage to less redundant Token.Storage ([149d65a](https://github.com/battis/oauth2-cli/commit/149d65ac218a2c230ed8bca76963e44a5a6ff441))
27
+ - simplify credentials structure ([0e95439](https://github.com/battis/oauth2-cli/commit/0e95439a30f78268ddf7363dc4feeb0b1ff0edba))
28
+ - simplify namespacing of Injection and Scope ([b5db750](https://github.com/battis/oauth2-cli/commit/b5db7503f557a0c2092d327742b1bdd82be0edbb))
14
29
 
15
30
  ### Bug Fixes
16
31
 
17
- * resolve remaining requestish requests correctly ([2be680c](https://github.com/battis/oauth2-cli/commit/2be680c9575bcfe9e816e450c85b94ccf5c8f950))
32
+ - export Scope without accidentally registering plugin ([3816537](https://github.com/battis/oauth2-cli/commit/38165376d6581b323cbb141a4923cd5613edeb63))
33
+ - improved clarity of errors and causes ([9f1ddce](https://github.com/battis/oauth2-cli/commit/9f1ddcec82c3295e39fc8857784634da072e7570))
34
+ - treat base_url as true base URL ([8a4b76c](https://github.com/battis/oauth2-cli/commit/8a4b76cb48041e31c7d0a72adb0312febad3ff28))
18
35
 
19
- ## [0.7.1](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.7.0...oauth2-cli/0.7.1) (2026-02-16)
36
+ ## [0.7.3](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.7.2...oauth2-cli/0.7.3) (2026-02-17)
20
37
 
21
- ## [0.7.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.6.0...oauth2-cli/0.7.0) (2026-02-16)
38
+ ### Bug Fixes
39
+
40
+ - push past failed well-known URL ([48eca87](https://github.com/battis/oauth2-cli/commit/48eca875e9fffe30adc88ad1b5fdf0202722bb12))
41
+
42
+ ## [0.7.2](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.7.1...oauth2-cli/0.7.2) (2026-02-16)
43
+
44
+ ### Bug Fixes
22
45
 
46
+ - resolve remaining requestish requests correctly ([2be680c](https://github.com/battis/oauth2-cli/commit/2be680c9575bcfe9e816e450c85b94ccf5c8f950))
47
+
48
+ ## [0.7.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.6.0...oauth2-cli/0.7.0) (2026-02-16)
23
49
 
24
50
  ### ⚠ BREAKING CHANGES
25
51
 
26
- * make more properties of Client accessible to subclasses
52
+ - make more properties of Client accessible to subclasses
27
53
 
28
54
  ### Features
29
55
 
30
- * make more properties of Client accessible to subclasses ([74ef874](https://github.com/battis/oauth2-cli/commit/74ef874804323a9c3c496ddf7b0e24bac9e671e1))
56
+ - make more properties of Client accessible to subclasses ([74ef874](https://github.com/battis/oauth2-cli/commit/74ef874804323a9c3c496ddf7b0e24bac9e671e1))
31
57
 
32
58
  ## [0.6.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.5.1...oauth2-cli/0.6.0) (2026-02-15)
33
59
 
34
-
35
60
  ### ⚠ BREAKING CHANGES
36
61
 
37
- * limit TokenStorage to storing _only_ refresh_tokens
38
- * improve express shutdown, refactor entire package
62
+ - limit TokenStorage to storing _only_ refresh_tokens
63
+ - improve express shutdown, refactor entire package
39
64
 
40
65
  ### Features
41
66
 
42
- * compatible with @battis/google-cloud-run-to-localhost ([3e449b1](https://github.com/battis/oauth2-cli/commit/3e449b14d546759f7e6543c86350ea83b60a80a7))
43
- * display authorization starting URL on command line as well as opening browser ([fb72bcf](https://github.com/battis/oauth2-cli/commit/fb72bcffafaf66453f8f8f0f8af4b27ef11827c6))
44
- * externalize path/port identification to gcrtl ([0f6c28b](https://github.com/battis/oauth2-cli/commit/0f6c28b31a7888eac524b28bcdc9c8eabbf57d91))
45
- * fallback to package templates if ejs present but no alternative template providedd ([6b05454](https://github.com/battis/oauth2-cli/commit/6b05454976b1fb4144f91ba51fc1c9331f1c0f34))
46
- * limit TokenStorage to storing _only_ refresh_tokens ([3de9c96](https://github.com/battis/oauth2-cli/commit/3de9c96510d15eebd51a0be7d8df278614541f95))
47
-
67
+ - compatible with @battis/google-cloud-run-to-localhost ([3e449b1](https://github.com/battis/oauth2-cli/commit/3e449b14d546759f7e6543c86350ea83b60a80a7))
68
+ - display authorization starting URL on command line as well as opening browser ([fb72bcf](https://github.com/battis/oauth2-cli/commit/fb72bcffafaf66453f8f8f0f8af4b27ef11827c6))
69
+ - externalize path/port identification to gcrtl ([0f6c28b](https://github.com/battis/oauth2-cli/commit/0f6c28b31a7888eac524b28bcdc9c8eabbf57d91))
70
+ - fallback to package templates if ejs present but no alternative template providedd ([6b05454](https://github.com/battis/oauth2-cli/commit/6b05454976b1fb4144f91ba51fc1c9331f1c0f34))
71
+ - limit TokenStorage to storing _only_ refresh_tokens ([3de9c96](https://github.com/battis/oauth2-cli/commit/3de9c96510d15eebd51a0be7d8df278614541f95))
48
72
 
49
73
  ### Bug Fixes
50
74
 
51
- * attempt to authorize and retry when encountering 401 error ([bc75fed](https://github.com/battis/oauth2-cli/commit/bc75fed052b548e41411287f7d98fa78c3f27ee5))
52
- * improve express shutdown, refactor entire package ([a740313](https://github.com/battis/oauth2-cli/commit/a740313c33d26f07ebab5b282607d8828cf3c3a7))
75
+ - attempt to authorize and retry when encountering 401 error ([bc75fed](https://github.com/battis/oauth2-cli/commit/bc75fed052b548e41411287f7d98fa78c3f27ee5))
76
+ - improve express shutdown, refactor entire package ([a740313](https://github.com/battis/oauth2-cli/commit/a740313c33d26f07ebab5b282607d8828cf3c3a7))
53
77
 
54
78
  ## [0.5.1](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.5.0...oauth2-cli/0.5.1) (2026-01-20)
55
79
 
56
-
57
80
  ### Bug Fixes
58
81
 
59
- * allow extending private methods for debugging ([ea9957f](https://github.com/battis/oauth2-cli/commit/ea9957f71629c4a177ebdf6acf0aecaa299a5260))
82
+ - allow extending private methods for debugging ([ea9957f](https://github.com/battis/oauth2-cli/commit/ea9957f71629c4a177ebdf6acf0aecaa299a5260))
60
83
 
61
84
  ## [0.5.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.4.0...oauth2-cli/0.5.0) (2026-01-14)
62
85
 
63
-
64
86
  ### ⚠ BREAKING CHANGES
65
87
 
66
- * move to Node.js v24 support
88
+ - move to Node.js v24 support
67
89
 
68
90
  ### Features
69
91
 
70
- * move to Node.js v24 support ([03d5cf4](https://github.com/battis/oauth2-cli/commit/03d5cf455e38f7beb2fbf93f1612acb906c5f5a0))
92
+ - move to Node.js v24 support ([03d5cf4](https://github.com/battis/oauth2-cli/commit/03d5cf455e38f7beb2fbf93f1612acb906c5f5a0))
71
93
 
72
94
  ## [0.4.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.3.0...oauth2-cli/0.4.0) (2026-01-04)
73
95
 
74
-
75
96
  ### ⚠ BREAKING CHANGES
76
97
 
77
- * remove deprecated TokenManager
98
+ - remove deprecated TokenManager
78
99
 
79
100
  ### Features
80
101
 
81
- * provide fetch() and fetchJSON() methods to translate to openid-client requests ([3fe454f](https://github.com/battis/oauth2-cli/commit/3fe454f28497d704041ea4e599a4ad5b2b08b469))
82
-
102
+ - provide fetch() and fetchJSON() methods to translate to openid-client requests ([3fe454f](https://github.com/battis/oauth2-cli/commit/3fe454f28497d704041ea4e599a4ad5b2b08b469))
83
103
 
84
104
  ### Bug Fixes
85
105
 
86
- * remove deprecated TokenManager ([2dde67e](https://github.com/battis/oauth2-cli/commit/2dde67edd70b151bd1bab6de3845839a06957e65))
106
+ - remove deprecated TokenManager ([2dde67e](https://github.com/battis/oauth2-cli/commit/2dde67edd70b151bd1bab6de3845839a06957e65))
87
107
 
88
108
  ## [0.3.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.2.3...oauth2-cli/0.3.0) (2025-12-24)
89
109
 
90
-
91
110
  ### ⚠ BREAKING CHANGES
92
111
 
93
- * resolve 1Password secret references successfully
112
+ - resolve 1Password secret references successfully
94
113
 
95
114
  ### Bug Fixes
96
115
 
97
- * resolve 1Password secret references successfully ([c4446e1](https://github.com/battis/oauth2-cli/commit/c4446e197a66271dac3ea8d58ff44725cc6be1db))
116
+ - resolve 1Password secret references successfully ([c4446e1](https://github.com/battis/oauth2-cli/commit/c4446e197a66271dac3ea8d58ff44725cc6be1db))
98
117
 
99
118
  ## [0.2.3](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.2.2...oauth2-cli/0.2.3) (2025-12-23)
100
119
 
101
-
102
120
  ### Bug Fixes
103
121
 
104
- * add wildcard param name ([97b2e58](https://github.com/battis/oauth2-cli/commit/97b2e58835941797fce564c736d8c4bd6e3ce97f))
122
+ - add wildcard param name ([97b2e58](https://github.com/battis/oauth2-cli/commit/97b2e58835941797fce564c736d8c4bd6e3ce97f))
105
123
 
106
124
  ## [0.2.2](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.2.1...oauth2-cli/0.2.2) (2025-12-23)
107
125
 
108
126
  ## [0.2.1](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.2.0...oauth2-cli/0.2.1) (2025-09-11)
109
127
 
110
-
111
128
  ### Bug Fixes
112
129
 
113
- * update dependencies to address transient openid-client config error ([f0ca9a8](https://github.com/battis/oauth2-cli/commit/f0ca9a8d2bb4551b80a49e48aa43df5ba66a5a9b))
130
+ - update dependencies to address transient openid-client config error ([f0ca9a8](https://github.com/battis/oauth2-cli/commit/f0ca9a8d2bb4551b80a49e48aa43df5ba66a5a9b))
114
131
 
115
132
  ## [0.2.0](https://github.com/battis/oauth2-cli/compare/oauth2-cli/0.1.6...oauth2-cli/0.2.0) (2025-03-09)
116
133
 
package/README.md CHANGED
@@ -39,7 +39,7 @@ Broadly speaking, having provided the configuration, the client is immediately r
39
39
 
40
40
  A `Client` requires some minimal information in order to interact with an OAuth 2.0 authorized API. The OAuth 2.0 base set is a `client_id`, `client_secret`, `authorization_endpoint`, `token_endpoint`, and a `redirect_uri`. For an OpenID-authenticated API, you could provide a `client_id`, `client_secret`, `issuer`, and `redirect_uri` and the Client will query the issuer for further details regarding required connection parameters (it is built on to of [openid-client](https://www.npmjs.com/package/openid-client)).
41
41
 
42
- In both cases, the token can be persisted by passing an implementation of [`TokenStorage`](https://github.com/battis/oauth2-cli/blob/main/packages/oauth2-cli/src/Token/TokenStorage.ts), such as [`FileStorage`](https://github.com/battis/oauth2-cli/blob/main/packages/oauth2-cli/src/Token/FileStorage.ts) which expects a path to a location to store a JSON file of access token data. _There are more secure ways to store your tokens, such as [@oauth2-cli/qui-cli](https://www.npmjs.com/package/@oauth2-cli/qui-cli)'s [`EnvironmentStorage`](https://github.com/battis/oauth2-cli/blob/main/packages/qui-cli/src/EnvironmentStorage.ts) which can be linked to a [1Password vault](https://github.com/battis/qui-cli/tree/main/packages/env#1password-integration)._
42
+ In both cases, the token can be persisted by passing an implementation of [`Token.Storage`](https://github.com/battis/oauth2-cli/blob/main/packages/oauth2-cli/src/Token/TokenStorage.ts), such as [`FileStorage`](https://github.com/battis/oauth2-cli/blob/main/packages/oauth2-cli/src/Token/FileStorage.ts) which expects a path to a location to store a JSON file of access token data. _There are more secure ways to store your tokens, such as [@oauth2-cli/qui-cli](https://www.npmjs.com/package/@oauth2-cli/qui-cli)'s [`EnvironmentStorage`](https://github.com/battis/oauth2-cli/blob/main/packages/qui-cli/src/EnvironmentStorage.ts) which can be linked to a [1Password vault](https://github.com/battis/qui-cli/tree/main/packages/env#1password-integration)._
43
43
 
44
44
  #### `redirect_uri` to Localhost
45
45
 
package/dist/Client.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  import { PathString } from '@battis/descriptive-types';
2
+ import { JSONValue } from '@battis/typescript-tricks';
2
3
  import { Request } from 'express';
3
4
  import { EventEmitter } from 'node:events';
4
5
  import * as OpenIDClient from 'openid-client';
5
6
  import * as requestish from 'requestish';
6
- import * as Credentials from './Credentials.js';
7
- import * as Req from './Request/index.js';
7
+ import { Credentials } from './Credentials.js';
8
+ import { Injection } from './Injection.js';
8
9
  import { Session, SessionOptions } from './Session.js';
9
10
  import * as Token from './Token/index.js';
10
11
  /**
@@ -12,22 +13,24 @@ import * as Token from './Token/index.js';
12
13
  * `redirect_uri` values
13
14
  */
14
15
  export declare const DEFAULT_REDIRECT_URI = "http://localhost:3000/oauth2-cli/redirect";
15
- export type ClientOptions = {
16
+ export type ClientOptions<C extends Credentials = Credentials> = {
16
17
  /** Credentials for server access */
17
- credentials: Credentials.Combined;
18
+ credentials: C;
18
19
  /** Optional request components to inject */
19
20
  inject?: {
20
21
  search?: requestish.URLSearchParams.ish;
21
22
  headers?: requestish.Headers.ish;
22
23
  body?: requestish.Body.ish;
23
24
  };
25
+ /** Base URL for all non-absolute requests */
26
+ base_url?: requestish.URL.ish;
24
27
  /**
25
28
  * Optional absolute path to EJS view templates directory, see
26
29
  * [WebServer.setViews()](./Webserver.ts)
27
30
  */
28
31
  views?: PathString;
29
32
  /** Optional {@link TokenStorage} implementation to manage tokens */
30
- storage?: Token.TokenStorage;
33
+ storage?: Token.Storage;
31
34
  };
32
35
  type RefreshOptions = {
33
36
  /**
@@ -38,7 +41,7 @@ type RefreshOptions = {
38
41
  */
39
42
  refresh_token?: string;
40
43
  /** Additional request injection for refresh grant flow */
41
- inject?: Req.Injection;
44
+ inject?: Injection;
42
45
  };
43
46
  type GetTokenOptions = {
44
47
  /**
@@ -52,7 +55,7 @@ type GetTokenOptions = {
52
55
  * Additional request injection for authorization code grant and/or refresh
53
56
  * grant flows
54
57
  */
55
- inject?: Req.Injection;
58
+ inject?: Injection;
56
59
  };
57
60
  /**
58
61
  * Wrap {@link https://www.npmjs.com/package/openid-client openid-client} in a
@@ -61,16 +64,17 @@ type GetTokenOptions = {
61
64
  *
62
65
  * Emits {@link Client.TokenEvent} whenever a new access token is received
63
66
  */
64
- export declare class Client extends EventEmitter {
67
+ export declare class Client<C extends Credentials = Credentials> extends EventEmitter {
65
68
  static readonly TokenEvent = "token";
66
- protected credentials: Credentials.Combined;
69
+ protected credentials: C;
70
+ protected base_url?: requestish.URL.ish;
67
71
  protected config?: OpenIDClient.Configuration;
72
+ protected inject?: Injection;
68
73
  protected views?: PathString;
69
- protected inject?: Req.Injection;
70
74
  private token?;
71
75
  private tokenLock;
72
76
  private storage?;
73
- constructor({ credentials, views, inject, storage }: ClientOptions);
77
+ constructor({ credentials, base_url, views, inject, storage }: ClientOptions<C>);
74
78
  get redirect_uri(): requestish.URL.ish;
75
79
  /**
76
80
  * @throws IndeterminateConfiguration if provided credentials combined with
@@ -104,10 +108,10 @@ export declare class Client extends EventEmitter {
104
108
  private toJSON;
105
109
  /**
106
110
  * Returns the result of {@link request} as a parsed JSON object, optionally
107
- * typed as `T`
111
+ * typed as `J`
108
112
  */
109
- requestJSON<T extends OpenIDClient.JsonValue = OpenIDClient.JsonValue>(url: requestish.URL.ish, method?: string, body?: OpenIDClient.FetchBody, headers?: requestish.Headers.ish, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<T>;
113
+ requestJSON<J extends JSONValue = JSONValue>(url: requestish.URL.ish, method?: string, body?: OpenIDClient.FetchBody, headers?: requestish.Headers.ish, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<J>;
110
114
  fetch(input: requestish.URL.ish, init?: RequestInit, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<Response>;
111
- fetchJSON<T extends OpenIDClient.JsonValue = OpenIDClient.JsonValue>(input: requestish.URL.ish, init?: RequestInit, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<T>;
115
+ fetchJSON<J extends JSONValue = JSONValue>(input: requestish.URL.ish, init?: RequestInit, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<J>;
112
116
  }
113
117
  export {};
package/dist/Client.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { Mutex } from 'async-mutex';
2
2
  import { EventEmitter } from 'node:events';
3
+ import path from 'node:path';
3
4
  import * as OpenIDClient from 'openid-client';
4
5
  import * as requestish from 'requestish';
5
- import * as Errors from './Errors/index.js';
6
- import * as Req from './Request/index.js';
6
+ import * as Scope from './Scope.js';
7
7
  import { Session } from './Session.js';
8
8
  /**
9
9
  * A generic `redirect_uri` to use if the server does not require pre-registered
@@ -20,15 +20,17 @@ export const DEFAULT_REDIRECT_URI = 'http://localhost:3000/oauth2-cli/redirect';
20
20
  export class Client extends EventEmitter {
21
21
  static TokenEvent = 'token';
22
22
  credentials;
23
+ base_url;
23
24
  config;
24
- views;
25
25
  inject;
26
+ views;
26
27
  token;
27
28
  tokenLock = new Mutex();
28
29
  storage;
29
- constructor({ credentials, views, inject, storage }) {
30
+ constructor({ credentials, base_url, views, inject, storage }) {
30
31
  super();
31
32
  this.credentials = credentials;
33
+ this.base_url = base_url;
32
34
  this.views = views;
33
35
  this.inject = inject;
34
36
  this.storage = storage;
@@ -41,12 +43,13 @@ export class Client extends EventEmitter {
41
43
  * OpenID discovery fail to generate a complete configuration
42
44
  */
43
45
  async getConfiguration() {
46
+ let error = undefined;
44
47
  if (!this.config && this.credentials.issuer) {
45
48
  try {
46
49
  this.config = await OpenIDClient.discovery(requestish.URL.from(this.credentials.issuer), this.credentials.client_id, { client_secret: this.credentials.client_secret });
47
50
  }
48
- catch (_) {
49
- // ignore error
51
+ catch (e) {
52
+ error = e;
50
53
  }
51
54
  }
52
55
  if (!this.config && this.credentials?.authorization_endpoint) {
@@ -58,7 +61,12 @@ export class Client extends EventEmitter {
58
61
  }, this.credentials.client_id, { client_secret: this.credentials.client_secret });
59
62
  }
60
63
  if (!this.config) {
61
- throw new Errors.IndeterminateConfiguration();
64
+ throw new Error('The client configuration could not be constructed from provided credentials.', {
65
+ cause: {
66
+ credentials: this.credentials,
67
+ 'OpenID configuration result': error
68
+ }
69
+ });
62
70
  }
63
71
  return this.config;
64
72
  }
@@ -69,7 +77,7 @@ export class Client extends EventEmitter {
69
77
  params.set('code_challenge_method', 'S256');
70
78
  params.set('state', session.state);
71
79
  if (this.credentials.scope) {
72
- params.set('scope', Req.Scope.toString(this.credentials.scope));
80
+ params.set('scope', Scope.toString(this.credentials.scope));
73
81
  }
74
82
  return params;
75
83
  }
@@ -139,7 +147,9 @@ export class Client extends EventEmitter {
139
147
  async save(token) {
140
148
  this.token = token;
141
149
  if (!token.access_token) {
142
- throw new Errors.MissingAccessToken();
150
+ throw new Error('No access_token in response.', {
151
+ cause: token
152
+ });
143
153
  }
144
154
  if (this.storage && this.token.refresh_token) {
145
155
  await this.storage.save(this.token.refresh_token);
@@ -160,11 +170,19 @@ export class Client extends EventEmitter {
160
170
  url = requestish.URL.from(url);
161
171
  }
162
172
  catch (error) {
163
- if (this.credentials.issuer) {
164
- url = new URL(url, this.credentials.issuer);
173
+ if (this.base_url || this.credentials.issuer) {
174
+ url = path.join(
175
+ // @ts-expect-error 2345 TS, I _just_ tested this!
176
+ requestish.URL.toString(this.base_url || this.credentials.issuer), requestish.URL.toString(url).replace(/^\/?/, ''));
165
177
  }
166
178
  else {
167
- throw error;
179
+ throw new Error(`Invalid request URL "${url}"`, {
180
+ cause: {
181
+ base_url: this.base_url,
182
+ issuer: this.credentials.issuer,
183
+ error
184
+ }
185
+ });
168
186
  }
169
187
  }
170
188
  const request = async () => await OpenIDClient.fetchProtectedResource(await this.getConfiguration(), (await this.getToken()).access_token, requestish.URL.from(requestish.URLSearchParams.appendTo(url, this.inject?.search || {})), method, body, requestish.Headers.merge(this.inject?.headers, headers), dPoPOptions);
@@ -189,12 +207,14 @@ export class Client extends EventEmitter {
189
207
  return (await response.json());
190
208
  }
191
209
  else {
192
- throw new Errors.BadResponse(response);
210
+ throw new Error('The response could not be parsed as JSON.', {
211
+ cause: response
212
+ });
193
213
  }
194
214
  }
195
215
  /**
196
216
  * Returns the result of {@link request} as a parsed JSON object, optionally
197
- * typed as `T`
217
+ * typed as `J`
198
218
  */
199
219
  async requestJSON(url, method = 'GET', body, headers = {}, dPoPOptions) {
200
220
  return await this.toJSON(await this.request(url, method, body, headers, dPoPOptions));
@@ -1,24 +1,10 @@
1
1
  import * as requestish from 'requestish';
2
- import * as Req from './Request/index.js';
3
- export type OAuth2 = {
2
+ import * as Scope from './Scope.js';
3
+ export type Credentials = {
4
4
  client_id: string;
5
5
  client_secret: string;
6
6
  redirect_uri: requestish.URL.ish;
7
- authorization_endpoint: requestish.URL.ish;
8
- token_endpoint: requestish.URL.ish;
9
- scope?: Req.Scope.ish;
10
- };
11
- export type OpenID = {
12
- issuer: requestish.URL.ish;
13
- client_id: string;
14
- client_secret: string;
15
- redirect_uri: requestish.URL.ish;
16
- };
17
- export type Combined = {
18
- client_id: string;
19
- client_secret: string;
20
- redirect_uri: requestish.URL.ish;
21
- scope?: Req.Scope.ish;
7
+ scope?: Scope.ish;
22
8
  } & ({
23
9
  issuer?: requestish.URL.ish;
24
10
  authorization_endpoint: requestish.URL.ish;
package/dist/Session.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { PathString } from '@battis/descriptive-types';
2
2
  import { Request } from 'express';
3
3
  import { Client } from './Client.js';
4
- import * as Req from './Request/index.js';
4
+ import { Injection } from './Injection.js';
5
5
  import * as Token from './Token/index.js';
6
6
  import * as WebServer from './WebServer.js';
7
7
  export type SessionOptions = {
@@ -9,7 +9,7 @@ export type SessionOptions = {
9
9
  /** See {@link WebServer.setViews Webserver.setViews()} */
10
10
  views?: PathString;
11
11
  /** Additional request injection for authorization code grant flow */
12
- inject?: Req.Injection;
12
+ inject?: Injection;
13
13
  };
14
14
  export type Resolver = (response?: Token.Response, error?: Error) => void | Promise<void>;
15
15
  export declare class Session {
@@ -20,7 +20,7 @@ export declare class Session {
20
20
  /** OAuth 2.0 state (if PKCE is not supported) */
21
21
  readonly state: string;
22
22
  /** Additional request injection for Authorization Code Grant request */
23
- readonly inject?: Req.Injection;
23
+ readonly inject?: Injection;
24
24
  private _resolve?;
25
25
  private spinner?;
26
26
  /**
package/dist/Session.js CHANGED
@@ -3,7 +3,6 @@ import * as gcrtl from 'gcrtl';
3
3
  import open from 'open';
4
4
  import * as OpenIDClient from 'openid-client';
5
5
  import ora from 'ora';
6
- import * as Errors from './Errors/index.js';
7
6
  import * as WebServer from './WebServer.js';
8
7
  export class Session {
9
8
  client;
@@ -49,7 +48,7 @@ export class Session {
49
48
  resolve(response);
50
49
  }
51
50
  else {
52
- reject(new Errors.MissingAccessToken());
51
+ reject(new Error('Authorization Code Grant response undefined.'));
53
52
  }
54
53
  };
55
54
  const url = gcrtl
@@ -1,5 +1,5 @@
1
- import { TokenStorage } from './TokenStorage.js';
2
- export declare class FileStorage implements TokenStorage {
1
+ import { Storage } from './Storage.js';
2
+ export declare class FileStorage implements Storage {
3
3
  private fileLock;
4
4
  private readonly filePath;
5
5
  constructor(filePath: string);
@@ -1,4 +1,4 @@
1
- export interface TokenStorage {
1
+ export interface Storage {
2
2
  load(): Promise<string | undefined>;
3
3
  save(refresh_token: string): Promise<void>;
4
4
  }
@@ -1,3 +1,3 @@
1
1
  export * from './FileStorage.js';
2
2
  export * from './Response.js';
3
- export * from './TokenStorage.js';
3
+ export * from './Storage.js';
@@ -1,3 +1,3 @@
1
1
  export * from './FileStorage.js';
2
2
  export * from './Response.js';
3
- export * from './TokenStorage.js';
3
+ export * from './Storage.js';
package/dist/WebServer.js CHANGED
@@ -3,7 +3,6 @@ import * as gcrtl from 'gcrtl';
3
3
  import fs from 'node:fs';
4
4
  import path from 'node:path';
5
5
  import * as requestish from 'requestish';
6
- import * as Errors from './Errors/index.js';
7
6
  let ejs = undefined;
8
7
  try {
9
8
  ejs = (await import('ejs')).default;
@@ -31,7 +30,7 @@ export class WebServer {
31
30
  const url = requestish.URL.from(this.session.redirect_uri);
32
31
  this.port = url.port;
33
32
  if (WebServer.activePorts.includes(this.port)) {
34
- throw new Errors.PortCollision(url.port);
33
+ throw new Error(`Another process is already running at http://localhost:${url.port}.`, { cause: { activePorts: WebServer.activePorts } });
35
34
  }
36
35
  WebServer.activePorts.push(this.port);
37
36
  const app = express();
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './Client.js';
2
- export * as Credentials from './Credentials.js';
3
- export * as Errors from './Errors/index.js';
4
- export * as Request from './Request/index.js';
2
+ export * from './Credentials.js';
3
+ export * from './Injection.js';
4
+ export * as Scope from './Scope.js';
5
5
  export * as Token from './Token/index.js';
6
6
  export * from './WebServer.js';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export * from './Client.js';
2
- export * as Credentials from './Credentials.js';
3
- export * as Errors from './Errors/index.js';
4
- export * as Request from './Request/index.js';
2
+ export * from './Credentials.js';
3
+ export * from './Injection.js';
4
+ export * as Scope from './Scope.js';
5
5
  export * as Token from './Token/index.js';
6
6
  export * from './WebServer.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oauth2-cli",
3
- "version": "0.7.3",
3
+ "version": "0.8.1",
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": {
@@ -1,3 +0,0 @@
1
- export declare class BadResponse extends Error {
2
- constructor(response: Response);
3
- }
@@ -1,7 +0,0 @@
1
- export class BadResponse extends Error {
2
- constructor(response) {
3
- super(`Response error ${response.status}: ${response.statusText}`, {
4
- cause: response
5
- });
6
- }
7
- }
@@ -1,3 +0,0 @@
1
- export declare class IndeterminateConfiguration extends Error {
2
- constructor();
3
- }
@@ -1,5 +0,0 @@
1
- export class IndeterminateConfiguration extends Error {
2
- constructor() {
3
- super('A configuration could not be determined from the provided credentials.');
4
- }
5
- }
@@ -1,3 +0,0 @@
1
- export declare class MissingAccessToken extends Error {
2
- constructor();
3
- }
@@ -1,5 +0,0 @@
1
- export class MissingAccessToken extends Error {
2
- constructor() {
3
- super('No access token available.');
4
- }
5
- }
@@ -1,3 +0,0 @@
1
- export declare class PortCollision extends Error {
2
- constructor(port: string);
3
- }
@@ -1,5 +0,0 @@
1
- export class PortCollision extends Error {
2
- constructor(port) {
3
- super(`Cannot start authorization: another process is already running at http://localhost:${port}.`);
4
- }
5
- }
@@ -1,4 +0,0 @@
1
- export * from './BadResponse.js';
2
- export * from './IndeterminateConfiguration.js';
3
- export * from './MissingAccessToken.js';
4
- export * from './PortCollision.js';
@@ -1,4 +0,0 @@
1
- export * from './BadResponse.js';
2
- export * from './IndeterminateConfiguration.js';
3
- export * from './MissingAccessToken.js';
4
- export * from './PortCollision.js';
@@ -1,2 +0,0 @@
1
- export * from './Injection.js';
2
- export * as Scope from './Scope.js';
@@ -1,2 +0,0 @@
1
- export * from './Injection.js';
2
- export * as Scope from './Scope.js';
File without changes
File without changes
File without changes
File without changes
File without changes