@oauth2-cli/qui-cli-plugin 0.2.1 → 0.2.2

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,21 @@
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.2.2](https://github.com/battis/oauth2-cli/compare/qui-cli-plugin/0.2.1...qui-cli-plugin/0.2.2) (2025-12-23)
6
+
7
+
8
+ ### Features
9
+
10
+ * add optional typing to requestJSON() ([5f7cf39](https://github.com/battis/oauth2-cli/commit/5f7cf39d8dc0ca86cbe3df7e8493d3273e630573))
11
+ * configurable options and usage ([aadbc4b](https://github.com/battis/oauth2-cli/commit/aadbc4bffc9eda241763ecd9f134963517250e5f))
12
+ * default suppress token path storage ([9df7f4f](https://github.com/battis/oauth2-cli/commit/9df7f4f6312713e2086366350f0c546a975b2c31))
13
+ * provide EnvironmentStorage implementation ([55fc676](https://github.com/battis/oauth2-cli/commit/55fc676716fa1e4830a6a890b6d0bf5cecf0f57f))
14
+
15
+
16
+ ### Bug Fixes
17
+
18
+ * update to current [@qui-cli](https://github.com/qui-cli) versions ([d54c521](https://github.com/battis/oauth2-cli/commit/d54c5210e55586ed688afa42840ec2b9e1cffeb0))
19
+
5
20
  ## [0.2.1](https://github.com/battis/oauth2-cli/compare/qui-cli-plugin/0.2.0...qui-cli-plugin/0.2.1) (2025-09-11)
6
21
 
7
22
 
@@ -0,0 +1,7 @@
1
+ import { Token, TokenStorage } from 'oauth2-cli';
2
+ export declare class EnvironmentStorage implements TokenStorage {
3
+ private tokenEnvVar;
4
+ constructor(tokenEnvVar?: string);
5
+ load(): Promise<Token | undefined>;
6
+ save(tokens: Token): Promise<Token>;
7
+ }
@@ -0,0 +1,25 @@
1
+ import { Env } from '@qui-cli/env-1password';
2
+ import { Token } from 'oauth2-cli';
3
+ export class EnvironmentStorage {
4
+ tokenEnvVar;
5
+ constructor(tokenEnvVar = 'ACCESS_TOKEN') {
6
+ this.tokenEnvVar = tokenEnvVar;
7
+ }
8
+ async load() {
9
+ try {
10
+ const data = JSON.parse(await Env.get({ key: this.tokenEnvVar }));
11
+ if (!data.access_token) {
12
+ throw new Error('No access token');
13
+ }
14
+ return Token.fromResponse(data);
15
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
16
+ }
17
+ catch (_) {
18
+ return undefined;
19
+ }
20
+ }
21
+ async save(tokens) {
22
+ await Env.set({ key: this.tokenEnvVar, value: JSON.stringify(tokens) });
23
+ return tokens;
24
+ }
25
+ }
@@ -1,8 +1,29 @@
1
1
  import { PathString, URLString } from '@battis/descriptive-types';
2
- import '@battis/qui-cli.env';
3
- import * as Plugin from '@battis/qui-cli.plugin';
2
+ import '@qui-cli/env-1password';
3
+ import * as Plugin from '@qui-cli/plugin';
4
4
  import * as OAuth2 from 'oauth2-cli';
5
5
  import * as OpenIDClient from 'openid-client';
6
+ type EnvironmentVars = {
7
+ client_id: string;
8
+ client_secret: string;
9
+ redirect_uri: string;
10
+ authorization_endpoint: string;
11
+ token_endpoint: string;
12
+ token_path: string;
13
+ access_token: string;
14
+ };
15
+ type OptionSuppression = {
16
+ clientId?: boolean;
17
+ clientSecret?: boolean;
18
+ redirectUri?: boolean;
19
+ authorizationEndpoint?: boolean;
20
+ tokenEndpoint?: boolean;
21
+ tokenPath?: boolean;
22
+ };
23
+ type Usage = {
24
+ heading: string;
25
+ text?: string[];
26
+ };
6
27
  export type Configuration = Plugin.Configuration & {
7
28
  client_id?: string;
8
29
  client_secret?: string;
@@ -11,12 +32,15 @@ export type Configuration = Plugin.Configuration & {
11
32
  token_endpoint?: URLString;
12
33
  store?: OAuth2.TokenStorage;
13
34
  token_path?: PathString;
35
+ env: EnvironmentVars;
36
+ man: Usage;
37
+ suppress?: OptionSuppression;
14
38
  };
15
39
  export declare const name = "@oauth2-cli/qui-cli-plugin";
16
- export declare const src: string;
17
- export declare function configure(config?: Configuration): void;
40
+ export declare function configure(proposal?: Partial<Configuration>): void;
18
41
  export declare function options(): Plugin.Options;
19
- export declare function init(args: Plugin.ExpectedArguments<typeof options>): void;
42
+ export declare function init(args: Plugin.ExpectedArguments<typeof options>): Promise<void>;
20
43
  export declare function getToken(): Promise<OAuth2.Token | undefined>;
21
44
  export declare function request(url: URL | string, method?: string, body?: OpenIDClient.FetchBody, headers?: Record<string, string>, options?: OpenIDClient.DPoPOptions): Promise<Response>;
22
- export declare function requestJSON(url: URL | string, method?: string, body?: OpenIDClient.FetchBody, headers?: Record<string, string>, options?: OpenIDClient.DPoPOptions): Promise<unknown>;
45
+ export declare function requestJSON<T = unknown>(url: URL | string, method?: string, body?: OpenIDClient.FetchBody, headers?: Record<string, string>, options?: OpenIDClient.DPoPOptions): Promise<T>;
46
+ export {};
package/dist/OAuth2CLI.js CHANGED
@@ -1,58 +1,118 @@
1
- import { Colors } from '@battis/qui-cli.colors';
2
- import '@battis/qui-cli.env';
3
- import * as Plugin from '@battis/qui-cli.plugin';
4
- import { Root } from '@battis/qui-cli.root';
1
+ import { Colors } from '@qui-cli/colors';
2
+ import '@qui-cli/env-1password';
3
+ import { Env } from '@qui-cli/env-1password';
4
+ import { Root } from '@qui-cli/root';
5
5
  import path from 'node:path';
6
6
  import * as OAuth2 from 'oauth2-cli';
7
+ import { EnvironmentStorage } from './EnvironmentStorage.js';
7
8
  export const name = '@oauth2-cli/qui-cli-plugin';
8
- export const src = import.meta.dirname;
9
- let client_id = undefined;
10
- let client_secret = undefined;
11
- let redirect_uri = undefined;
12
- let authorization_endpoint = undefined;
13
- let token_endpoint = undefined;
14
- let store = undefined;
9
+ const config = {
10
+ redirect_uri: 'http://localhost:3000/redirect',
11
+ env: {
12
+ client_id: 'CLIENT_ID',
13
+ client_secret: 'CLIENT_SECRET',
14
+ redirect_uri: 'REDIRECT_URI',
15
+ authorization_endpoint: 'AUTHORIZATION_ENDPOINT',
16
+ token_endpoint: 'TOKEN_ENDPOINT',
17
+ token_path: 'TOKEN_PATH',
18
+ access_token: 'ACCESS_TOKEN'
19
+ },
20
+ man: {
21
+ heading: 'OAuth 2.0 client options'
22
+ },
23
+ suppress: {
24
+ tokenPath: true
25
+ }
26
+ };
15
27
  let client = undefined;
16
- export function configure(config = {}) {
17
- client_id = Plugin.hydrate(config.client_id, client_id);
18
- client_secret = Plugin.hydrate(config.client_secret, client_secret);
19
- redirect_uri = Plugin.hydrate(config.redirect_uri, redirect_uri);
20
- authorization_endpoint = Plugin.hydrate(config.authorization_endpoint, authorization_endpoint);
21
- token_endpoint = Plugin.hydrate(config.token_endpoint, token_endpoint);
22
- if (config.store) {
23
- store = config.store;
28
+ export function configure(proposal = {}) {
29
+ for (const key in proposal) {
30
+ if (proposal[key] !== undefined) {
31
+ config[key] = proposal[key];
32
+ }
24
33
  }
25
- else if (config.token_path) {
26
- store = new OAuth2.FileStorage(path.resolve(Root.path(), config.token_path));
34
+ if (!config.store) {
35
+ if (config.token_path) {
36
+ config.store = new OAuth2.FileStorage(path.resolve(Root.path(), config.token_path));
37
+ }
38
+ else {
39
+ config.store = new EnvironmentStorage(config.env.access_token);
40
+ }
27
41
  }
28
42
  }
29
43
  export function options() {
30
44
  return {
45
+ man: [
46
+ { level: 1, text: config.man.heading },
47
+ ...(config.man.text || []).map((t) => ({ text: t }))
48
+ ],
31
49
  opt: {
32
- clientId: {
33
- description: `OAuth 2.0 client ID (defaults to environment variable ${Colors.value('CLIENT_ID')})`
34
- },
35
- clientSecret: {
36
- description: `OAuth 2.0 client secret (defaults to environment variable ${Colors.value('CLIENT_SECRET')}`
37
- },
38
- redirectUri: {
39
- description: `OAuth 2.0 redirect URI (must be to host ${Colors.url('localhost')}, e.g. ${Colors.quotedValue(`"http://localhost:3000/oauth2/redirect"`)}, defaults to environment variables ${Colors.value('REDIRECT_URI')})`
40
- },
41
- authorizationEndpoint: {
42
- description: `OAuth 2.0 authorization endpoint (defaults to environment variable ${Colors.value('AUTHORIZATION_ENDPOINT')}`
43
- },
44
- tokenEndpoint: {
45
- description: `OAuth 2.0 token endpoint (will fall back to authorization endpoint if not provided, defaults to environment variable ${Colors.value('TOKEN_ENDPOINT')}`
46
- },
47
- tokenPath: {
48
- description: `Path to token storage JSON file (defaults to environent variable ${Colors.value('TOKEN_PATH')}`
49
- }
50
+ ...(config.suppress?.clientId
51
+ ? {}
52
+ : {
53
+ clientId: {
54
+ description: `OAuth 2.0 client ID (defaults to environment variable ${Colors.value(config.env.client_id)})`,
55
+ secret: true,
56
+ default: config.client_id
57
+ }
58
+ }),
59
+ ...(config.suppress?.clientSecret
60
+ ? {}
61
+ : {
62
+ clientSecret: {
63
+ description: `OAuth 2.0 client secret (defaults to environment variable ${Colors.value(config.env.client_secret)}`,
64
+ secret: true,
65
+ default: config.client_secret
66
+ }
67
+ }),
68
+ ...(config.suppress?.redirectUri
69
+ ? {}
70
+ : {
71
+ redirectUri: {
72
+ description: `OAuth 2.0 redirect URI (must be to host ${Colors.url('localhost')}, defaults to environment variables ${Colors.value(config.env.redirect_uri)})`,
73
+ hint: Colors.quotedValue(`"${config.redirect_uri}"`),
74
+ default: config.redirect_uri
75
+ }
76
+ }),
77
+ ...(config.suppress?.authorizationEndpoint
78
+ ? {}
79
+ : {
80
+ authorizationEndpoint: {
81
+ description: `OAuth 2.0 authorization endpoint (defaults to environment variable ${Colors.value(config.env.authorization_endpoint)}`,
82
+ default: config.authorization_endpoint
83
+ }
84
+ }),
85
+ ...(config.suppress?.tokenEndpoint
86
+ ? {}
87
+ : {
88
+ tokenEndpoint: {
89
+ description: `OAuth 2.0 token endpoint (will fall back to authorization endpoint if not provided, defaults to environment variable ${Colors.value(config.env.token_endpoint)}`,
90
+ default: config.token_endpoint
91
+ }
92
+ }),
93
+ ...(config.suppress?.tokenPath
94
+ ? {}
95
+ : {
96
+ tokenPath: {
97
+ description: `Path to token storage JSON file (defaults to environent variable ${Colors.value(config.env.token_path)}`,
98
+ default: config.token_path
99
+ }
100
+ })
50
101
  }
51
102
  };
52
103
  }
53
- export function init(args) {
54
- const { values: { clientId: client_id = process.env.CLIENT_ID, clientSecret: client_secret = process.env.CLIENT_SECRET, redirectUri: redirect_uri = process.env.REDIRECT_URI, authorizationEndpoint: authorization_endpoint = process.env
55
- .AUTHORIZATION_ENDPOINT, tokenEndpoint: token_endpoint = process.env.TOKEN_ENDPOINT, tokenPath: token_path = process.env.TOKEN_PATH } } = args;
104
+ export async function init(args) {
105
+ const { values: { clientId: client_id = await Env.get({
106
+ key: config.env.client_id
107
+ }), clientSecret: client_secret = await Env.get({
108
+ key: config.env.client_secret
109
+ }), redirectUri: redirect_uri = await Env.get({
110
+ key: config.env.redirect_uri
111
+ }), authorizationEndpoint: authorization_endpoint = await Env.get({
112
+ key: config.env.authorization_endpoint
113
+ }), tokenEndpoint: token_endpoint = await Env.get({
114
+ key: config.env.token_endpoint
115
+ }), tokenPath: token_path = await Env.get({ key: config.env.token_path }) } } = args;
56
116
  configure({
57
117
  client_id,
58
118
  client_secret,
@@ -64,6 +124,7 @@ export function init(args) {
64
124
  }
65
125
  function getClient() {
66
126
  if (!client) {
127
+ const { client_id, client_secret, redirect_uri, authorization_endpoint, token_endpoint, store } = config;
67
128
  if (!client_id) {
68
129
  throw new Error('OAuth 2.0 client ID not defined');
69
130
  }
@@ -94,5 +155,5 @@ export async function request(url, method = 'GET', body, headers, options) {
94
155
  return await getClient().request(url, method, body, headers, options);
95
156
  }
96
157
  export async function requestJSON(url, method = 'GET', body, headers, options) {
97
- return await getClient().requestJSON(url, method, body, headers, options);
158
+ return (await getClient().requestJSON(url, method, body, headers, options));
98
159
  }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  import * as OAuth2 from './OAuth2CLI.js';
2
+ export * from './EnvironmentStorage.js';
2
3
  export { OAuth2 };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- import { register } from '@battis/qui-cli.plugin';
1
+ import { register } from '@qui-cli/plugin';
2
2
  import * as OAuth2 from './OAuth2CLI.js';
3
- await register(OAuth2);
3
+ export * from './EnvironmentStorage.js';
4
4
  export { OAuth2 };
5
+ await register(OAuth2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oauth2-cli/qui-cli-plugin",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "@battis/qui-cli.plugin wrapper for oauth2-cli",
5
5
  "homepage": "https://github.com/battis/oauth2-cli/tree/main/packages/qui-cli-plugin#readme",
6
6
  "repository": {
@@ -16,26 +16,26 @@
16
16
  "main": "./dist/index.js",
17
17
  "types": "./dist/index.d.ts",
18
18
  "dependencies": {
19
- "openid-client": "^6.8.0",
20
- "oauth2-cli": "0.2.1"
19
+ "openid-client": "^6.8.1",
20
+ "oauth2-cli": "0.2.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@battis/descriptive-types": "^0.2.3",
24
- "@battis/qui-cli.colors": "^2.1.0",
25
- "@battis/qui-cli.env": "^2.1.2",
26
- "@battis/qui-cli.plugin": "^2.4.2",
27
- "@battis/qui-cli.root": "^2.0.5",
28
- "@tsconfig/node20": "^20.1.6",
29
- "commit-and-tag-version": "^12.6.0",
23
+ "@battis/descriptive-types": "^0.2.6",
24
+ "@qui-cli/colors": "^3.1.1",
25
+ "@qui-cli/env-1password": "^1.2.0",
26
+ "@qui-cli/plugin": "^4.0.0",
27
+ "@qui-cli/root": "^3.0.4",
28
+ "@tsconfig/node20": "^20.1.8",
29
+ "commit-and-tag-version": "^12.6.1",
30
30
  "del-cli": "^6.0.0",
31
31
  "npm-run-all": "^4.1.5",
32
- "typescript": "^5.9.2"
32
+ "typescript": "^5.9.3"
33
33
  },
34
34
  "peerDependencies": {
35
- "@battis/qui-cli.colors": "^2.0",
36
- "@battis/qui-cli.env": "^2.0",
37
- "@battis/qui-cli.plugin": "^2.2",
38
- "@battis/qui-cli.root": "^2.0"
35
+ "@qui-cli/colors": "3.x",
36
+ "@qui-cli/env-1password": "1.x",
37
+ "@qui-cli/plugin": "4.x",
38
+ "@qui-cli/root": "3.x"
39
39
  },
40
40
  "scripts": {
41
41
  "clean": "del ./dist",
package/.versionrc.json DELETED
@@ -1,5 +0,0 @@
1
- {
2
- "path": ".",
3
- "tag-prefix": "qui-cli-plugin/",
4
- "releaseCommitMessageFormat": "chore(qui-cli-plugin): @oauth2-cli/qui-cli-plugin@{{currentTag}}"
5
- }
package/src/OAuth2CLI.ts DELETED
@@ -1,144 +0,0 @@
1
- import { PathString, URLString } from '@battis/descriptive-types';
2
- import { Colors } from '@battis/qui-cli.colors';
3
- import '@battis/qui-cli.env';
4
- import * as Plugin from '@battis/qui-cli.plugin';
5
- import { Root } from '@battis/qui-cli.root';
6
- import path from 'node:path';
7
- import * as OAuth2 from 'oauth2-cli';
8
- import * as OpenIDClient from 'openid-client';
9
-
10
- export type Configuration = Plugin.Configuration & {
11
- client_id?: string;
12
- client_secret?: string;
13
- redirect_uri?: URLString;
14
- authorization_endpoint?: URLString;
15
- token_endpoint?: URLString;
16
- store?: OAuth2.TokenStorage;
17
- token_path?: PathString;
18
- };
19
-
20
- export const name = '@oauth2-cli/qui-cli-plugin';
21
- export const src = import.meta.dirname;
22
-
23
- let client_id: string | undefined = undefined;
24
- let client_secret: string | undefined = undefined;
25
- let redirect_uri: URLString | undefined = undefined;
26
- let authorization_endpoint: URLString | undefined = undefined;
27
- let token_endpoint: URLString | undefined = undefined;
28
- let store: OAuth2.TokenStorage | undefined = undefined;
29
- let client: OAuth2.Client | undefined = undefined;
30
-
31
- export function configure(config: Configuration = {}) {
32
- client_id = Plugin.hydrate(config.client_id, client_id);
33
- client_secret = Plugin.hydrate(config.client_secret, client_secret);
34
- redirect_uri = Plugin.hydrate(config.redirect_uri, redirect_uri);
35
- authorization_endpoint = Plugin.hydrate(
36
- config.authorization_endpoint,
37
- authorization_endpoint
38
- );
39
- token_endpoint = Plugin.hydrate(config.token_endpoint, token_endpoint);
40
- if (config.store) {
41
- store = config.store;
42
- } else if (config.token_path) {
43
- store = new OAuth2.FileStorage(
44
- path.resolve(Root.path(), config.token_path)
45
- );
46
- }
47
- }
48
-
49
- export function options(): Plugin.Options {
50
- return {
51
- opt: {
52
- clientId: {
53
- description: `OAuth 2.0 client ID (defaults to environment variable ${Colors.value('CLIENT_ID')})`
54
- },
55
- clientSecret: {
56
- description: `OAuth 2.0 client secret (defaults to environment variable ${Colors.value('CLIENT_SECRET')}`
57
- },
58
- redirectUri: {
59
- description: `OAuth 2.0 redirect URI (must be to host ${Colors.url('localhost')}, e.g. ${Colors.quotedValue(`"http://localhost:3000/oauth2/redirect"`)}, defaults to environment variables ${Colors.value('REDIRECT_URI')})`
60
- },
61
- authorizationEndpoint: {
62
- description: `OAuth 2.0 authorization endpoint (defaults to environment variable ${Colors.value('AUTHORIZATION_ENDPOINT')}`
63
- },
64
- tokenEndpoint: {
65
- description: `OAuth 2.0 token endpoint (will fall back to authorization endpoint if not provided, defaults to environment variable ${Colors.value('TOKEN_ENDPOINT')}`
66
- },
67
- tokenPath: {
68
- description: `Path to token storage JSON file (defaults to environent variable ${Colors.value('TOKEN_PATH')}`
69
- }
70
- }
71
- };
72
- }
73
-
74
- export function init(args: Plugin.ExpectedArguments<typeof options>) {
75
- const {
76
- values: {
77
- clientId: client_id = process.env.CLIENT_ID,
78
- clientSecret: client_secret = process.env.CLIENT_SECRET,
79
- redirectUri: redirect_uri = process.env.REDIRECT_URI,
80
- authorizationEndpoint: authorization_endpoint = process.env
81
- .AUTHORIZATION_ENDPOINT,
82
- tokenEndpoint: token_endpoint = process.env.TOKEN_ENDPOINT,
83
- tokenPath: token_path = process.env.TOKEN_PATH
84
- }
85
- } = args;
86
- configure({
87
- client_id,
88
- client_secret,
89
- redirect_uri,
90
- authorization_endpoint,
91
- token_endpoint,
92
- token_path
93
- });
94
- }
95
-
96
- function getClient() {
97
- if (!client) {
98
- if (!client_id) {
99
- throw new Error('OAuth 2.0 client ID not defined');
100
- }
101
- if (!client_secret) {
102
- throw new Error('OAuth 2.0 client secret not defined');
103
- }
104
- if (!redirect_uri) {
105
- throw new Error('OAuth 2.0 redirect URI not defined');
106
- }
107
- if (!authorization_endpoint) {
108
- throw new Error('OAuth 2.0 authorization endpoint not defined');
109
- }
110
- client = new OAuth2.Client({
111
- client_id,
112
- client_secret,
113
- redirect_uri,
114
- authorization_endpoint,
115
- token_endpoint,
116
- store
117
- });
118
- }
119
- return client;
120
- }
121
-
122
- export async function getToken() {
123
- return await getClient().getToken();
124
- }
125
-
126
- export async function request(
127
- url: URL | string,
128
- method: string = 'GET',
129
- body?: OpenIDClient.FetchBody,
130
- headers?: Record<string, string>,
131
- options?: OpenIDClient.DPoPOptions
132
- ) {
133
- return await getClient().request(url, method, body, headers, options);
134
- }
135
-
136
- export async function requestJSON(
137
- url: URL | string,
138
- method: string = 'GET',
139
- body?: OpenIDClient.FetchBody,
140
- headers?: Record<string, string>,
141
- options?: OpenIDClient.DPoPOptions
142
- ) {
143
- return await getClient().requestJSON(url, method, body, headers, options);
144
- }
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- import { register } from '@battis/qui-cli.plugin';
2
- import * as OAuth2 from './OAuth2CLI.js';
3
-
4
- await register(OAuth2);
5
- export { OAuth2 };
package/tsconfig.json DELETED
@@ -1,8 +0,0 @@
1
- {
2
- "extends": "@tsconfig/node20/tsconfig.json",
3
- "compilerOptions": {
4
- "declaration": true,
5
- "outDir": "./dist"
6
- },
7
- "include": ["./src"]
8
- }