linear-sdk-cli 0.2.4 → 0.3.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 +36 -16
- package/MIGRATING.md +7 -6
- package/README.md +120 -31
- package/package.json +5 -3
- package/skills/linear-sdk-cli/SKILL.md +43 -8
- package/skills/linear-sdk-cli/references/api.md +1 -1
- package/skills/linear-sdk-cli/references/attachment.md +1 -1
- package/skills/linear-sdk-cli/references/auth.md +26 -7
- package/skills/linear-sdk-cli/references/commands.md +1 -1
- package/skills/linear-sdk-cli/references/comment.md +1 -1
- package/skills/linear-sdk-cli/references/completion.md +1 -1
- package/skills/linear-sdk-cli/references/config.md +5 -1
- package/skills/linear-sdk-cli/references/cycle.md +1 -1
- package/skills/linear-sdk-cli/references/document.md +1 -1
- package/skills/linear-sdk-cli/references/favorite.md +1 -1
- package/skills/linear-sdk-cli/references/initiative-update.md +1 -1
- package/skills/linear-sdk-cli/references/initiative.md +1 -1
- package/skills/linear-sdk-cli/references/issue.md +1 -1
- package/skills/linear-sdk-cli/references/label.md +1 -1
- package/skills/linear-sdk-cli/references/milestone.md +1 -1
- package/skills/linear-sdk-cli/references/notification.md +1 -1
- package/skills/linear-sdk-cli/references/open.md +1 -1
- package/skills/linear-sdk-cli/references/organization.md +1 -1
- package/skills/linear-sdk-cli/references/project-update.md +1 -1
- package/skills/linear-sdk-cli/references/project.md +1 -1
- package/skills/linear-sdk-cli/references/roadmap.md +1 -1
- package/skills/linear-sdk-cli/references/schema.md +1 -1
- package/skills/linear-sdk-cli/references/state.md +1 -1
- package/skills/linear-sdk-cli/references/team.md +1 -1
- package/skills/linear-sdk-cli/references/user.md +1 -1
- package/skills/linear-sdk-cli/references/webhook.md +1 -1
- package/skills/linear-sdk-cli/references/whoami.md +1 -1
- package/skills/linear-sdk-cli/scripts/generate-docs.ts +3 -1
- package/src/client.ts +57 -2
- package/src/commands/meta.ts +240 -65
- package/src/config.ts +319 -16
- package/src/context.ts +2 -0
- package/src/index.ts +19 -0
- package/src/lib/introspect.ts +1 -0
- package/src/lib/options.ts +1 -0
- package/src/lib/output-shapes.ts +21 -2
- package/src/oauth.ts +582 -0
|
@@ -6,7 +6,7 @@ Group alias: `iu`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear initiative-update --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear initiative-update`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `init`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear initiative --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear initiative`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `i`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear issue --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear issue`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `lb`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear label --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear label`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `m`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear milestone --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear milestone`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `notif`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear notification --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear notification`
|
|
12
12
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
_Generated from `linear commands --json`. `linear open --help` (or `<subcommand> --help`) is authoritative._
|
|
6
6
|
|
|
7
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
7
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
8
8
|
|
|
9
9
|
### `linear open`
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@ Group alias: `org`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear organization --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear organization`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `pu`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear project-update --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear project-update`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `p`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear project --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear project`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `rm`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear roadmap --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear roadmap`
|
|
12
12
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
_Generated from `linear commands --json`. `linear schema --help` (or `<subcommand> --help`) is authoritative._
|
|
6
6
|
|
|
7
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
7
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
8
8
|
|
|
9
9
|
### `linear schema`
|
|
10
10
|
|
|
@@ -6,7 +6,7 @@ Group alias: `st`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear state --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear state`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `t`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear team --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear team`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `u`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear user --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear user`
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ Group alias: `wh`
|
|
|
6
6
|
|
|
7
7
|
_Generated from `linear commands --json`. `linear webhook --help` (or `<subcommand> --help`) is authoritative._
|
|
8
8
|
|
|
9
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
9
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
10
10
|
|
|
11
11
|
### `linear webhook`
|
|
12
12
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
_Generated from `linear commands --json`. `linear whoami --help` (or `<subcommand> --help`) is authoritative._
|
|
6
6
|
|
|
7
|
-
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
7
|
+
Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, `-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, `-t/--team <key>`, `-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), and `--debug`. Only command-specific options are listed below.
|
|
8
8
|
|
|
9
9
|
### `linear whoami`
|
|
10
10
|
|
|
@@ -66,6 +66,7 @@ const GLOBAL_OPTIONS = new Map([
|
|
|
66
66
|
["-j, --json", "output machine-readable JSON"],
|
|
67
67
|
["--no-ansi", "disable colored output"],
|
|
68
68
|
["--api-key <key>", "Linear API key (overrides env/config)"],
|
|
69
|
+
["--access-token <token>", "Linear OAuth access token (overrides env/config)"],
|
|
69
70
|
["--workspace <slug>", "select workspace credential profile"],
|
|
70
71
|
["-t, --team <key>", "default team key (e.g. TES)"],
|
|
71
72
|
["-n, --limit <n>", "max results (positive integer; 0 = all)"],
|
|
@@ -229,7 +230,8 @@ function buildReference(group: string, commands: CliCommand[]): string {
|
|
|
229
230
|
lines.push("");
|
|
230
231
|
lines.push(
|
|
231
232
|
"Every command also accepts the global flags `-j/--json`, `--no-input`, `-y/--yes`, " +
|
|
232
|
-
"`-q/--quiet`, `--workspace <slug>`, `--api-key <key>`,
|
|
233
|
+
"`-q/--quiet`, `--workspace <slug>`, `--api-key <key>`, `--access-token <token>`, " +
|
|
234
|
+
"`-t/--team <key>`, " +
|
|
233
235
|
"`-n/--limit <n>`, `--all`, `-f/--fields <a,b,c>`, `--no-ansi` (alias `--no-color`), " +
|
|
234
236
|
"and `--debug`. " +
|
|
235
237
|
"Only command-specific options are listed below.",
|
package/src/client.ts
CHANGED
|
@@ -3,21 +3,76 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { LinearClient } from "@linear/sdk";
|
|
6
|
-
import type
|
|
6
|
+
import { rotateOAuthCredential, type ResolvedConfig } from "./config.js";
|
|
7
|
+
import { OAuthUserTokenProvider } from "./oauth.js";
|
|
7
8
|
import { authError, normalizeError, CliError } from "./lib/errors.js";
|
|
8
9
|
|
|
9
10
|
export function createClient(config: ResolvedConfig): LinearClient {
|
|
11
|
+
if (config.oauthCredential) {
|
|
12
|
+
return createRefreshingOAuthClient(config);
|
|
13
|
+
}
|
|
14
|
+
if (config.accessToken) {
|
|
15
|
+
return new LinearClient({ accessToken: config.accessToken });
|
|
16
|
+
}
|
|
10
17
|
if (!config.apiKey) {
|
|
11
18
|
// Surface the precise credential-selection error (ambiguous / unstored
|
|
12
19
|
// workspace) only now, when a client is actually required.
|
|
13
20
|
throw (
|
|
14
21
|
config.apiKeyError ??
|
|
15
|
-
authError(
|
|
22
|
+
authError(
|
|
23
|
+
"No Linear credential found. Set LINEAR_ACCESS_TOKEN or LINEAR_API_KEY, pass --access-token or --api-key, or run `linear auth login`.",
|
|
24
|
+
)
|
|
16
25
|
);
|
|
17
26
|
}
|
|
18
27
|
return new LinearClient({ apiKey: config.apiKey });
|
|
19
28
|
}
|
|
20
29
|
|
|
30
|
+
function isAuthenticationFailure(err: unknown): boolean {
|
|
31
|
+
const value = err as Record<string, any> | undefined;
|
|
32
|
+
const status = value?.status ?? value?.response?.status ?? value?.raw?.response?.status;
|
|
33
|
+
if (status === 401) return true;
|
|
34
|
+
const errors = value?.response?.errors ?? value?.errors ?? value?.raw?.response?.errors;
|
|
35
|
+
return (
|
|
36
|
+
Array.isArray(errors) &&
|
|
37
|
+
errors.some((item) => {
|
|
38
|
+
const type = `${item?.extensions?.type ?? ""} ${item?.extensions?.code ?? ""}`;
|
|
39
|
+
const message = `${item?.message ?? ""}`;
|
|
40
|
+
return (
|
|
41
|
+
/^(?:authentication(?:error)?|unauthorized|invalidtoken|invalid_token)$/i.test(
|
|
42
|
+
type.trim(),
|
|
43
|
+
) ||
|
|
44
|
+
/authentication (?:failed|required)|unauthori[sz]ed|invalid (?:access )?token|token (?:expired|invalid)/i.test(
|
|
45
|
+
message,
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
})
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** SDK client whose request boundary refreshes stored PKCE credentials before expiry and once on 401. */
|
|
53
|
+
function createRefreshingOAuthClient(config: ResolvedConfig): LinearClient {
|
|
54
|
+
const credential = config.oauthCredential!;
|
|
55
|
+
const provider = new OAuthUserTokenProvider({
|
|
56
|
+
credential,
|
|
57
|
+
persist: (previous, next) => rotateOAuthCredential(credential.workspace.urlKey, previous, next),
|
|
58
|
+
});
|
|
59
|
+
const client = new LinearClient({ accessToken: credential.accessToken });
|
|
60
|
+
const original = client.client.request.bind(client.client);
|
|
61
|
+
client.client.request = async (document, variables, requestHeaders) => {
|
|
62
|
+
const accessToken = await provider.getAccessToken();
|
|
63
|
+
client.client.setHeader("Authorization", `Bearer ${accessToken}`);
|
|
64
|
+
try {
|
|
65
|
+
return await original(document, variables, requestHeaders);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
if (!isAuthenticationFailure(err)) throw err;
|
|
68
|
+
const replacement = await provider.getAccessToken({ forceRefresh: true });
|
|
69
|
+
client.client.setHeader("Authorization", `Bearer ${replacement}`);
|
|
70
|
+
return original(document, variables, requestHeaders);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
return client;
|
|
74
|
+
}
|
|
75
|
+
|
|
21
76
|
/**
|
|
22
77
|
* The longest single wait `withRetry` will honour. Linear's request quota
|
|
23
78
|
* resets hourly, so a `Retry-After` can be in the thousands of seconds; a CLI
|