@oauth2-cli/qui-cli 0.7.16 → 1.0.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.
@@ -3,12 +3,13 @@ import { Env } from '@qui-cli/env';
3
3
  import { Log } from '@qui-cli/log';
4
4
  import * as Plugin from '@qui-cli/plugin';
5
5
  import * as OAuth2CLI from 'oauth2-cli';
6
- import * as requestish from 'requestish';
6
+ import { URL } from 'requestish';
7
7
  export class OAuth2Plugin {
8
8
  name;
9
9
  static names = [];
10
10
  static registeredPorts = {};
11
11
  overrideName;
12
+ reason;
12
13
  /**
13
14
  * @param name Human-readable name for client in messages. Must also be a
14
15
  * unique qui-cli plugin name.
@@ -19,15 +20,19 @@ export class OAuth2Plugin {
19
20
  throw new Error(`A @qui-cli/plugin named ${Colors.value(name)} has already been instantiated.`);
20
21
  }
21
22
  }
23
+ /** Configured client credentials */
22
24
  credentials;
25
+ /** Configured client base_url */
23
26
  base_url;
24
- man = {
25
- heading: 'OAuth 2.0 / Open ID Connect client options'
26
- };
27
+ /** Configured usage information */
28
+ man = undefined;
29
+ /** Configured reference URLs for credentials */
27
30
  url = undefined;
31
+ /** Configured hint values for credentials */
28
32
  hint = {
29
33
  redirect_uri: Colors.quotedValue(`"http://localhost:3000/redirect"`)
30
34
  };
35
+ /** Configured environment variable names for credentials */
31
36
  env = {
32
37
  issuer: 'ISSUER',
33
38
  client_id: 'CLIENT_ID',
@@ -38,13 +43,74 @@ export class OAuth2Plugin {
38
43
  base_url: 'BASE_URL',
39
44
  scope: 'SCOPE'
40
45
  };
41
- suppress = {
42
- scope: true
43
- };
46
+ /** Configured credentials to suppress in usage and init */
47
+ suppress = undefined;
48
+ /** Configured request components for client to inject */
44
49
  inject = undefined;
45
- views = undefined;
50
+ /** Configured {@link OAuth2CLI.Localhost.Options} to pass to client */
51
+ localhost;
52
+ /** Configured client refresh token storage strategy */
46
53
  storage = undefined;
47
54
  _client = undefined;
55
+ /**
56
+ * Configured oauth2-cli client
57
+ *
58
+ * Do _not_ access until intitialization is complete -- the client will be
59
+ * configured upon first access based on available configuration known at that
60
+ * time
61
+ */
62
+ get client() {
63
+ if (!this._client) {
64
+ if (!this.credentials?.client_id) {
65
+ throw new Error(`A ${Colors.varName(this.env.client_id)} ${Colors.keyword('must')} ` +
66
+ `be configured for ${this.overrideName || this.name}.`);
67
+ }
68
+ if (!this.credentials?.client_secret) {
69
+ throw new Error(`A ${Colors.varName(this.env.client_secret)} ${Colors.keyword('must')} ` +
70
+ `be configured for ${this.overrideName || this.name}.`);
71
+ }
72
+ if (!this.credentials?.redirect_uri) {
73
+ throw new Error(`A ${Colors.varName(this.env.redirect_uri)} ${Colors.keyword('must')} ` +
74
+ `be configured for ${this.overrideName || this.name}.`);
75
+ }
76
+ if (!this.credentials?.issuer) {
77
+ if (!this.credentials?.authorization_endpoint) {
78
+ throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
79
+ `${Colors.varName(this.env.authorization_endpoint)} ` +
80
+ `${Colors.keyword('must')} be configured for ` +
81
+ `${this.overrideName || this.name}.`);
82
+ }
83
+ if (!this.credentials?.token_endpoint) {
84
+ throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
85
+ `${Colors.varName(this.env.token_endpoint)} ` +
86
+ `${Colors.keyword('must')} be configured for ` +
87
+ `${this.overrideName || this.name}.`);
88
+ }
89
+ }
90
+ this._client = this.instantiateClient({
91
+ name: this.overrideName || this.name,
92
+ reason: this.reason,
93
+ credentials: this.credentials,
94
+ base_url: this.base_url,
95
+ inject: this.inject,
96
+ localhost: this.localhost,
97
+ storage: this.storage
98
+ });
99
+ }
100
+ return this._client;
101
+ }
102
+ /**
103
+ * Configure plugin for use
104
+ *
105
+ * May be called repeatedly, overlaying different options as they become
106
+ * available
107
+ *
108
+ * Invoked automatically by
109
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} during
110
+ * initialization
111
+ *
112
+ * @see {@link Configuration}
113
+ */
48
114
  configure(proposal = {}) {
49
115
  function hydrate(p, c) {
50
116
  if (p) {
@@ -60,6 +126,7 @@ export class OAuth2Plugin {
60
126
  return c;
61
127
  }
62
128
  this.overrideName = Plugin.hydrate(proposal.name, this.overrideName);
129
+ this.reason = Plugin.hydrate(proposal.reason, this.reason);
63
130
  this.credentials = hydrate(proposal.credentials, this.credentials);
64
131
  this.base_url = Plugin.hydrate(proposal.base_url, this.base_url);
65
132
  this.storage = Plugin.hydrate(proposal.storage, this.storage);
@@ -69,8 +136,9 @@ export class OAuth2Plugin {
69
136
  this.hint = hydrate(proposal.hint, this.hint);
70
137
  this.env = hydrate(proposal.env, this.env);
71
138
  this.suppress = hydrate(proposal.suppress, this.suppress);
139
+ this.localhost = hydrate(proposal.localhost, this.localhost);
72
140
  if (this.credentials?.redirect_uri) {
73
- const url = requestish.URL.from(this.credentials.redirect_uri);
141
+ const url = URL.from(this.credentials.redirect_uri);
74
142
  if (url.hostname !== 'localhost' &&
75
143
  !/^\/https?\/localhost(:\d+)?\//.test(url.pathname)) {
76
144
  Log.warning(`The ${Colors.varName(this.env.redirect_uri)} value ${Colors.url(this.credentials.redirect_uri)} for ${this.overrideName || this.name} may not work: it ` +
@@ -93,6 +161,15 @@ export class OAuth2Plugin {
93
161
  }
94
162
  }
95
163
  }
164
+ /**
165
+ * Provide usage options to
166
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} for display to user
167
+ * on command line
168
+ *
169
+ * Invoked automatically by
170
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} during
171
+ * initialization
172
+ */
96
173
  options() {
97
174
  const descriptions = {
98
175
  issuer: `The OpenID ${Colors.keyword('issuer')} URL is set from the ` +
@@ -126,7 +203,10 @@ export class OAuth2Plugin {
126
203
  };
127
204
  return {
128
205
  man: [
129
- { level: 1, text: this.man.heading },
206
+ {
207
+ level: 1,
208
+ text: this.man?.heading || `${this.overrideName || this.name} options`
209
+ },
130
210
  ...Object.keys(descriptions)
131
211
  .filter((key) => !this.suppress || !this.suppress[key])
132
212
  .map((key) => ({
@@ -136,10 +216,17 @@ export class OAuth2Plugin {
136
216
  ? ` See ${Colors.url(this.url[key])} for more information.`
137
217
  : '')
138
218
  })),
139
- ...(this.man.text || []).map((t) => ({ text: t }))
219
+ ...(this.man?.text || []).map((t) => ({ text: t }))
140
220
  ]
141
221
  };
142
222
  }
223
+ /**
224
+ * Intialize plugin configuration from command line options and environment
225
+ *
226
+ * Invoked automatically by
227
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} during
228
+ * initialization
229
+ */
143
230
  async init(_) {
144
231
  const credentials = {};
145
232
  const base_url = this.base_url ||
@@ -157,57 +244,43 @@ export class OAuth2Plugin {
157
244
  }
158
245
  this.configure({ credentials, base_url });
159
246
  }
247
+ /**
248
+ * Instantiate the `oauth2-cli` client
249
+ *
250
+ * Available hook for custom configurations in plugin development
251
+ */
160
252
  instantiateClient(options) {
161
253
  return new OAuth2CLI.Client(options);
162
254
  }
163
- get client() {
164
- if (!this._client) {
165
- if (!this.credentials?.client_id) {
166
- throw new Error(`A ${Colors.varName(this.env.client_id)} ${Colors.keyword('must')} ` +
167
- `be configured for ${this.overrideName || this.name}.`);
168
- }
169
- if (!this.credentials?.client_secret) {
170
- throw new Error(`A ${Colors.varName(this.env.client_secret)} ${Colors.keyword('must')} ` +
171
- `be configured for ${this.overrideName || this.name}.`);
172
- }
173
- if (!this.credentials?.redirect_uri) {
174
- throw new Error(`A ${Colors.varName(this.env.redirect_uri)} ${Colors.keyword('must')} ` +
175
- `be configured for ${this.overrideName || this.name}.`);
176
- }
177
- if (!this.credentials?.issuer) {
178
- if (!this.credentials?.authorization_endpoint) {
179
- throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
180
- `${Colors.varName(this.env.authorization_endpoint)} ` +
181
- `${Colors.keyword('must')} be configured for ` +
182
- `${this.overrideName || this.name}.`);
183
- }
184
- if (!this.credentials?.token_endpoint) {
185
- throw new Error(`Either an ${Colors.varName(this.env.issuer)} or ` +
186
- `${Colors.varName(this.env.token_endpoint)} ` +
187
- `${Colors.keyword('must')} be configured for ` +
188
- `${this.overrideName || this.name}.`);
189
- }
190
- }
191
- this._client = this.instantiateClient({
192
- name: this.overrideName || this.name,
193
- credentials: this.credentials,
194
- base_url: this.base_url,
195
- inject: this.inject,
196
- views: this.views,
197
- storage: this.storage
198
- });
199
- }
200
- return this._client;
201
- }
255
+ /**
256
+ * Convenience method
257
+ *
258
+ * @see {@link OAuth2CLI.Client.request}
259
+ */
202
260
  request(...args) {
203
261
  return this.client.request(...args);
204
262
  }
263
+ /**
264
+ * Convenience method
265
+ *
266
+ * @see {@link OAuth2CLI.Client.requestJSON}
267
+ */
205
268
  requestJSON(...args) {
206
269
  return this.client.requestJSON(...args);
207
270
  }
271
+ /**
272
+ * Convenience method
273
+ *
274
+ * @see {@link OAuth2CLI.Client.fetch}
275
+ */
208
276
  fetch(...args) {
209
277
  return this.client.fetch(...args);
210
278
  }
279
+ /**
280
+ * Convenience method
281
+ *
282
+ * @see {@link OAuth2CLI.Client.fetchJSON}
283
+ */
211
284
  fetchJSON(...args) {
212
285
  return this.client.fetchJSON(...args);
213
286
  }
@@ -1,6 +1,20 @@
1
1
  import { Token } from 'oauth2-cli';
2
+ /**
3
+ * Persist a refresh token in the local environment
4
+ *
5
+ * Care should be taken when using this persistence strategy to:
6
+ *
7
+ * 1. Ideally encrypt or otherwise secure the environment value (see
8
+ * {@link https://github.com/battis/oauth2-cli/tree/main/examples/qui-cli/04%201password-integration#readme 1password-integration}
9
+ * example for one approach)
10
+ * 2. Do not commit `.env` files to a public repo
11
+ */
2
12
  export declare class EnvironmentStorage implements Token.Storage {
3
13
  private tokenEnvVar;
14
+ /**
15
+ * @param tokenEnvVar Name of the environment variable containing the refresh
16
+ * token, defaults to `REFRESH_TOKEN`
17
+ */
4
18
  constructor(tokenEnvVar?: string);
5
19
  load(): Promise<string | undefined>;
6
20
  save(refresh_token: string): Promise<void>;
@@ -1,6 +1,20 @@
1
1
  import { Env } from '@qui-cli/env';
2
+ /**
3
+ * Persist a refresh token in the local environment
4
+ *
5
+ * Care should be taken when using this persistence strategy to:
6
+ *
7
+ * 1. Ideally encrypt or otherwise secure the environment value (see
8
+ * {@link https://github.com/battis/oauth2-cli/tree/main/examples/qui-cli/04%201password-integration#readme 1password-integration}
9
+ * example for one approach)
10
+ * 2. Do not commit `.env` files to a public repo
11
+ */
2
12
  export class EnvironmentStorage {
3
13
  tokenEnvVar;
14
+ /**
15
+ * @param tokenEnvVar Name of the environment variable containing the refresh
16
+ * token, defaults to `REFRESH_TOKEN`
17
+ */
4
18
  constructor(tokenEnvVar = 'REFRESH_TOKEN') {
5
19
  this.tokenEnvVar = tokenEnvVar;
6
20
  }
@@ -1,4 +1,4 @@
1
- export { ClientOptions, Credentials, Injection, Scope, WebServer } from 'oauth2-cli';
1
+ export { Credentials, Injection, Localhost, Options } from 'oauth2-cli';
2
2
  export * from './Client.js';
3
3
  export * from './OAuth2Plugin.js';
4
4
  export * as Token from './Token/index.js';
@@ -1,4 +1,4 @@
1
- export { Scope, WebServer } from 'oauth2-cli';
1
+ export { Localhost } from 'oauth2-cli';
2
2
  export * from './Client.js';
3
3
  export * from './OAuth2Plugin.js';
4
4
  export * as Token from './Token/index.js';
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
+ export * from './extendable.js';
1
2
  export * as OAuth2 from './OAuth2.js';
2
- export * from './Unregistered.js';
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
+ export * from './extendable.js';
1
2
  export * as OAuth2 from './OAuth2.js';
2
- export * from './Unregistered.js';
@@ -0,0 +1,24 @@
1
+ import { JSONValue } from '@battis/typescript-tricks';
2
+ import { Request } from 'express';
3
+ import * as OAuth2CLI from 'oauth2-cli';
4
+ import type * as OpenIDClient from 'openid-client';
5
+ import * as requestish from 'requestish';
6
+ /**
7
+ * Wrap {@link https://www.npmjs.com/package/openid-client openid-client} in a
8
+ * class instance specific to a particular OAuth/OpenID server credential-set,
9
+ * abstracting away most flows into {@link getToken}
10
+ *
11
+ * Emits {@link Client.TokenEvent} whenever a new access token is received
12
+ *
13
+ * Provides optional debug logging output using
14
+ * {@link https://www.npmjs.com/package/@qui-cli/env @qui-cli/env}
15
+ */
16
+ export declare class Client<C extends OAuth2CLI.Credentials = OAuth2CLI.Credentials> extends OAuth2CLI.Client<C> {
17
+ getConfiguration(): Promise<OpenIDClient.Configuration>;
18
+ authorize(): Promise<OAuth2CLI.Token.Response>;
19
+ handleAuthorizationCodeRedirect(request: Request, session: OAuth2CLI.Localhost.Server): Promise<OAuth2CLI.Token.Response>;
20
+ protected refreshTokenGrant(token: OAuth2CLI.Token.Response): Promise<OAuth2CLI.Token.Response | undefined>;
21
+ protected save(response: OAuth2CLI.Token.Response): Promise<OAuth2CLI.Token.Response>;
22
+ request(url: requestish.URL.ish, method?: string, body?: OpenIDClient.FetchBody, headers?: requestish.Headers.ish, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<Response>;
23
+ requestJSON<J extends JSONValue = JSONValue>(url: requestish.URL.ish, method?: string, body?: OpenIDClient.FetchBody, headers?: requestish.Headers.ish, dPoPOptions?: OpenIDClient.DPoPOptions): Promise<J>;
24
+ }
@@ -0,0 +1,71 @@
1
+ import { Log } from '@qui-cli/log';
2
+ import * as OAuth2CLI from 'oauth2-cli';
3
+ /**
4
+ * Wrap {@link https://www.npmjs.com/package/openid-client openid-client} in a
5
+ * class instance specific to a particular OAuth/OpenID server credential-set,
6
+ * abstracting away most flows into {@link getToken}
7
+ *
8
+ * Emits {@link Client.TokenEvent} whenever a new access token is received
9
+ *
10
+ * Provides optional debug logging output using
11
+ * {@link https://www.npmjs.com/package/@qui-cli/env @qui-cli/env}
12
+ */
13
+ export class Client extends OAuth2CLI.Client {
14
+ async getConfiguration() {
15
+ const creating = !this.config;
16
+ const config = await super.getConfiguration();
17
+ if (creating) {
18
+ Log.debug(`${this.name} OAuth 2.0 configuration created`, {
19
+ credentials: this.credentials,
20
+ config: {
21
+ serverMetadata: config.serverMetadata(),
22
+ clientMetadata: config.clientMetadata()
23
+ }
24
+ });
25
+ }
26
+ return config;
27
+ }
28
+ async authorize() {
29
+ Log.debug(`Authorizing ${this.name} new access token`);
30
+ const response = await super.authorize();
31
+ Log.debug(`Authorized ${this.name} new access token`, { response });
32
+ return response;
33
+ }
34
+ async handleAuthorizationCodeRedirect(request, session) {
35
+ Log.debug(`Handling ${this.name} authorization code redirect`, { request });
36
+ const response = await super.handleAuthorizationCodeRedirect(request, session);
37
+ Log.debug(`Received ${this.name} authorization code response`, {
38
+ response
39
+ });
40
+ return response;
41
+ }
42
+ async refreshTokenGrant(token) {
43
+ Log.debug(`Refreshing expired ${this.name} access token`, {
44
+ token
45
+ });
46
+ const refreshed = await super.refreshTokenGrant(token);
47
+ Log.debug(`Received refreshed ${this.name} access token`, {
48
+ token: refreshed
49
+ });
50
+ return refreshed;
51
+ }
52
+ async save(response) {
53
+ Log.debug(`Persisting ${this.name} refresh token, if present and storage configured`, {
54
+ response
55
+ });
56
+ return await super.save(response);
57
+ }
58
+ async request(url, method, body, headers, dPoPOptions) {
59
+ Log.debug(`Sending request to ${this.name}`, {
60
+ request: { method, url, headers, body, dPoPOptions }
61
+ });
62
+ const response = await super.request(url, method, body, headers, dPoPOptions);
63
+ Log.debug(`Received response from ${this.name}`, { response });
64
+ return response;
65
+ }
66
+ async requestJSON(url, method, body, headers, dPoPOptions) {
67
+ const json = await super.requestJSON(url, method, body, headers, dPoPOptions);
68
+ Log.debug(`Parsed JSON from ${this.name} response`, { json });
69
+ return json;
70
+ }
71
+ }
@@ -0,0 +1,154 @@
1
+ import { URLString } from '@battis/descriptive-types';
2
+ import { JSONValue } from '@battis/typescript-tricks';
3
+ import * as Plugin from '@qui-cli/plugin';
4
+ import * as OAuth2CLI from 'oauth2-cli';
5
+ import { URL } from 'requestish';
6
+ import { Client } from './Client.js';
7
+ /** Key for value to be read from the local environment */
8
+ type EnvironmentKey = 'issuer' | 'client_id' | 'client_secret' | 'redirect_uri' | 'authorization_endpoint' | 'token_endpoint' | 'scope' | 'base_url';
9
+ /** Names of environment variables */
10
+ type EnvironmentVars = Record<EnvironmentKey, string>;
11
+ /** Reference URLs for environment variables */
12
+ type SupportUrls = Record<EnvironmentKey, URLString>;
13
+ /** Hint values for environment variables */
14
+ type Hints = Record<EnvironmentKey, string>;
15
+ /** Environment variables to ignore and supporess in usage documentation */
16
+ type EnvVarSuppression = Record<EnvironmentKey, boolean>;
17
+ /** Custom usage information to present to user */
18
+ type Usage = {
19
+ heading: string;
20
+ text?: string[];
21
+ };
22
+ /** Plugin configuration */
23
+ export type Configuration<C extends OAuth2CLI.Credentials = OAuth2CLI.Credentials> = Plugin.Configuration & {
24
+ /** Human-readable name for client in messages (e.g. the name of the API) */
25
+ name?: string;
26
+ /**
27
+ * Human-readable for authorizing access in messages (e.g. the name of the
28
+ * app)
29
+ */
30
+ reason?: string;
31
+ /** OAuth 2.0/OpenID Connect credential set */
32
+ credentials?: Partial<C>;
33
+ /** Base URL for all non-absolute requests */
34
+ base_url?: URL.ish;
35
+ /** Request components to inject into server requests */
36
+ inject?: OAuth2CLI.Injection;
37
+ /** Refresh token storage service */
38
+ storage?: OAuth2CLI.Token.Storage;
39
+ /** CLI usage section header and text */
40
+ man?: Usage;
41
+ /** Reference URLs for particular credential values */
42
+ url?: Partial<SupportUrls>;
43
+ /** Hint values for particular credential values */
44
+ hint?: Partial<Hints>;
45
+ /** Actual environment variable names for each credential value */
46
+ env?: Partial<EnvironmentVars>;
47
+ /** Should a particular credential value _not_ be loaded from the environment? */
48
+ suppress?: Partial<EnvVarSuppression>;
49
+ localhost?: OAuth2CLI.Options['localhost'];
50
+ };
51
+ export declare class OAuth2Plugin<C extends OAuth2CLI.Credentials = OAuth2CLI.Credentials, L extends Client<C> = Client<C>> {
52
+ readonly name: string;
53
+ [key: string]: unknown;
54
+ private static names;
55
+ private static registeredPorts;
56
+ private overrideName?;
57
+ private reason?;
58
+ /**
59
+ * @param name Human-readable name for client in messages. Must also be a
60
+ * unique qui-cli plugin name.
61
+ */
62
+ constructor(name?: string);
63
+ /** Configured client credentials */
64
+ private credentials?;
65
+ /** Configured client base_url */
66
+ private base_url?;
67
+ /** Configured usage information */
68
+ private man?;
69
+ /** Configured reference URLs for credentials */
70
+ private url?;
71
+ /** Configured hint values for credentials */
72
+ private hint;
73
+ /** Configured environment variable names for credentials */
74
+ private env;
75
+ /** Configured credentials to suppress in usage and init */
76
+ private suppress?;
77
+ /** Configured request components for client to inject */
78
+ private inject?;
79
+ /** Configured {@link OAuth2CLI.Localhost.Options} to pass to client */
80
+ private localhost?;
81
+ /** Configured client refresh token storage strategy */
82
+ private storage?;
83
+ private _client?;
84
+ /**
85
+ * Configured oauth2-cli client
86
+ *
87
+ * Do _not_ access until intitialization is complete -- the client will be
88
+ * configured upon first access based on available configuration known at that
89
+ * time
90
+ */
91
+ get client(): L;
92
+ /**
93
+ * Configure plugin for use
94
+ *
95
+ * May be called repeatedly, overlaying different options as they become
96
+ * available
97
+ *
98
+ * Invoked automatically by
99
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} during
100
+ * initialization
101
+ *
102
+ * @see {@link Configuration}
103
+ */
104
+ configure(proposal?: Configuration<C>): void;
105
+ /**
106
+ * Provide usage options to
107
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} for display to user
108
+ * on command line
109
+ *
110
+ * Invoked automatically by
111
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} during
112
+ * initialization
113
+ */
114
+ options(): Plugin.Options;
115
+ /**
116
+ * Intialize plugin configuration from command line options and environment
117
+ *
118
+ * Invoked automatically by
119
+ * {@link https://github.com/battis/qui-cli#readme qui-cli} during
120
+ * initialization
121
+ */
122
+ init(_: Plugin.ExpectedArguments<typeof this.options>): Promise<void>;
123
+ /**
124
+ * Instantiate the `oauth2-cli` client
125
+ *
126
+ * Available hook for custom configurations in plugin development
127
+ */
128
+ protected instantiateClient(options: OAuth2CLI.Options<C>): L;
129
+ /**
130
+ * Convenience method
131
+ *
132
+ * @see {@link OAuth2CLI.Client.request}
133
+ */
134
+ request(...args: Parameters<OAuth2CLI.Client<C>['request']>): Promise<Response>;
135
+ /**
136
+ * Convenience method
137
+ *
138
+ * @see {@link OAuth2CLI.Client.requestJSON}
139
+ */
140
+ requestJSON<T extends JSONValue>(...args: Parameters<OAuth2CLI.Client<C>['requestJSON']>): Promise<T>;
141
+ /**
142
+ * Convenience method
143
+ *
144
+ * @see {@link OAuth2CLI.Client.fetch}
145
+ */
146
+ fetch(...args: Parameters<OAuth2CLI.Client<C>['fetch']>): Promise<Response>;
147
+ /**
148
+ * Convenience method
149
+ *
150
+ * @see {@link OAuth2CLI.Client.fetchJSON}
151
+ */
152
+ fetchJSON<T extends JSONValue>(...args: Parameters<OAuth2CLI.Client<C>['fetchJSON']>): Promise<T>;
153
+ }
154
+ export {};